From 84e819220468e989a0dde33bf1121888c5e749b1 Mon Sep 17 00:00:00 2001 From: Sachin Kamat Date: Mon, 4 Mar 2013 09:59:00 +0530 Subject: serial: tegra: Convert to devm_ioremap_resource() Use the newly introduced devm_ioremap_resource() instead of devm_request_and_ioremap() which provides more consistent error handling. devm_ioremap_resource() provides its own error messages; so all explicit error messages can be removed from the failure code paths. Signed-off-by: Sachin Kamat Reviewed-by: Thierry Reding Cc: Laxman Dewangan Signed-off-by: Greg Kroah-Hartman --- drivers/tty/serial/serial-tegra.c | 9 ++++----- 1 file changed, 4 insertions(+), 5 deletions(-) (limited to 'drivers/tty/serial') diff --git a/drivers/tty/serial/serial-tegra.c b/drivers/tty/serial/serial-tegra.c index 372de8a..9799d04 100644 --- a/drivers/tty/serial/serial-tegra.c +++ b/drivers/tty/serial/serial-tegra.c @@ -26,6 +26,7 @@ #include #include #include +#include #include #include #include @@ -1301,11 +1302,9 @@ static int tegra_uart_probe(struct platform_device *pdev) } u->mapbase = resource->start; - u->membase = devm_request_and_ioremap(&pdev->dev, resource); - if (!u->membase) { - dev_err(&pdev->dev, "memregion/iomap address req failed\n"); - return -EADDRNOTAVAIL; - } + u->membase = devm_ioremap_resource(&pdev->dev, resource); + if (IS_ERR(u->membase)) + return PTR_ERR(u->membase); tup->uart_clk = devm_clk_get(&pdev->dev, NULL); if (IS_ERR(tup->uart_clk)) { -- cgit v1.1 From 82b231323e419dcd61de9ff38d66dd7e82564594 Mon Sep 17 00:00:00 2001 From: Sachin Kamat Date: Mon, 4 Mar 2013 14:24:39 +0530 Subject: serial: vt8500_serial: Convert to devm_ioremap_resource() Use the newly introduced devm_ioremap_resource() instead of devm_request_and_ioremap() which provides more consistent error handling. Signed-off-by: Sachin Kamat Acked-by: Tony Prisk Reviewed-by: Thierry Reding Signed-off-by: Greg Kroah-Hartman --- drivers/tty/serial/vt8500_serial.c | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) (limited to 'drivers/tty/serial') diff --git a/drivers/tty/serial/vt8500_serial.c b/drivers/tty/serial/vt8500_serial.c index a3f9dd5..f15f53f 100644 --- a/drivers/tty/serial/vt8500_serial.c +++ b/drivers/tty/serial/vt8500_serial.c @@ -35,6 +35,7 @@ #include #include #include +#include /* * UART Register offsets @@ -585,9 +586,9 @@ static int vt8500_serial_probe(struct platform_device *pdev) if (!vt8500_port) return -ENOMEM; - vt8500_port->uart.membase = devm_request_and_ioremap(&pdev->dev, mmres); - if (!vt8500_port->uart.membase) - return -EADDRNOTAVAIL; + vt8500_port->uart.membase = devm_ioremap_resource(&pdev->dev, mmres); + if (IS_ERR(vt8500_port->uart.membase)) + return PTR_ERR(vt8500_port->uart.membase); vt8500_port->clk = of_clk_get(pdev->dev.of_node, 0); if (IS_ERR(vt8500_port->clk)) { -- cgit v1.1 From ef44d28c4fd94166ec6be054359ae26ba73b0291 Mon Sep 17 00:00:00 2001 From: Liang Li Date: Tue, 5 Mar 2013 22:30:38 +0800 Subject: serial: pch_uart: add console poll support Implement console poll for pch_uart, this could enable KGDBoC when on pch-uart console. Signed-off-by: Liang Li Acked-by: Jason Wessel Signed-off-by: Greg Kroah-Hartman --- drivers/tty/serial/pch_uart.c | 103 ++++++++++++++++++++++++++++++++---------- 1 file changed, 79 insertions(+), 24 deletions(-) (limited to 'drivers/tty/serial') diff --git a/drivers/tty/serial/pch_uart.c b/drivers/tty/serial/pch_uart.c index 7a6c989..21a7e17 100644 --- a/drivers/tty/serial/pch_uart.c +++ b/drivers/tty/serial/pch_uart.c @@ -1493,29 +1493,6 @@ static int pch_uart_verify_port(struct uart_port *port, return 0; } -static struct uart_ops pch_uart_ops = { - .tx_empty = pch_uart_tx_empty, - .set_mctrl = pch_uart_set_mctrl, - .get_mctrl = pch_uart_get_mctrl, - .stop_tx = pch_uart_stop_tx, - .start_tx = pch_uart_start_tx, - .stop_rx = pch_uart_stop_rx, - .enable_ms = pch_uart_enable_ms, - .break_ctl = pch_uart_break_ctl, - .startup = pch_uart_startup, - .shutdown = pch_uart_shutdown, - .set_termios = pch_uart_set_termios, -/* .pm = pch_uart_pm, Not supported yet */ -/* .set_wake = pch_uart_set_wake, Not supported yet */ - .type = pch_uart_type, - .release_port = pch_uart_release_port, - .request_port = pch_uart_request_port, - .config_port = pch_uart_config_port, - .verify_port = pch_uart_verify_port -}; - -#ifdef CONFIG_SERIAL_PCH_UART_CONSOLE - /* * Wait for transmitter & holding register to empty */ @@ -1547,6 +1524,84 @@ static void wait_for_xmitr(struct eg20t_port *up, int bits) } } +#ifdef CONFIG_CONSOLE_POLL +/* + * Console polling routines for communicate via uart while + * in an interrupt or debug context. + */ +static int pch_uart_get_poll_char(struct uart_port *port) +{ + struct eg20t_port *priv = + container_of(port, struct eg20t_port, port); + u8 lsr = ioread8(priv->membase + UART_LSR); + + if (!(lsr & UART_LSR_DR)) + return NO_POLL_CHAR; + + return ioread8(priv->membase + PCH_UART_RBR); +} + + +static void pch_uart_put_poll_char(struct uart_port *port, + unsigned char c) +{ + unsigned int ier; + struct eg20t_port *priv = + container_of(port, struct eg20t_port, port); + + /* + * First save the IER then disable the interrupts + */ + ier = ioread8(priv->membase + UART_IER); + pch_uart_hal_disable_interrupt(priv, PCH_UART_HAL_ALL_INT); + + wait_for_xmitr(priv, UART_LSR_THRE); + /* + * Send the character out. + * If a LF, also do CR... + */ + iowrite8(c, priv->membase + PCH_UART_THR); + if (c == 10) { + wait_for_xmitr(priv, UART_LSR_THRE); + iowrite8(13, priv->membase + PCH_UART_THR); + } + + /* + * Finally, wait for transmitter to become empty + * and restore the IER + */ + wait_for_xmitr(priv, BOTH_EMPTY); + iowrite8(ier, priv->membase + UART_IER); +} +#endif /* CONFIG_CONSOLE_POLL */ + +static struct uart_ops pch_uart_ops = { + .tx_empty = pch_uart_tx_empty, + .set_mctrl = pch_uart_set_mctrl, + .get_mctrl = pch_uart_get_mctrl, + .stop_tx = pch_uart_stop_tx, + .start_tx = pch_uart_start_tx, + .stop_rx = pch_uart_stop_rx, + .enable_ms = pch_uart_enable_ms, + .break_ctl = pch_uart_break_ctl, + .startup = pch_uart_startup, + .shutdown = pch_uart_shutdown, + .set_termios = pch_uart_set_termios, +/* .pm = pch_uart_pm, Not supported yet */ +/* .set_wake = pch_uart_set_wake, Not supported yet */ + .type = pch_uart_type, + .release_port = pch_uart_release_port, + .request_port = pch_uart_request_port, + .config_port = pch_uart_config_port, + .verify_port = pch_uart_verify_port, +#ifdef CONFIG_CONSOLE_POLL + .poll_get_char = pch_uart_get_poll_char, + .poll_put_char = pch_uart_put_poll_char, +#endif +}; + +#ifdef CONFIG_SERIAL_PCH_UART_CONSOLE + static void pch_console_putchar(struct uart_port *port, int ch) { struct eg20t_port *priv = @@ -1655,7 +1710,7 @@ static struct console pch_console = { #define PCH_CONSOLE (&pch_console) #else #define PCH_CONSOLE NULL -#endif +#endif /* CONFIG_SERIAL_PCH_UART_CONSOLE */ static struct uart_driver pch_uart_driver = { .owner = THIS_MODULE, -- cgit v1.1 From b1622e0ac1b18632cff1e9af807fcdcb2397071b Mon Sep 17 00:00:00 2001 From: Jiri Slaby Date: Thu, 7 Mar 2013 13:12:25 +0100 Subject: TTY: jsm, remove superfluous check data_len in jsm_input cannot be zero as we would jump out early in the function. It also cannot be negative because it is an int and we do bitwise and with 8192. So remove the check. Signed-off-by: Jiri Slaby Cc: Lucas Tavares Signed-off-by: Greg Kroah-Hartman --- drivers/tty/serial/jsm/jsm_tty.c | 6 ------ 1 file changed, 6 deletions(-) (limited to 'drivers/tty/serial') diff --git a/drivers/tty/serial/jsm/jsm_tty.c b/drivers/tty/serial/jsm/jsm_tty.c index 00f250a..27bb750 100644 --- a/drivers/tty/serial/jsm/jsm_tty.c +++ b/drivers/tty/serial/jsm/jsm_tty.c @@ -596,12 +596,6 @@ void jsm_input(struct jsm_channel *ch) jsm_dbg(READ, &ch->ch_bd->pci_dev, "start 2\n"); - if (data_len <= 0) { - spin_unlock_irqrestore(&ch->ch_lock, lock_flags); - jsm_dbg(READ, &ch->ch_bd->pci_dev, "jsm_input 1\n"); - return; - } - len = tty_buffer_request_room(port, data_len); n = len; -- cgit v1.1 From 6982a398426a22166eaf049b79544536fdd6429f Mon Sep 17 00:00:00 2001 From: Jiri Slaby Date: Thu, 7 Mar 2013 13:12:28 +0100 Subject: TTY: msm_smd_tty, clean up activate/shutdown Do not dig struct smd_tty_info out of tty_struct using tty_port_tty_get. It is unnecessarily too complicated, use simple container_of instead. Signed-off-by: Jiri Slaby Signed-off-by: Greg Kroah-Hartman --- drivers/tty/serial/msm_smd_tty.c | 14 +++++--------- 1 file changed, 5 insertions(+), 9 deletions(-) (limited to 'drivers/tty/serial') diff --git a/drivers/tty/serial/msm_smd_tty.c b/drivers/tty/serial/msm_smd_tty.c index e722ff1..1238ac3 100644 --- a/drivers/tty/serial/msm_smd_tty.c +++ b/drivers/tty/serial/msm_smd_tty.c @@ -90,13 +90,13 @@ static void smd_tty_notify(void *priv, unsigned event) static int smd_tty_port_activate(struct tty_port *tport, struct tty_struct *tty) { + struct smd_tty_info *info = container_of(tport, struct smd_tty_info, + port); int i, res = 0; - int n = tty->index; const char *name = NULL; - struct smd_tty_info *info = smd_tty + n; for (i = 0; i < smd_tty_channels_len; i++) { - if (smd_tty_channels[i].id == n) { + if (smd_tty_channels[i].id == tty->index) { name = smd_tty_channels[i].name; break; } @@ -117,17 +117,13 @@ static int smd_tty_port_activate(struct tty_port *tport, struct tty_struct *tty) static void smd_tty_port_shutdown(struct tty_port *tport) { - struct smd_tty_info *info; - struct tty_struct *tty = tty_port_tty_get(tport); + struct smd_tty_info *info = container_of(tport, struct smd_tty_info, + port); - info = tty->driver_data; if (info->ch) { smd_close(info->ch); info->ch = 0; } - - tty->driver_data = 0; - tty_kref_put(tty); } static int smd_tty_open(struct tty_struct *tty, struct file *f) -- cgit v1.1 From 6aad04f21374633bd8cecf25024553d1e11a9522 Mon Sep 17 00:00:00 2001 From: Jiri Slaby Date: Thu, 7 Mar 2013 13:12:29 +0100 Subject: TTY: add tty_port_tty_wakeup helper It allows for cleaning up on a considerable amount of places. They did port_get, wakeup, kref_put. Now the only thing needed is to call tty_port_tty_wakeup which does exactly that. One exception is ifx6x60 where tty_wakeup was open-coded. We now call tty_wakeup properly there. Signed-off-by: Jiri Slaby Signed-off-by: Greg Kroah-Hartman --- drivers/tty/serial/ifx6x60.c | 33 ++------------------------------- 1 file changed, 2 insertions(+), 31 deletions(-) (limited to 'drivers/tty/serial') diff --git a/drivers/tty/serial/ifx6x60.c b/drivers/tty/serial/ifx6x60.c index 68d7ce99..d723d41 100644 --- a/drivers/tty/serial/ifx6x60.c +++ b/drivers/tty/serial/ifx6x60.c @@ -443,25 +443,6 @@ static void ifx_spi_setup_spi_header(unsigned char *txbuffer, int tx_count, } /** - * ifx_spi_wakeup_serial - SPI space made - * @port_data: our SPI device - * - * We have emptied the FIFO enough that we want to get more data - * queued into it. Poke the line discipline via tty_wakeup so that - * it will feed us more bits - */ -static void ifx_spi_wakeup_serial(struct ifx_spi_device *ifx_dev) -{ - struct tty_struct *tty; - - tty = tty_port_tty_get(&ifx_dev->tty_port); - if (!tty) - return; - tty_wakeup(tty); - tty_kref_put(tty); -} - -/** * ifx_spi_prepare_tx_buffer - prepare transmit frame * @ifx_dev: our SPI device * @@ -506,7 +487,7 @@ static int ifx_spi_prepare_tx_buffer(struct ifx_spi_device *ifx_dev) tx_count += temp_count; if (temp_count == queue_length) /* poke port to get more data */ - ifx_spi_wakeup_serial(ifx_dev); + tty_port_tty_wakeup(&ifx_dev->tty_port); else /* more data in port, use next SPI message */ ifx_dev->spi_more = 1; } @@ -683,8 +664,6 @@ static void ifx_spi_insert_flip_string(struct ifx_spi_device *ifx_dev, static void ifx_spi_complete(void *ctx) { struct ifx_spi_device *ifx_dev = ctx; - struct tty_struct *tty; - struct tty_ldisc *ldisc = NULL; int length; int actual_length; unsigned char more; @@ -762,15 +741,7 @@ complete_exit: */ ifx_spi_power_state_clear(ifx_dev, IFX_SPI_POWER_DATA_PENDING); - tty = tty_port_tty_get(&ifx_dev->tty_port); - if (tty) { - ldisc = tty_ldisc_ref(tty); - if (ldisc) { - ldisc->ops->write_wakeup(tty); - tty_ldisc_deref(ldisc); - } - tty_kref_put(tty); - } + tty_port_tty_wakeup(&ifx_dev->tty_port); } } } -- cgit v1.1 From aa27a094e2c2e0cc59914e56113b860f524f4479 Mon Sep 17 00:00:00 2001 From: Jiri Slaby Date: Thu, 7 Mar 2013 13:12:30 +0100 Subject: TTY: add tty_port_tty_hangup helper It allows for cleaning up on a considerable amount of places. They did port_get, hangup, kref_put. Now the only thing needed is to call tty_port_tty_hangup which does exactly that. And they can also decide whether to consider CLOCAL or completely ignore that. Signed-off-by: Jiri Slaby Signed-off-by: Greg Kroah-Hartman --- drivers/tty/serial/ifx6x60.c | 21 ++------------------- 1 file changed, 2 insertions(+), 19 deletions(-) (limited to 'drivers/tty/serial') diff --git a/drivers/tty/serial/ifx6x60.c b/drivers/tty/serial/ifx6x60.c index d723d41..2c77fed 100644 --- a/drivers/tty/serial/ifx6x60.c +++ b/drivers/tty/serial/ifx6x60.c @@ -270,23 +270,6 @@ static void mrdy_assert(struct ifx_spi_device *ifx_dev) } /** - * ifx_spi_hangup - hang up an IFX device - * @ifx_dev: our SPI device - * - * Hang up the tty attached to the IFX device if one is currently - * open. If not take no action - */ -static void ifx_spi_ttyhangup(struct ifx_spi_device *ifx_dev) -{ - struct tty_port *pport = &ifx_dev->tty_port; - struct tty_struct *tty = tty_port_tty_get(pport); - if (tty) { - tty_hangup(tty); - tty_kref_put(tty); - } -} - -/** * ifx_spi_timeout - SPI timeout * @arg: our SPI device * @@ -298,7 +281,7 @@ static void ifx_spi_timeout(unsigned long arg) struct ifx_spi_device *ifx_dev = (struct ifx_spi_device *)arg; dev_warn(&ifx_dev->spi_dev->dev, "*** SPI Timeout ***"); - ifx_spi_ttyhangup(ifx_dev); + tty_port_tty_hangup(&ifx_dev->tty_port, false); mrdy_set_low(ifx_dev); clear_bit(IFX_SPI_STATE_TIMER_PENDING, &ifx_dev->flags); } @@ -933,7 +916,7 @@ static irqreturn_t ifx_spi_reset_interrupt(int irq, void *dev) set_bit(MR_INPROGRESS, &ifx_dev->mdm_reset_state); if (!solreset) { /* unsolicited reset */ - ifx_spi_ttyhangup(ifx_dev); + tty_port_tty_hangup(&ifx_dev->tty_port, false); } } else { /* exited reset */ -- cgit v1.1 From e99c33b9d3abfbba5ff34a16579a8e0a9e3211c4 Mon Sep 17 00:00:00 2001 From: Jiri Slaby Date: Thu, 7 Mar 2013 13:12:32 +0100 Subject: TTY: serial/bfin_uart, unbreak build with KGDB enabled There are no (and never were any) kgdb fields in uart_ops. Setting them produces a build error: drivers/tty/serial/bfin_uart.c:1054:2: error: unknown field 'kgdboc_port_startup' specified in initializer drivers/tty/serial/bfin_uart.c:1054:2: warning: initialization from incompatible pointer type [enabled by default] drivers/tty/serial/bfin_uart.c:1054:2: warning: (near initialization for 'bfin_serial_pops.ioctl') [enabled by default] drivers/tty/serial/bfin_uart.c:1055:2: error: unknown field 'kgdboc_port_shutdown' specified in initializer drivers/tty/serial/bfin_uart.c:1055:2: warning: initialization from incompatible pointer type [enabled by default] drivers/tty/serial/bfin_uart.c:1055:2: warning: (near initialization for 'bfin_serial_pops.poll_init') [enabled by default] Remove them. Signed-off-by: Jiri Slaby Acked-by: Sonic Zhang Signed-off-by: Greg Kroah-Hartman --- drivers/tty/serial/bfin_uart.c | 23 ----------------------- 1 file changed, 23 deletions(-) (limited to 'drivers/tty/serial') diff --git a/drivers/tty/serial/bfin_uart.c b/drivers/tty/serial/bfin_uart.c index 12dceda..26a3be7 100644 --- a/drivers/tty/serial/bfin_uart.c +++ b/drivers/tty/serial/bfin_uart.c @@ -1011,24 +1011,6 @@ static int bfin_serial_poll_get_char(struct uart_port *port) } #endif -#if defined(CONFIG_KGDB_SERIAL_CONSOLE) || \ - defined(CONFIG_KGDB_SERIAL_CONSOLE_MODULE) -static void bfin_kgdboc_port_shutdown(struct uart_port *port) -{ - if (kgdboc_break_enabled) { - kgdboc_break_enabled = 0; - bfin_serial_shutdown(port); - } -} - -static int bfin_kgdboc_port_startup(struct uart_port *port) -{ - kgdboc_port_line = port->line; - kgdboc_break_enabled = !bfin_serial_startup(port); - return 0; -} -#endif - static struct uart_ops bfin_serial_pops = { .tx_empty = bfin_serial_tx_empty, .set_mctrl = bfin_serial_set_mctrl, @@ -1047,11 +1029,6 @@ static struct uart_ops bfin_serial_pops = { .request_port = bfin_serial_request_port, .config_port = bfin_serial_config_port, .verify_port = bfin_serial_verify_port, -#if defined(CONFIG_KGDB_SERIAL_CONSOLE) || \ - defined(CONFIG_KGDB_SERIAL_CONSOLE_MODULE) - .kgdboc_port_startup = bfin_kgdboc_port_startup, - .kgdboc_port_shutdown = bfin_kgdboc_port_shutdown, -#endif #ifdef CONFIG_CONSOLE_POLL .poll_put_char = bfin_serial_poll_put_char, .poll_get_char = bfin_serial_poll_get_char, -- cgit v1.1 From 4d29994ddb4cc97e19a533834df2e0fdb1c1d8a8 Mon Sep 17 00:00:00 2001 From: Jiri Slaby Date: Thu, 7 Mar 2013 13:12:33 +0100 Subject: TTY: serial/msm_serial_hs, remove unused tty Signed-off-by: Jiri Slaby Signed-off-by: Greg Kroah-Hartman --- drivers/tty/serial/msm_serial_hs.c | 2 -- 1 file changed, 2 deletions(-) (limited to 'drivers/tty/serial') diff --git a/drivers/tty/serial/msm_serial_hs.c b/drivers/tty/serial/msm_serial_hs.c index 4a942c7..4ca2f64 100644 --- a/drivers/tty/serial/msm_serial_hs.c +++ b/drivers/tty/serial/msm_serial_hs.c @@ -907,7 +907,6 @@ static void msm_hs_dmov_rx_callback(struct msm_dmov_cmd *cmd_ptr, unsigned int error_f = 0; unsigned long flags; unsigned int flush; - struct tty_struct *tty; struct tty_port *port; struct uart_port *uport; struct msm_hs_port *msm_uport; @@ -919,7 +918,6 @@ static void msm_hs_dmov_rx_callback(struct msm_dmov_cmd *cmd_ptr, clk_enable(msm_uport->clk); port = &uport->state->port; - tty = port->tty; msm_hs_write(uport, UARTDM_CR_ADDR, STALE_EVENT_DISABLE); -- cgit v1.1 From ee7970690568b0c875467f475d9c957ec0d9e099 Mon Sep 17 00:00:00 2001 From: Jiri Slaby Date: Thu, 7 Mar 2013 13:12:34 +0100 Subject: TTY: cleanup tty->hw_stopped uses tty->hw_stopped is set only by drivers to remember HW state. If it is never set to 1 in a particular driver, there is no need to check it in the driver at all. Remove such checks. Signed-off-by: Jiri Slaby Signed-off-by: Greg Kroah-Hartman --- drivers/tty/serial/68328serial.c | 9 +++------ drivers/tty/serial/arc_uart.c | 2 +- drivers/tty/serial/crisv10.c | 12 ++---------- 3 files changed, 6 insertions(+), 17 deletions(-) (limited to 'drivers/tty/serial') diff --git a/drivers/tty/serial/68328serial.c b/drivers/tty/serial/68328serial.c index 4939947..ef2e08e 100644 --- a/drivers/tty/serial/68328serial.c +++ b/drivers/tty/serial/68328serial.c @@ -630,8 +630,7 @@ static void rs_flush_chars(struct tty_struct *tty) /* Enable transmitter */ local_irq_save(flags); - if (info->xmit_cnt <= 0 || tty->stopped || tty->hw_stopped || - !info->xmit_buf) { + if (info->xmit_cnt <= 0 || tty->stopped || !info->xmit_buf) { local_irq_restore(flags); return; } @@ -697,7 +696,7 @@ static int rs_write(struct tty_struct * tty, total += c; } - if (info->xmit_cnt && !tty->stopped && !tty->hw_stopped) { + if (info->xmit_cnt && !tty->stopped) { /* Enable transmitter */ local_irq_disable(); #ifndef USE_INTS @@ -978,10 +977,8 @@ static void rs_set_termios(struct tty_struct *tty, struct ktermios *old_termios) change_speed(info, tty); if ((old_termios->c_cflag & CRTSCTS) && - !(tty->termios.c_cflag & CRTSCTS)) { - tty->hw_stopped = 0; + !(tty->termios.c_cflag & CRTSCTS)) rs_start(tty); - } } diff --git a/drivers/tty/serial/arc_uart.c b/drivers/tty/serial/arc_uart.c index d97e194..cbf1d15 100644 --- a/drivers/tty/serial/arc_uart.c +++ b/drivers/tty/serial/arc_uart.c @@ -162,7 +162,7 @@ static unsigned int arc_serial_tx_empty(struct uart_port *port) /* * Driver internal routine, used by both tty(serial core) as well as tx-isr * -Called under spinlock in either cases - * -also tty->stopped / tty->hw_stopped has already been checked + * -also tty->stopped has already been checked * = by uart_start( ) before calling us * = tx_ist checks that too before calling */ diff --git a/drivers/tty/serial/crisv10.c b/drivers/tty/serial/crisv10.c index 5f37c31..50f56f3 100644 --- a/drivers/tty/serial/crisv10.c +++ b/drivers/tty/serial/crisv10.c @@ -2534,8 +2534,7 @@ static void handle_ser_tx_interrupt(struct e100_serial *info) } /* Normal char-by-char interrupt */ if (info->xmit.head == info->xmit.tail - || info->port.tty->stopped - || info->port.tty->hw_stopped) { + || info->port.tty->stopped) { DFLOW(DEBUG_LOG(info->line, "tx_int: stopped %i\n", info->port.tty->stopped)); e100_disable_serial_tx_ready_irq(info); @@ -3098,7 +3097,6 @@ rs_flush_chars(struct tty_struct *tty) if (info->tr_running || info->xmit.head == info->xmit.tail || tty->stopped || - tty->hw_stopped || !info->xmit.buf) return; @@ -3176,7 +3174,6 @@ static int rs_raw_write(struct tty_struct *tty, if (info->xmit.head != info->xmit.tail && !tty->stopped && - !tty->hw_stopped && !info->tr_running) { start_transmit(info); } @@ -3733,10 +3730,8 @@ rs_set_termios(struct tty_struct *tty, struct ktermios *old_termios) /* Handle turning off CRTSCTS */ if ((old_termios->c_cflag & CRTSCTS) && - !(tty->termios.c_cflag & CRTSCTS)) { - tty->hw_stopped = 0; + !(tty->termios.c_cflag & CRTSCTS)) rs_start(tty); - } } @@ -4256,9 +4251,6 @@ static void seq_line_info(struct seq_file *m, struct e100_serial *info) if (info->port.tty->stopped) seq_printf(m, " stopped:%i", (int)info->port.tty->stopped); - if (info->port.tty->hw_stopped) - seq_printf(m, " hw_stopped:%i", - (int)info->port.tty->hw_stopped); } { -- cgit v1.1 From b1d984cf7d6b7d4e395f1aa6a0a4d3d1ecf21495 Mon Sep 17 00:00:00 2001 From: Jiri Slaby Date: Thu, 7 Mar 2013 13:12:36 +0100 Subject: crisv10: use flags from tty_port First, remove STD_FLAGS as the value, or its subvalues (ASYNC_BOOT_AUTOCONF | ASYNC_SKIP_TEST) is not tested anywhere -- there is no point to initialize flags to that. Second, use flags member from tty_port when we have it now. So that we do not waste space. Signed-off-by: Jiri Slaby Signed-off-by: Greg Kroah-Hartman --- drivers/tty/serial/crisv10.c | 64 ++++++++++++++++++++------------------------ drivers/tty/serial/crisv10.h | 2 -- 2 files changed, 29 insertions(+), 37 deletions(-) (limited to 'drivers/tty/serial') diff --git a/drivers/tty/serial/crisv10.c b/drivers/tty/serial/crisv10.c index 50f56f3..2ae378c 100644 --- a/drivers/tty/serial/crisv10.c +++ b/drivers/tty/serial/crisv10.c @@ -169,7 +169,6 @@ static int get_lsr_info(struct e100_serial *info, unsigned int *value); #define DEF_BAUD 115200 /* 115.2 kbit/s */ -#define STD_FLAGS (ASYNC_BOOT_AUTOCONF | ASYNC_SKIP_TEST) #define DEF_RX 0x20 /* or SERIAL_CTRL_W >> 8 */ /* Default value of tx_ctrl register: has txd(bit 7)=1 (idle) as default */ #define DEF_TX 0x80 /* or SERIAL_CTRL_B */ @@ -246,7 +245,6 @@ static struct e100_serial rs_table[] = { .ifirstadr = R_DMA_CH7_FIRST, .icmdadr = R_DMA_CH7_CMD, .idescradr = R_DMA_CH7_DESCR, - .flags = STD_FLAGS, .rx_ctrl = DEF_RX, .tx_ctrl = DEF_TX, .iseteop = 2, @@ -300,7 +298,6 @@ static struct e100_serial rs_table[] = { .ifirstadr = R_DMA_CH9_FIRST, .icmdadr = R_DMA_CH9_CMD, .idescradr = R_DMA_CH9_DESCR, - .flags = STD_FLAGS, .rx_ctrl = DEF_RX, .tx_ctrl = DEF_TX, .iseteop = 3, @@ -356,7 +353,6 @@ static struct e100_serial rs_table[] = { .ifirstadr = R_DMA_CH3_FIRST, .icmdadr = R_DMA_CH3_CMD, .idescradr = R_DMA_CH3_DESCR, - .flags = STD_FLAGS, .rx_ctrl = DEF_RX, .tx_ctrl = DEF_TX, .iseteop = 0, @@ -410,7 +406,6 @@ static struct e100_serial rs_table[] = { .ifirstadr = R_DMA_CH5_FIRST, .icmdadr = R_DMA_CH5_CMD, .idescradr = R_DMA_CH5_DESCR, - .flags = STD_FLAGS, .rx_ctrl = DEF_RX, .tx_ctrl = DEF_TX, .iseteop = 1, @@ -2721,7 +2716,7 @@ startup(struct e100_serial * info) /* if it was already initialized, skip this */ - if (info->flags & ASYNC_INITIALIZED) { + if (info->port.flags & ASYNC_INITIALIZED) { local_irq_restore(flags); free_page(xmit_page); return 0; @@ -2846,7 +2841,7 @@ startup(struct e100_serial * info) #endif /* CONFIG_SVINTO_SIM */ - info->flags |= ASYNC_INITIALIZED; + info->port.flags |= ASYNC_INITIALIZED; local_irq_restore(flags); return 0; @@ -2891,7 +2886,7 @@ shutdown(struct e100_serial * info) #endif /* CONFIG_SVINTO_SIM */ - if (!(info->flags & ASYNC_INITIALIZED)) + if (!(info->port.flags & ASYNC_INITIALIZED)) return; #ifdef SERIAL_DEBUG_OPEN @@ -2922,7 +2917,7 @@ shutdown(struct e100_serial * info) if (info->port.tty) set_bit(TTY_IO_ERROR, &info->port.tty->flags); - info->flags &= ~ASYNC_INITIALIZED; + info->port.flags &= ~ASYNC_INITIALIZED; local_irq_restore(flags); } @@ -2947,7 +2942,7 @@ change_speed(struct e100_serial *info) /* possibly, the tx/rx should be disabled first to do this safely */ /* change baud-rate and write it to the hardware */ - if ((info->flags & ASYNC_SPD_MASK) == ASYNC_SPD_CUST) { + if ((info->port.flags & ASYNC_SPD_MASK) == ASYNC_SPD_CUST) { /* Special baudrate */ u32 mask = 0xFF << (info->line*8); /* Each port has 8 bits */ unsigned long alt_source = @@ -3397,7 +3392,7 @@ get_serial_info(struct e100_serial * info, tmp.line = info->line; tmp.port = (int)info->ioport; tmp.irq = info->irq; - tmp.flags = info->flags; + tmp.flags = info->port.flags; tmp.baud_base = info->baud_base; tmp.close_delay = info->close_delay; tmp.closing_wait = info->closing_wait; @@ -3424,9 +3419,9 @@ set_serial_info(struct e100_serial *info, if ((new_serial.type != info->type) || (new_serial.close_delay != info->close_delay) || ((new_serial.flags & ~ASYNC_USR_MASK) != - (info->flags & ~ASYNC_USR_MASK))) + (info->port.flags & ~ASYNC_USR_MASK))) return -EPERM; - info->flags = ((info->flags & ~ASYNC_USR_MASK) | + info->port.flags = ((info->port.flags & ~ASYNC_USR_MASK) | (new_serial.flags & ASYNC_USR_MASK)); goto check_and_exit; } @@ -3440,16 +3435,16 @@ set_serial_info(struct e100_serial *info, */ info->baud_base = new_serial.baud_base; - info->flags = ((info->flags & ~ASYNC_FLAGS) | + info->port.flags = ((info->port.flags & ~ASYNC_FLAGS) | (new_serial.flags & ASYNC_FLAGS)); info->custom_divisor = new_serial.custom_divisor; info->type = new_serial.type; info->close_delay = new_serial.close_delay; info->closing_wait = new_serial.closing_wait; - info->port.low_latency = (info->flags & ASYNC_LOW_LATENCY) ? 1 : 0; + info->port.low_latency = (info->port.flags & ASYNC_LOW_LATENCY) ? 1 : 0; check_and_exit: - if (info->flags & ASYNC_INITIALIZED) { + if (info->port.flags & ASYNC_INITIALIZED) { change_speed(info); } else retval = startup(info); @@ -3789,12 +3784,12 @@ rs_close(struct tty_struct *tty, struct file * filp) local_irq_restore(flags); return; } - info->flags |= ASYNC_CLOSING; + info->port.flags |= ASYNC_CLOSING; /* * Save the termios structure, since this port may have * separate termios for callout and dialin. */ - if (info->flags & ASYNC_NORMAL_ACTIVE) + if (info->port.flags & ASYNC_NORMAL_ACTIVE) info->normal_termios = tty->termios; /* * Now we wait for the transmit buffer to clear; and we notify @@ -3815,7 +3810,7 @@ rs_close(struct tty_struct *tty, struct file * filp) e100_disable_rx(info); e100_disable_rx_irq(info); - if (info->flags & ASYNC_INITIALIZED) { + if (info->port.flags & ASYNC_INITIALIZED) { /* * Before we drop DTR, make sure the UART transmitter * has completely drained; this is especially @@ -3836,7 +3831,7 @@ rs_close(struct tty_struct *tty, struct file * filp) schedule_timeout_interruptible(info->close_delay); wake_up_interruptible(&info->open_wait); } - info->flags &= ~(ASYNC_NORMAL_ACTIVE|ASYNC_CLOSING); + info->port.flags &= ~(ASYNC_NORMAL_ACTIVE|ASYNC_CLOSING); wake_up_interruptible(&info->close_wait); local_irq_restore(flags); @@ -3931,7 +3926,7 @@ rs_hangup(struct tty_struct *tty) shutdown(info); info->event = 0; info->count = 0; - info->flags &= ~ASYNC_NORMAL_ACTIVE; + info->port.flags &= ~ASYNC_NORMAL_ACTIVE; info->port.tty = NULL; wake_up_interruptible(&info->open_wait); } @@ -3955,11 +3950,11 @@ block_til_ready(struct tty_struct *tty, struct file * filp, * until it's done, and then try again. */ if (tty_hung_up_p(filp) || - (info->flags & ASYNC_CLOSING)) { + (info->port.flags & ASYNC_CLOSING)) { wait_event_interruptible_tty(tty, info->close_wait, - !(info->flags & ASYNC_CLOSING)); + !(info->port.flags & ASYNC_CLOSING)); #ifdef SERIAL_DO_RESTART - if (info->flags & ASYNC_HUP_NOTIFY) + if (info->port.flags & ASYNC_HUP_NOTIFY) return -EAGAIN; else return -ERESTARTSYS; @@ -3974,7 +3969,7 @@ block_til_ready(struct tty_struct *tty, struct file * filp, */ if ((filp->f_flags & O_NONBLOCK) || (tty->flags & (1 << TTY_IO_ERROR))) { - info->flags |= ASYNC_NORMAL_ACTIVE; + info->port.flags |= ASYNC_NORMAL_ACTIVE; return 0; } @@ -4010,9 +4005,9 @@ block_til_ready(struct tty_struct *tty, struct file * filp, local_irq_restore(flags); set_current_state(TASK_INTERRUPTIBLE); if (tty_hung_up_p(filp) || - !(info->flags & ASYNC_INITIALIZED)) { + !(info->port.flags & ASYNC_INITIALIZED)) { #ifdef SERIAL_DO_RESTART - if (info->flags & ASYNC_HUP_NOTIFY) + if (info->port.flags & ASYNC_HUP_NOTIFY) retval = -EAGAIN; else retval = -ERESTARTSYS; @@ -4021,7 +4016,7 @@ block_til_ready(struct tty_struct *tty, struct file * filp, #endif break; } - if (!(info->flags & ASYNC_CLOSING) && do_clocal) + if (!(info->port.flags & ASYNC_CLOSING) && do_clocal) /* && (do_clocal || DCD_IS_ASSERTED) */ break; if (signal_pending(current)) { @@ -4047,7 +4042,7 @@ block_til_ready(struct tty_struct *tty, struct file * filp, #endif if (retval) return retval; - info->flags |= ASYNC_NORMAL_ACTIVE; + info->port.flags |= ASYNC_NORMAL_ACTIVE; return 0; } @@ -4088,17 +4083,17 @@ rs_open(struct tty_struct *tty, struct file * filp) tty->driver_data = info; info->port.tty = tty; - info->port.low_latency = !!(info->flags & ASYNC_LOW_LATENCY); + info->port.low_latency = !!(info->port.flags & ASYNC_LOW_LATENCY); /* * If the port is in the middle of closing, bail out now */ if (tty_hung_up_p(filp) || - (info->flags & ASYNC_CLOSING)) { + (info->port.flags & ASYNC_CLOSING)) { wait_event_interruptible_tty(tty, info->close_wait, - !(info->flags & ASYNC_CLOSING)); + !(info->port.flags & ASYNC_CLOSING)); #ifdef SERIAL_DO_RESTART - return ((info->flags & ASYNC_HUP_NOTIFY) ? + return ((info->port.flags & ASYNC_HUP_NOTIFY) ? -EAGAIN : -ERESTARTSYS); #else return -EAGAIN; @@ -4198,7 +4193,7 @@ rs_open(struct tty_struct *tty, struct file * filp) return retval; } - if ((info->count == 1) && (info->flags & ASYNC_SPLIT_TERMIOS)) { + if ((info->count == 1) && (info->port.flags & ASYNC_SPLIT_TERMIOS)) { tty->termios = info->normal_termios; change_speed(info); } @@ -4447,7 +4442,6 @@ static int __init rs_init(void) info->forced_eop = 0; info->baud_base = DEF_BAUD_BASE; info->custom_divisor = 0; - info->flags = 0; info->close_delay = 5*HZ/10; info->closing_wait = 30*HZ; info->x_char = 0; diff --git a/drivers/tty/serial/crisv10.h b/drivers/tty/serial/crisv10.h index ea0beb46..7146ed2 100644 --- a/drivers/tty/serial/crisv10.h +++ b/drivers/tty/serial/crisv10.h @@ -53,8 +53,6 @@ struct e100_serial { volatile u8 *icmdadr; /* adr to R_DMA_CHx_CMD */ volatile u32 *idescradr; /* adr to R_DMA_CHx_DESCR */ - int flags; /* defined in tty.h */ - u8 rx_ctrl; /* shadow for R_SERIALx_REC_CTRL */ u8 tx_ctrl; /* shadow for R_SERIALx_TR_CTRL */ u8 iseteop; /* bit number for R_SET_EOP for the input dma */ -- cgit v1.1 From 12aad550f005fef2dd0ad40e4978549f64f8f296 Mon Sep 17 00:00:00 2001 From: Jiri Slaby Date: Thu, 7 Mar 2013 13:12:35 +0100 Subject: crisv10: stop returning info from handle_ser_rx_interrupt The return value is not used anywhere, so no need to return anything. Signed-off-by: Jiri Slaby Signed-off-by: Greg Kroah-Hartman --- drivers/tty/serial/crisv10.c | 10 ++++------ 1 file changed, 4 insertions(+), 6 deletions(-) (limited to 'drivers/tty/serial') diff --git a/drivers/tty/serial/crisv10.c b/drivers/tty/serial/crisv10.c index 2ae378c..ec2dcc7 100644 --- a/drivers/tty/serial/crisv10.c +++ b/drivers/tty/serial/crisv10.c @@ -2258,8 +2258,7 @@ TODO: The break will be delayed until an F or V character is received. */ -static -struct e100_serial * handle_ser_rx_interrupt_no_dma(struct e100_serial *info) +static void handle_ser_rx_interrupt_no_dma(struct e100_serial *info) { unsigned long data_read; @@ -2365,10 +2364,9 @@ more_data: } tty_flip_buffer_push(&info->port); - return info; } -static struct e100_serial* handle_ser_rx_interrupt(struct e100_serial *info) +static void handle_ser_rx_interrupt(struct e100_serial *info) { unsigned char rstat; @@ -2377,7 +2375,8 @@ static struct e100_serial* handle_ser_rx_interrupt(struct e100_serial *info) #endif /* DEBUG_LOG(info->line, "ser_interrupt stat %03X\n", rstat | (i << 8)); */ if (!info->uses_dma_in) { - return handle_ser_rx_interrupt_no_dma(info); + handle_ser_rx_interrupt_no_dma(info); + return; } /* DMA is used */ rstat = info->ioport[REG_STATUS]; @@ -2484,7 +2483,6 @@ static struct e100_serial* handle_ser_rx_interrupt(struct e100_serial *info) /* Restarting the DMA never hurts */ *info->icmdadr = IO_STATE(R_DMA_CH6_CMD, cmd, restart); START_FLUSH_FAST_TIMER(info, "ser_int"); - return info; } /* handle_ser_rx_interrupt */ static void handle_ser_tx_interrupt(struct e100_serial *info) -- cgit v1.1 From 82c3b87b7e0153c5a05ac994cd5586df41264cb6 Mon Sep 17 00:00:00 2001 From: Jiri Slaby Date: Thu, 7 Mar 2013 13:12:37 +0100 Subject: crisv10: remove unused members Well, all those are unused. They were perhaps copied from generic serial structure ages ago. Remove them for good. Signed-off-by: Jiri Slaby Signed-off-by: Greg Kroah-Hartman --- drivers/tty/serial/crisv10.h | 6 ------ 1 file changed, 6 deletions(-) (limited to 'drivers/tty/serial') diff --git a/drivers/tty/serial/crisv10.h b/drivers/tty/serial/crisv10.h index 7146ed2..59f70c4 100644 --- a/drivers/tty/serial/crisv10.h +++ b/drivers/tty/serial/crisv10.h @@ -86,15 +86,10 @@ struct e100_serial { volatile int tr_running; /* 1 if output is running */ - struct tty_struct *tty; - int read_status_mask; - int ignore_status_mask; int x_char; /* xon/xoff character */ int close_delay; unsigned short closing_wait; - unsigned short closing_wait2; unsigned long event; - unsigned long last_active; int line; int type; /* PORT_ETRAX */ int count; /* # of fd on device */ @@ -108,7 +103,6 @@ struct e100_serial { struct work_struct work; struct async_icount icount; /* error-statistics etc.*/ struct ktermios normal_termios; - struct ktermios callout_termios; wait_queue_head_t open_wait; wait_queue_head_t close_wait; -- cgit v1.1 From 892c7cfc16f4379e04983f2b58cdfc35f486d269 Mon Sep 17 00:00:00 2001 From: Jiri Slaby Date: Thu, 7 Mar 2013 13:12:38 +0100 Subject: crisv10: use close delays from tty_port The same as flags, convert to using close delays from tty_port. Signed-off-by: Jiri Slaby Signed-off-by: Greg Kroah-Hartman --- drivers/tty/serial/crisv10.c | 20 +++++++++----------- drivers/tty/serial/crisv10.h | 2 -- 2 files changed, 9 insertions(+), 13 deletions(-) (limited to 'drivers/tty/serial') diff --git a/drivers/tty/serial/crisv10.c b/drivers/tty/serial/crisv10.c index ec2dcc7..0e75ec33 100644 --- a/drivers/tty/serial/crisv10.c +++ b/drivers/tty/serial/crisv10.c @@ -3392,8 +3392,8 @@ get_serial_info(struct e100_serial * info, tmp.irq = info->irq; tmp.flags = info->port.flags; tmp.baud_base = info->baud_base; - tmp.close_delay = info->close_delay; - tmp.closing_wait = info->closing_wait; + tmp.close_delay = info->port.close_delay; + tmp.closing_wait = info->port.closing_wait; tmp.custom_divisor = info->custom_divisor; if (copy_to_user(retinfo, &tmp, sizeof(*retinfo))) return -EFAULT; @@ -3415,7 +3415,7 @@ set_serial_info(struct e100_serial *info, if (!capable(CAP_SYS_ADMIN)) { if ((new_serial.type != info->type) || - (new_serial.close_delay != info->close_delay) || + (new_serial.close_delay != info->port.close_delay) || ((new_serial.flags & ~ASYNC_USR_MASK) != (info->port.flags & ~ASYNC_USR_MASK))) return -EPERM; @@ -3437,8 +3437,8 @@ set_serial_info(struct e100_serial *info, (new_serial.flags & ASYNC_FLAGS)); info->custom_divisor = new_serial.custom_divisor; info->type = new_serial.type; - info->close_delay = new_serial.close_delay; - info->closing_wait = new_serial.closing_wait; + info->port.close_delay = new_serial.close_delay; + info->port.closing_wait = new_serial.closing_wait; info->port.low_latency = (info->port.flags & ASYNC_LOW_LATENCY) ? 1 : 0; check_and_exit: @@ -3794,8 +3794,8 @@ rs_close(struct tty_struct *tty, struct file * filp) * the line discipline to only process XON/XOFF characters. */ tty->closing = 1; - if (info->closing_wait != ASYNC_CLOSING_WAIT_NONE) - tty_wait_until_sent(tty, info->closing_wait); + if (info->port.closing_wait != ASYNC_CLOSING_WAIT_NONE) + tty_wait_until_sent(tty, info->port.closing_wait); /* * At this point we stop accepting input. To do this, we * disable the serial receiver and the DMA receive interrupt. @@ -3825,8 +3825,8 @@ rs_close(struct tty_struct *tty, struct file * filp) info->event = 0; info->port.tty = NULL; if (info->blocked_open) { - if (info->close_delay) - schedule_timeout_interruptible(info->close_delay); + if (info->port.close_delay) + schedule_timeout_interruptible(info->port.close_delay); wake_up_interruptible(&info->open_wait); } info->port.flags &= ~(ASYNC_NORMAL_ACTIVE|ASYNC_CLOSING); @@ -4440,8 +4440,6 @@ static int __init rs_init(void) info->forced_eop = 0; info->baud_base = DEF_BAUD_BASE; info->custom_divisor = 0; - info->close_delay = 5*HZ/10; - info->closing_wait = 30*HZ; info->x_char = 0; info->event = 0; info->count = 0; diff --git a/drivers/tty/serial/crisv10.h b/drivers/tty/serial/crisv10.h index 59f70c4..a05c36b 100644 --- a/drivers/tty/serial/crisv10.h +++ b/drivers/tty/serial/crisv10.h @@ -87,8 +87,6 @@ struct e100_serial { volatile int tr_running; /* 1 if output is running */ int x_char; /* xon/xoff character */ - int close_delay; - unsigned short closing_wait; unsigned long event; int line; int type; /* PORT_ETRAX */ -- cgit v1.1 From 4aeaeb0c39c6d0cca78d829c4fe2042e0d8d595d Mon Sep 17 00:00:00 2001 From: Jiri Slaby Date: Thu, 7 Mar 2013 13:12:39 +0100 Subject: crisv10: use *_wait from tty_port The same as flags, convert to using *_wait queues from tty_port. Signed-off-by: Jiri Slaby Signed-off-by: Greg Kroah-Hartman --- drivers/tty/serial/crisv10.c | 16 +++++++--------- drivers/tty/serial/crisv10.h | 2 -- 2 files changed, 7 insertions(+), 11 deletions(-) (limited to 'drivers/tty/serial') diff --git a/drivers/tty/serial/crisv10.c b/drivers/tty/serial/crisv10.c index 0e75ec33..ef5bca1 100644 --- a/drivers/tty/serial/crisv10.c +++ b/drivers/tty/serial/crisv10.c @@ -3827,10 +3827,10 @@ rs_close(struct tty_struct *tty, struct file * filp) if (info->blocked_open) { if (info->port.close_delay) schedule_timeout_interruptible(info->port.close_delay); - wake_up_interruptible(&info->open_wait); + wake_up_interruptible(&info->port.open_wait); } info->port.flags &= ~(ASYNC_NORMAL_ACTIVE|ASYNC_CLOSING); - wake_up_interruptible(&info->close_wait); + wake_up_interruptible(&info->port.close_wait); local_irq_restore(flags); /* port closed */ @@ -3926,7 +3926,7 @@ rs_hangup(struct tty_struct *tty) info->count = 0; info->port.flags &= ~ASYNC_NORMAL_ACTIVE; info->port.tty = NULL; - wake_up_interruptible(&info->open_wait); + wake_up_interruptible(&info->port.open_wait); } /* @@ -3949,7 +3949,7 @@ block_til_ready(struct tty_struct *tty, struct file * filp, */ if (tty_hung_up_p(filp) || (info->port.flags & ASYNC_CLOSING)) { - wait_event_interruptible_tty(tty, info->close_wait, + wait_event_interruptible_tty(tty, info->port.close_wait, !(info->port.flags & ASYNC_CLOSING)); #ifdef SERIAL_DO_RESTART if (info->port.flags & ASYNC_HUP_NOTIFY) @@ -3983,7 +3983,7 @@ block_til_ready(struct tty_struct *tty, struct file * filp, * exit, either normal or abnormal. */ retval = 0; - add_wait_queue(&info->open_wait, &wait); + add_wait_queue(&info->port.open_wait, &wait); #ifdef SERIAL_DEBUG_OPEN printk("block_til_ready before block: ttyS%d, count = %d\n", info->line, info->count); @@ -4030,7 +4030,7 @@ block_til_ready(struct tty_struct *tty, struct file * filp, tty_lock(tty); } set_current_state(TASK_RUNNING); - remove_wait_queue(&info->open_wait, &wait); + remove_wait_queue(&info->port.open_wait, &wait); if (extra_count) info->count++; info->blocked_open--; @@ -4088,7 +4088,7 @@ rs_open(struct tty_struct *tty, struct file * filp) */ if (tty_hung_up_p(filp) || (info->port.flags & ASYNC_CLOSING)) { - wait_event_interruptible_tty(tty, info->close_wait, + wait_event_interruptible_tty(tty, info->port.close_wait, !(info->port.flags & ASYNC_CLOSING)); #ifdef SERIAL_DO_RESTART return ((info->port.flags & ASYNC_HUP_NOTIFY) ? @@ -4445,8 +4445,6 @@ static int __init rs_init(void) info->count = 0; info->blocked_open = 0; info->normal_termios = driver->init_termios; - init_waitqueue_head(&info->open_wait); - init_waitqueue_head(&info->close_wait); info->xmit.buf = NULL; info->xmit.tail = info->xmit.head = 0; info->first_recv_buffer = info->last_recv_buffer = NULL; diff --git a/drivers/tty/serial/crisv10.h b/drivers/tty/serial/crisv10.h index a05c36b..1cd2299 100644 --- a/drivers/tty/serial/crisv10.h +++ b/drivers/tty/serial/crisv10.h @@ -101,8 +101,6 @@ struct e100_serial { struct work_struct work; struct async_icount icount; /* error-statistics etc.*/ struct ktermios normal_termios; - wait_queue_head_t open_wait; - wait_queue_head_t close_wait; unsigned long char_time_usec; /* The time for 1 char, in usecs */ unsigned long flush_time_usec; /* How often we should flush */ -- cgit v1.1 From b12d8dc2dbe2d2d1d6eec314d586b1eed75756dc Mon Sep 17 00:00:00 2001 From: Jiri Slaby Date: Thu, 7 Mar 2013 13:12:40 +0100 Subject: crisv10: use counts from tty_port The same as flags, convert to using open/close counts from tty_port. Signed-off-by: Jiri Slaby Signed-off-by: Greg Kroah-Hartman --- drivers/tty/serial/crisv10.c | 48 +++++++++++++++++++++----------------------- drivers/tty/serial/crisv10.h | 2 -- 2 files changed, 23 insertions(+), 27 deletions(-) (limited to 'drivers/tty/serial') diff --git a/drivers/tty/serial/crisv10.c b/drivers/tty/serial/crisv10.c index ef5bca1..477f22f 100644 --- a/drivers/tty/serial/crisv10.c +++ b/drivers/tty/serial/crisv10.c @@ -3424,7 +3424,7 @@ set_serial_info(struct e100_serial *info, goto check_and_exit; } - if (info->count > 1) + if (info->port.count > 1) return -EBUSY; /* @@ -3760,7 +3760,7 @@ rs_close(struct tty_struct *tty, struct file * filp) printk("[%d] rs_close ttyS%d, count = %d\n", current->pid, info->line, info->count); #endif - if ((tty->count == 1) && (info->count != 1)) { + if ((tty->count == 1) && (info->port.count != 1)) { /* * Uh, oh. tty->count is 1, which means that the tty * structure will be freed. Info->count should always @@ -3770,15 +3770,15 @@ rs_close(struct tty_struct *tty, struct file * filp) */ printk(KERN_ERR "rs_close: bad serial port count; tty->count is 1, " - "info->count is %d\n", info->count); - info->count = 1; + "info->count is %d\n", info->port.count); + info->port.count = 1; } - if (--info->count < 0) { + if (--info->port.count < 0) { printk(KERN_ERR "rs_close: bad serial port count for ttyS%d: %d\n", - info->line, info->count); - info->count = 0; + info->line, info->port.count); + info->port.count = 0; } - if (info->count) { + if (info->port.count) { local_irq_restore(flags); return; } @@ -3824,7 +3824,7 @@ rs_close(struct tty_struct *tty, struct file * filp) tty->closing = 0; info->event = 0; info->port.tty = NULL; - if (info->blocked_open) { + if (info->port.blocked_open) { if (info->port.close_delay) schedule_timeout_interruptible(info->port.close_delay); wake_up_interruptible(&info->port.open_wait); @@ -3923,7 +3923,7 @@ rs_hangup(struct tty_struct *tty) rs_flush_buffer(tty); shutdown(info); info->event = 0; - info->count = 0; + info->port.count = 0; info->port.flags &= ~ASYNC_NORMAL_ACTIVE; info->port.tty = NULL; wake_up_interruptible(&info->port.open_wait); @@ -3978,7 +3978,7 @@ block_til_ready(struct tty_struct *tty, struct file * filp, /* * Block waiting for the carrier detect and the line to become * free (i.e., not in use by the callout). While we are in - * this loop, info->count is dropped by one, so that + * this loop, info->port.count is dropped by one, so that * rs_close() knows when to free things. We restore it upon * exit, either normal or abnormal. */ @@ -3986,15 +3986,15 @@ block_til_ready(struct tty_struct *tty, struct file * filp, add_wait_queue(&info->port.open_wait, &wait); #ifdef SERIAL_DEBUG_OPEN printk("block_til_ready before block: ttyS%d, count = %d\n", - info->line, info->count); + info->line, info->port.count); #endif local_irq_save(flags); if (!tty_hung_up_p(filp)) { extra_count++; - info->count--; + info->port.count--; } local_irq_restore(flags); - info->blocked_open++; + info->port.blocked_open++; while (1) { local_irq_save(flags); /* assert RTS and DTR */ @@ -4023,7 +4023,7 @@ block_til_ready(struct tty_struct *tty, struct file * filp, } #ifdef SERIAL_DEBUG_OPEN printk("block_til_ready blocking: ttyS%d, count = %d\n", - info->line, info->count); + info->line, info->port.count); #endif tty_unlock(tty); schedule(); @@ -4032,11 +4032,11 @@ block_til_ready(struct tty_struct *tty, struct file * filp, set_current_state(TASK_RUNNING); remove_wait_queue(&info->port.open_wait, &wait); if (extra_count) - info->count++; - info->blocked_open--; + info->port.count++; + info->port.blocked_open--; #ifdef SERIAL_DEBUG_OPEN printk("block_til_ready after blocking: ttyS%d, count = %d\n", - info->line, info->count); + info->line, info->port.count); #endif if (retval) return retval; @@ -4074,10 +4074,10 @@ rs_open(struct tty_struct *tty, struct file * filp) #ifdef SERIAL_DEBUG_OPEN printk("[%d] rs_open %s, count = %d\n", current->pid, tty->name, - info->count); + info->port.count); #endif - info->count++; + info->port.count++; tty->driver_data = info; info->port.tty = tty; @@ -4101,7 +4101,7 @@ rs_open(struct tty_struct *tty, struct file * filp) /* * If DMA is enabled try to allocate the irq's. */ - if (info->count == 1) { + if (info->port.count == 1) { allocated_resources = 1; if (info->dma_in_enabled) { if (request_irq(info->dma_in_irq_nbr, @@ -4174,7 +4174,7 @@ rs_open(struct tty_struct *tty, struct file * filp) if (allocated_resources) deinit_port(info); - /* FIXME Decrease count info->count here too? */ + /* FIXME Decrease count info->port.count here too? */ return retval; } @@ -4191,7 +4191,7 @@ rs_open(struct tty_struct *tty, struct file * filp) return retval; } - if ((info->count == 1) && (info->port.flags & ASYNC_SPLIT_TERMIOS)) { + if ((info->port.count == 1) && (info->port.flags & ASYNC_SPLIT_TERMIOS)) { tty->termios = info->normal_termios; change_speed(info); } @@ -4442,8 +4442,6 @@ static int __init rs_init(void) info->custom_divisor = 0; info->x_char = 0; info->event = 0; - info->count = 0; - info->blocked_open = 0; info->normal_termios = driver->init_termios; info->xmit.buf = NULL; info->xmit.tail = info->xmit.head = 0; diff --git a/drivers/tty/serial/crisv10.h b/drivers/tty/serial/crisv10.h index 1cd2299..7599014 100644 --- a/drivers/tty/serial/crisv10.h +++ b/drivers/tty/serial/crisv10.h @@ -90,8 +90,6 @@ struct e100_serial { unsigned long event; int line; int type; /* PORT_ETRAX */ - int count; /* # of fd on device */ - int blocked_open; /* # of blocked opens */ struct circ_buf xmit; struct etrax_recv_buffer *first_recv_buffer; struct etrax_recv_buffer *last_recv_buffer; -- cgit v1.1 From c47ddc26db389e046c1414c78ac4a6016c7df500 Mon Sep 17 00:00:00 2001 From: Lars-Peter Clausen Date: Mon, 11 Mar 2013 18:44:49 +0100 Subject: tty: max3100: Use dev_pm_ops Use dev_pm_ops instead of the deprecated legacy suspend/resume for the max3100 driver. Signed-off-by: Lars-Peter Clausen Signed-off-by: Greg Kroah-Hartman --- drivers/tty/serial/max3100.c | 20 ++++++++++---------- 1 file changed, 10 insertions(+), 10 deletions(-) (limited to 'drivers/tty/serial') diff --git a/drivers/tty/serial/max3100.c b/drivers/tty/serial/max3100.c index 32517d4..57da9bb 100644 --- a/drivers/tty/serial/max3100.c +++ b/drivers/tty/serial/max3100.c @@ -849,11 +849,11 @@ static int max3100_remove(struct spi_device *spi) return 0; } -#ifdef CONFIG_PM +#ifdef CONFIG_PM_SLEEP -static int max3100_suspend(struct spi_device *spi, pm_message_t state) +static int max3100_suspend(struct device *dev) { - struct max3100_port *s = dev_get_drvdata(&spi->dev); + struct max3100_port *s = dev_get_drvdata(dev); dev_dbg(&s->spi->dev, "%s\n", __func__); @@ -874,9 +874,9 @@ static int max3100_suspend(struct spi_device *spi, pm_message_t state) return 0; } -static int max3100_resume(struct spi_device *spi) +static int max3100_resume(struct device *dev) { - struct max3100_port *s = dev_get_drvdata(&spi->dev); + struct max3100_port *s = dev_get_drvdata(dev); dev_dbg(&s->spi->dev, "%s\n", __func__); @@ -894,21 +894,21 @@ static int max3100_resume(struct spi_device *spi) return 0; } +static SIMPLE_DEV_PM_OPS(max3100_pm_ops, max3100_suspend, max3100_resume); +#define MAX3100_PM_OPS (&max3100_pm_ops) + #else -#define max3100_suspend NULL -#define max3100_resume NULL +#define MAX3100_PM_OPS NULL #endif static struct spi_driver max3100_driver = { .driver = { .name = "max3100", .owner = THIS_MODULE, + .pm = MAX3100_PM_OPS, }, - .probe = max3100_probe, .remove = max3100_remove, - .suspend = max3100_suspend, - .resume = max3100_resume, }; module_spi_driver(max3100_driver); -- cgit v1.1 From b7df719db7326d51a3145bb0cfc277aeb50763c3 Mon Sep 17 00:00:00 2001 From: Lars-Peter Clausen Date: Mon, 11 Mar 2013 18:44:50 +0100 Subject: tty: max310x: Use dev_pm_ops Use dev_pm_ops instead of the deprecated legacy suspend/resume for the max310x driver. Cc: Alexander Shiyan Signed-off-by: Lars-Peter Clausen Signed-off-by: Greg Kroah-Hartman --- drivers/tty/serial/max310x.c | 24 ++++++++++++++++-------- 1 file changed, 16 insertions(+), 8 deletions(-) (limited to 'drivers/tty/serial') diff --git a/drivers/tty/serial/max310x.c b/drivers/tty/serial/max310x.c index 0c2422c..8941e64 100644 --- a/drivers/tty/serial/max310x.c +++ b/drivers/tty/serial/max310x.c @@ -881,12 +881,14 @@ static struct uart_ops max310x_ops = { .verify_port = max310x_verify_port, }; -static int max310x_suspend(struct spi_device *spi, pm_message_t state) +#ifdef CONFIG_PM_SLEEP + +static int max310x_suspend(struct device *dev) { int ret; - struct max310x_port *s = dev_get_drvdata(&spi->dev); + struct max310x_port *s = dev_get_drvdata(dev); - dev_dbg(&spi->dev, "Suspend\n"); + dev_dbg(dev, "Suspend\n"); ret = uart_suspend_port(&s->uart, &s->port); @@ -905,11 +907,11 @@ static int max310x_suspend(struct spi_device *spi, pm_message_t state) return ret; } -static int max310x_resume(struct spi_device *spi) +static int max310x_resume(struct device *dev) { - struct max310x_port *s = dev_get_drvdata(&spi->dev); + struct max310x_port *s = dev_get_drvdata(dev); - dev_dbg(&spi->dev, "Resume\n"); + dev_dbg(dev, "Resume\n"); if (s->pdata->suspend) s->pdata->suspend(0); @@ -928,6 +930,13 @@ static int max310x_resume(struct spi_device *spi) return uart_resume_port(&s->uart, &s->port); } +static SIMPLE_DEV_PM_OPS(max310x_pm_ops, max310x_suspend, max310x_resume); +#define MAX310X_PM_OPS (&max310x_pm_ops) + +#else +#define MAX310X_PM_OPS NULL +#endif + #ifdef CONFIG_GPIOLIB static int max310x_gpio_get(struct gpio_chip *chip, unsigned offset) { @@ -1242,11 +1251,10 @@ static struct spi_driver max310x_driver = { .driver = { .name = "max310x", .owner = THIS_MODULE, + .pm = MAX310X_PM_OPS, }, .probe = max310x_probe, .remove = max310x_remove, - .suspend = max310x_suspend, - .resume = max310x_resume, .id_table = max310x_id_table, }; module_spi_driver(max310x_driver); -- cgit v1.1 From c2ee91bd6644324160ba9e090e3a017d62abc0b4 Mon Sep 17 00:00:00 2001 From: Lars-Peter Clausen Date: Mon, 11 Mar 2013 18:44:51 +0100 Subject: tty: mrst_max3110: Use dev_pm_ops Use dev_pm_ops instead of the deprecated legacy suspend/resume for the mrst_max3110 driver. Cc: Alan Cox Signed-off-by: Lars-Peter Clausen Signed-off-by: Greg Kroah-Hartman --- drivers/tty/serial/mrst_max3110.c | 19 ++++++++++++------- 1 file changed, 12 insertions(+), 7 deletions(-) (limited to 'drivers/tty/serial') diff --git a/drivers/tty/serial/mrst_max3110.c b/drivers/tty/serial/mrst_max3110.c index f641c23..9b6ef20 100644 --- a/drivers/tty/serial/mrst_max3110.c +++ b/drivers/tty/serial/mrst_max3110.c @@ -743,9 +743,10 @@ static struct uart_driver serial_m3110_reg = { .cons = &serial_m3110_console, }; -#ifdef CONFIG_PM -static int serial_m3110_suspend(struct spi_device *spi, pm_message_t state) +#ifdef CONFIG_PM_SLEEP +static int serial_m3110_suspend(struct device *dev) { + struct spi_device *spi = to_spi_device(dev); struct uart_max3110 *max = spi_get_drvdata(spi); disable_irq(max->irq); @@ -754,8 +755,9 @@ static int serial_m3110_suspend(struct spi_device *spi, pm_message_t state) return 0; } -static int serial_m3110_resume(struct spi_device *spi) +static int serial_m3110_resume(struct device *dev) { + struct spi_device *spi = to_spi_device(dev); struct uart_max3110 *max = spi_get_drvdata(spi); max3110_out(max, max->cur_conf); @@ -763,9 +765,13 @@ static int serial_m3110_resume(struct spi_device *spi) enable_irq(max->irq); return 0; } + +static SIMPLE_DEV_PM_OPS(serial_m3110_pm_ops, serial_m3110_suspend, + serial_m3110_resume); +#define SERIAL_M3110_PM_OPS (&serial_m3110_pm_ops) + #else -#define serial_m3110_suspend NULL -#define serial_m3110_resume NULL +#define SERIAL_M3110_PM_OPS NULL #endif static int serial_m3110_probe(struct spi_device *spi) @@ -872,11 +878,10 @@ static struct spi_driver uart_max3110_driver = { .driver = { .name = "spi_max3111", .owner = THIS_MODULE, + .pm = SERIAL_M3110_PM_OPS, }, .probe = serial_m3110_probe, .remove = serial_m3110_remove, - .suspend = serial_m3110_suspend, - .resume = serial_m3110_resume, }; static int __init serial_m3110_init(void) -- cgit v1.1 From 91debb0383d6564e0dc8ae76181f6daf8e24717a Mon Sep 17 00:00:00 2001 From: Lars-Peter Clausen Date: Mon, 11 Mar 2013 18:44:52 +0100 Subject: tty: ifx6x60: Remove unused suspend/resume callbacks The ifx6x60 driver implements both legacy suspend/resume callbacks and dev_pm_ops. The SPI core is going to ignore legacy suspend/resume callbacks if a driver implements dev_pm_ops. Since the legacy suspend/resume callbacks are empty in this case it is safe to just remove them. Cc: Bi Chao Cc: Chen Jun Signed-off-by: Lars-Peter Clausen Signed-off-by: Greg Kroah-Hartman --- drivers/tty/serial/ifx6x60.c | 26 -------------------------- 1 file changed, 26 deletions(-) (limited to 'drivers/tty/serial') diff --git a/drivers/tty/serial/ifx6x60.c b/drivers/tty/serial/ifx6x60.c index 2c77fed..8b1534c 100644 --- a/drivers/tty/serial/ifx6x60.c +++ b/drivers/tty/serial/ifx6x60.c @@ -1279,30 +1279,6 @@ static void ifx_spi_spi_shutdown(struct spi_device *spi) */ /** - * ifx_spi_spi_suspend - suspend SPI on system suspend - * @dev: device being suspended - * - * Suspend the SPI side. No action needed on Intel MID platforms, may - * need extending for other systems. - */ -static int ifx_spi_spi_suspend(struct spi_device *spi, pm_message_t msg) -{ - return 0; -} - -/** - * ifx_spi_spi_resume - resume SPI side on system resume - * @dev: device being suspended - * - * Suspend the SPI side. No action needed on Intel MID platforms, may - * need extending for other systems. - */ -static int ifx_spi_spi_resume(struct spi_device *spi) -{ - return 0; -} - -/** * ifx_spi_pm_suspend - suspend modem on system suspend * @dev: device being suspended * @@ -1391,8 +1367,6 @@ static struct spi_driver ifx_spi_driver = { .probe = ifx_spi_spi_probe, .shutdown = ifx_spi_spi_shutdown, .remove = ifx_spi_spi_remove, - .suspend = ifx_spi_spi_suspend, - .resume = ifx_spi_spi_resume, .id_table = ifx_id_table }; -- cgit v1.1 From 7bbe08d6b89fce09ae4e6a7ce62ccd3c279a31ce Mon Sep 17 00:00:00 2001 From: Jiri Slaby Date: Thu, 14 Mar 2013 00:30:34 +0100 Subject: TTY: serial, stop accessing potential NULLs The following commits: * 6732c8bb8671acbdac6cdc93dd72ddd581dd5e25 (TTY: switch tty_schedule_flip) * 2e124b4a390ca85325fae75764bef92f0547fa25 (TTY: switch tty_flip_buffer_push) * 05c7cd39907184328f48d3e7899f9cdd653ad336 (TTY: switch tty_insert_flip_string) * 92a19f9cec9a80ad93c06e115822deb729e2c6ad (TTY: switch tty_insert_flip_char) * 227434f8986c3827a1faedd1feb437acd6285315 (TTY: switch tty_buffer_request_room to tty_port) introduced a potential NULL dereference to some drivers. In particular, when the device is used as a console, incoming bytes can kill the box. This is caused by removed checks for TTY against NULL. It happened because it was unclear to me why the checks were there. I assumed them superfluous because the interrupts were unbound or otherwise stopped. But this is not the case for consoles for these drivers, as was pointed out by David Miller. Now, this patch re-introduces the checks (at this point we check port->state, not the tty proper, as we do not care about tty pointers anymore). For both of the drivers, we place the check below the handling of break signal so that sysrq can actually work. (One needs to issue a break and then sysrq key within the following 5 seconds.) We do not change sc26xx, sunhv, and sunsu here because they behave the same as before. People having that hardware should fix the driver eventually, however. They always could unconditionally dereference tty in receive_chars, port->state in uart_handle_dcd_change, and up->port.state->port.tty. There is perhaps more to fix in all those drivers, but they are at least in a state they were before. Signed-off-by: Jiri Slaby Cc: "David S. Miller" Cc: Grant Likely Cc: Rob Herring Cc: sparclinux@vger.kernel.org Signed-off-by: Greg Kroah-Hartman --- drivers/tty/serial/sunsab.c | 2 +- drivers/tty/serial/sunzilog.c | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) (limited to 'drivers/tty/serial') diff --git a/drivers/tty/serial/sunsab.c b/drivers/tty/serial/sunsab.c index 8de2213..a422c8b 100644 --- a/drivers/tty/serial/sunsab.c +++ b/drivers/tty/serial/sunsab.c @@ -203,7 +203,7 @@ receive_chars(struct uart_sunsab_port *up, flag = TTY_FRAME; } - if (uart_handle_sysrq_char(&up->port, ch)) + if (uart_handle_sysrq_char(&up->port, ch) || !port) continue; if ((stat->sreg.isr0 & (up->port.ignore_status_mask & 0xff)) == 0 && diff --git a/drivers/tty/serial/sunzilog.c b/drivers/tty/serial/sunzilog.c index 27669ff..813ef8e 100644 --- a/drivers/tty/serial/sunzilog.c +++ b/drivers/tty/serial/sunzilog.c @@ -388,7 +388,7 @@ sunzilog_receive_chars(struct uart_sunzilog_port *up, else if (r1 & CRC_ERR) flag = TTY_FRAME; } - if (uart_handle_sysrq_char(&up->port, ch)) + if (uart_handle_sysrq_char(&up->port, ch) || !port) continue; if (up->port.ignore_status_mask == 0xff || -- cgit v1.1 From b9a129f4813ef5dea8da4670e100f8ba89abebea Mon Sep 17 00:00:00 2001 From: Zhang Yanfei Date: Tue, 12 Mar 2013 13:27:29 +0800 Subject: driver: tty: serial: remove cast for kzalloc return value remove cast for kzalloc return value. Signed-off-by: Zhang Yanfei Cc: Jiri Slaby Cc: Andrew Morton Signed-off-by: Greg Kroah-Hartman --- drivers/tty/serial/icom.c | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) (limited to 'drivers/tty/serial') diff --git a/drivers/tty/serial/icom.c b/drivers/tty/serial/icom.c index bc9e6b01..18ed5ae 100644 --- a/drivers/tty/serial/icom.c +++ b/drivers/tty/serial/icom.c @@ -1415,8 +1415,7 @@ static int icom_alloc_adapter(struct icom_adapter struct icom_adapter *cur_adapter_entry; struct list_head *tmp; - icom_adapter = (struct icom_adapter *) - kzalloc(sizeof(struct icom_adapter), GFP_KERNEL); + icom_adapter = kzalloc(sizeof(struct icom_adapter), GFP_KERNEL); if (!icom_adapter) { return -ENOMEM; -- cgit v1.1 From 6a3f45dccfa3db4de43aabc2f75a337e878f9b4b Mon Sep 17 00:00:00 2001 From: Heikki Krogerus Date: Mon, 25 Mar 2013 13:34:44 +0200 Subject: serial: 8250: Allow probe drivers to ignore tx_loadsz In most cases the tx_loadsz is the same as fifosize. This will store the fifosize in it if it was not separately delivered from the driver. Signed-off-by: Heikki Krogerus Signed-off-by: Greg Kroah-Hartman --- drivers/tty/serial/8250/8250.c | 4 ++++ 1 file changed, 4 insertions(+) (limited to 'drivers/tty/serial') diff --git a/drivers/tty/serial/8250/8250.c b/drivers/tty/serial/8250/8250.c index cf6a538..19ebbdf 100644 --- a/drivers/tty/serial/8250/8250.c +++ b/drivers/tty/serial/8250/8250.c @@ -3247,6 +3247,10 @@ int serial8250_register_8250_port(struct uart_8250_port *up) uart->tx_loadsz = up->tx_loadsz; uart->capabilities = up->capabilities; + /* Take tx_loadsz from fifosize if it wasn't set separately */ + if (uart->port.fifosize && !uart->tx_loadsz) + uart->tx_loadsz = uart->port.fifosize; + if (up->port.dev) uart->port.dev = up->port.dev; -- cgit v1.1 From 9f1ca068ea9968e2bde4a2418d97fcd89005f4bf Mon Sep 17 00:00:00 2001 From: Heikki Krogerus Date: Mon, 25 Mar 2013 13:34:45 +0200 Subject: serial: of_serial: Handle fifo-size property This will reduce the need for extra types in 8250.c just in case the fifo size differs from the standard. Signed-off-by: Heikki Krogerus Acked-by: Arnd Bergmann Signed-off-by: Greg Kroah-Hartman --- drivers/tty/serial/of_serial.c | 4 ++++ 1 file changed, 4 insertions(+) (limited to 'drivers/tty/serial') diff --git a/drivers/tty/serial/of_serial.c b/drivers/tty/serial/of_serial.c index b025d54..267711b 100644 --- a/drivers/tty/serial/of_serial.c +++ b/drivers/tty/serial/of_serial.c @@ -97,6 +97,10 @@ static int of_platform_serial_setup(struct platform_device *ofdev, if (of_property_read_u32(np, "reg-shift", &prop) == 0) port->regshift = prop; + /* Check for fifo size */ + if (of_property_read_u32(np, "fifo-size", &prop) == 0) + port->fifosize = prop; + port->irq = irq_of_parse_and_map(np, 0); port->iotype = UPIO_MEM; if (of_property_read_u32(np, "reg-io-width", &prop) == 0) { -- cgit v1.1 From b250a6b0015753362eeb63c3a0dd985848ed772d Mon Sep 17 00:00:00 2001 From: Paul Bolle Date: Mon, 25 Mar 2013 11:50:28 +0100 Subject: serial: sh-sci: remove obsolete Kconfig macros Support for SH7367 and SH7377 got removed in v3.8. Now remove their last Kconfig macros. Signed-off-by: Paul Bolle Signed-off-by: Greg Kroah-Hartman --- drivers/tty/serial/sh-sci.h | 2 -- 1 file changed, 2 deletions(-) (limited to 'drivers/tty/serial') diff --git a/drivers/tty/serial/sh-sci.h b/drivers/tty/serial/sh-sci.h index 4c22a15..5aca736 100644 --- a/drivers/tty/serial/sh-sci.h +++ b/drivers/tty/serial/sh-sci.h @@ -15,8 +15,6 @@ defined(CONFIG_CPU_SUBTYPE_SH7720) || \ defined(CONFIG_CPU_SUBTYPE_SH7721) || \ defined(CONFIG_ARCH_SH73A0) || \ - defined(CONFIG_ARCH_SH7367) || \ - defined(CONFIG_ARCH_SH7377) || \ defined(CONFIG_ARCH_SH7372) || \ defined(CONFIG_ARCH_R8A7740) -- cgit v1.1 From 30215c3b8f36cc532267615ceade3657a9bd9563 Mon Sep 17 00:00:00 2001 From: Steffen Trumtrar Date: Fri, 22 Mar 2013 18:50:02 +0100 Subject: serial: xilinx_uartps: remove superfluous IDR write The datesheet clearly states, that writing low bits to the XUARTPS_IDR register have no effect. Remove the write. Signed-off-by: Steffen Trumtrar Cc: Greg Kroah-Hartman Signed-off-by: Greg Kroah-Hartman --- drivers/tty/serial/xilinx_uartps.c | 3 --- 1 file changed, 3 deletions(-) (limited to 'drivers/tty/serial') diff --git a/drivers/tty/serial/xilinx_uartps.c b/drivers/tty/serial/xilinx_uartps.c index ba451c7..974c361 100644 --- a/drivers/tty/serial/xilinx_uartps.c +++ b/drivers/tty/serial/xilinx_uartps.c @@ -583,9 +583,6 @@ static int xuartps_startup(struct uart_port *port) xuartps_writel(XUARTPS_IXR_TXEMPTY | XUARTPS_IXR_PARITY | XUARTPS_IXR_FRAMING | XUARTPS_IXR_OVERRUN | XUARTPS_IXR_RXTRIG | XUARTPS_IXR_TOUT, XUARTPS_IER_OFFSET); - xuartps_writel(~(XUARTPS_IXR_TXEMPTY | XUARTPS_IXR_PARITY | - XUARTPS_IXR_FRAMING | XUARTPS_IXR_OVERRUN | - XUARTPS_IXR_RXTRIG | XUARTPS_IXR_TOUT), XUARTPS_IDR_OFFSET); return retval; } -- cgit v1.1 From b0b8c84cf58d2486d48f486b5c47af7a7a33a497 Mon Sep 17 00:00:00 2001 From: Heikki Krogerus Date: Mon, 25 Mar 2013 15:51:15 +0200 Subject: serial: of_serial: Handle auto-flow-control property Automatic Flow Control capability is not tied to this property. This is only one way of detecting it. The property is limited to be used only with 8250 driver. Signed-off-by: Heikki Krogerus Acked-by: Arnd Bergmann Signed-off-by: Greg Kroah-Hartman --- drivers/tty/serial/of_serial.c | 13 ++++++++++--- 1 file changed, 10 insertions(+), 3 deletions(-) (limited to 'drivers/tty/serial') diff --git a/drivers/tty/serial/of_serial.c b/drivers/tty/serial/of_serial.c index 267711b..39c7ea4 100644 --- a/drivers/tty/serial/of_serial.c +++ b/drivers/tty/serial/of_serial.c @@ -14,7 +14,6 @@ #include #include #include -#include #include #include #include @@ -22,6 +21,8 @@ #include #include +#include "8250/8250.h" + struct of_serial_info { struct clk *clk; int type; @@ -171,11 +172,17 @@ static int of_platform_serial_probe(struct platform_device *ofdev) #ifdef CONFIG_SERIAL_8250 case PORT_8250 ... PORT_MAX_8250: { - /* For now the of bindings don't support the extra - 8250 specific bits */ struct uart_8250_port port8250; memset(&port8250, 0, sizeof(port8250)); port8250.port = port; + + if (port.fifosize) + port8250.capabilities = UART_CAP_FIFO; + + if (of_property_read_bool(ofdev->dev.of_node, + "auto-flow-control")) + port8250.capabilities |= UART_CAP_AFE; + ret = serial8250_register_8250_port(&port8250); break; } -- cgit v1.1 From 65c1b12b453ec726fe0692707a8a2493502bd6a2 Mon Sep 17 00:00:00 2001 From: Paul Bolle Date: Mon, 25 Mar 2013 23:01:21 +0100 Subject: serial: 8250: remove a few lines of dead code Support for the WindRiver SBC8560 board was removed in v3.6. But there are still a few lines depending on its obsolete Kconfig macro. Remove these now. Signed-off-by: Paul Bolle Signed-off-by: Greg Kroah-Hartman --- drivers/tty/serial/8250/8250.h | 7 ------- 1 file changed, 7 deletions(-) (limited to 'drivers/tty/serial') diff --git a/drivers/tty/serial/8250/8250.h b/drivers/tty/serial/8250/8250.h index 34eb676..1ebf853 100644 --- a/drivers/tty/serial/8250/8250.h +++ b/drivers/tty/serial/8250/8250.h @@ -117,13 +117,6 @@ static inline void serial_dl_write(struct uart_8250_port *up, int value) * is cleared, the machine locks up with endless interrupts. */ #define ALPHA_KLUDGE_MCR (UART_MCR_OUT2 | UART_MCR_OUT1) -#elif defined(CONFIG_SBC8560) -/* - * WindRiver did something similarly broken on their SBC8560 board. The - * UART tristates its IRQ output while OUT2 is clear, but they pulled - * the interrupt line _up_ instead of down, so if we register the IRQ - * while the UART is in that state, we die in an IRQ storm. */ -#define ALPHA_KLUDGE_MCR (UART_MCR_OUT2) #else #define ALPHA_KLUDGE_MCR 0 #endif -- cgit v1.1 From cfcec52e9781f08948c6eb98198d65c45be75a70 Mon Sep 17 00:00:00 2001 From: Karthik Manamcheri Date: Thu, 28 Mar 2013 17:33:20 -0500 Subject: serial: 8250: Make SERIAL_8250_RUNTIME_UARTS work correctly Consider a situation where I have an ARM based system and therefore no legacy ports. Say, I have two memory-mapped ports. I use device tree to describe the ports. What would be the config options I set so that I get only the two ports in my system? I do not want legacy ports being created automatically and I want it to be flexible enough that it creates the devices based only on the device tree. I expected setting SERIAL_8250_RUNTIME_UARTS = 0 to work because the description said, "Set this to the maximum number of serial ports you want the kernel to register at boot time." Unfortunately, even though SERIAL_8250_NR_UARTS was set to the default value of 4, I did not get any device nodes (because SERIAL_8250_RUNTIME_UARTS was 0). This is what this change is addressing. SERIAL_8250_NR_UARTS controls the maximum number of ports you can support. SERIAL_8250_RUNTIME_UARTS specifies the number of ports you want to create automatically for legacy ports at boot time. All other ports will be created when serial8250_register_port is called (and if does not exceed the total number of supported ports as specified by SERIAL_8250_NR_UARTS). Signed-off-by: Karthik Manamcheri Signed-off-by: Greg Kroah-Hartman --- drivers/tty/serial/8250/8250.c | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) (limited to 'drivers/tty/serial') diff --git a/drivers/tty/serial/8250/8250.c b/drivers/tty/serial/8250/8250.c index 19ebbdf..e5ddfd6 100644 --- a/drivers/tty/serial/8250/8250.c +++ b/drivers/tty/serial/8250/8250.c @@ -2755,7 +2755,7 @@ static void __init serial8250_isa_init_ports(void) if (nr_uarts > UART_NR) nr_uarts = UART_NR; - for (i = 0; i < nr_uarts; i++) { + for (i = 0; i < UART_NR; i++) { struct uart_8250_port *up = &serial8250_ports[i]; struct uart_port *port = &up->port; @@ -2916,7 +2916,7 @@ static int __init serial8250_console_setup(struct console *co, char *options) * if so, search for the first available port that does have * console support. */ - if (co->index >= nr_uarts) + if (co->index >= UART_NR) co->index = 0; port = &serial8250_ports[co->index].port; if (!port->iobase && !port->membase) @@ -2957,7 +2957,7 @@ int serial8250_find_port(struct uart_port *p) int line; struct uart_port *port; - for (line = 0; line < nr_uarts; line++) { + for (line = 0; line < UART_NR; line++) { port = &serial8250_ports[line].port; if (uart_match_port(p, port)) return line; @@ -3110,7 +3110,7 @@ static int serial8250_remove(struct platform_device *dev) { int i; - for (i = 0; i < nr_uarts; i++) { + for (i = 0; i < UART_NR; i++) { struct uart_8250_port *up = &serial8250_ports[i]; if (up->port.dev == &dev->dev) @@ -3178,7 +3178,7 @@ static struct uart_8250_port *serial8250_find_match_or_unused(struct uart_port * /* * First, find a port entry which matches. */ - for (i = 0; i < nr_uarts; i++) + for (i = 0; i < UART_NR; i++) if (uart_match_port(&serial8250_ports[i].port, port)) return &serial8250_ports[i]; @@ -3187,7 +3187,7 @@ static struct uart_8250_port *serial8250_find_match_or_unused(struct uart_port * * free entry. We look for one which hasn't been previously * used (indicated by zero iobase). */ - for (i = 0; i < nr_uarts; i++) + for (i = 0; i < UART_NR; i++) if (serial8250_ports[i].port.type == PORT_UNKNOWN && serial8250_ports[i].port.iobase == 0) return &serial8250_ports[i]; @@ -3196,7 +3196,7 @@ static struct uart_8250_port *serial8250_find_match_or_unused(struct uart_port * * That also failed. Last resort is to find any entry which * doesn't have a real port associated with it. */ - for (i = 0; i < nr_uarts; i++) + for (i = 0; i < UART_NR; i++) if (serial8250_ports[i].port.type == PORT_UNKNOWN) return &serial8250_ports[i]; -- cgit v1.1 From b6ad29355560beef6d127c6d33fb10ec0113bd85 Mon Sep 17 00:00:00 2001 From: Tomasz Figa Date: Tue, 26 Mar 2013 15:57:35 +0100 Subject: tty: serial: samsung: Disable interrupts in a suspend-friendly way Since the interrupt mask register is not preserved across system suspend and it defaults to all interrupts enabled, it is not enough to disable UART interrupt. This patch adds free_irq to port shutdown and mask setting to port startup to handle IRQ disabling in a suspend-friendly way. In addition, a bug caused by multiple request_irq calls in port startup callback is fixed. Signed-off-by: Tomasz Figa Signed-off-by: Kyungmin Park Signed-off-by: Greg Kroah-Hartman --- drivers/tty/serial/samsung.c | 4 ++++ 1 file changed, 4 insertions(+) (limited to 'drivers/tty/serial') diff --git a/drivers/tty/serial/samsung.c b/drivers/tty/serial/samsung.c index 2769a38..b386fc8 100644 --- a/drivers/tty/serial/samsung.c +++ b/drivers/tty/serial/samsung.c @@ -446,6 +446,8 @@ static void s3c24xx_serial_shutdown(struct uart_port *port) /* Clear pending interrupts and mask all interrupts */ if (s3c24xx_serial_has_interrupt_mask(port)) { + free_irq(port->irq, ourport); + wr_regl(port, S3C64XX_UINTP, 0xf); wr_regl(port, S3C64XX_UINTM, 0xf); } @@ -505,6 +507,8 @@ static int s3c64xx_serial_startup(struct uart_port *port) dbg("s3c64xx_serial_startup: port=%p (%08lx,%p)\n", port->mapbase, port->membase); + wr_regl(port, S3C64XX_UINTM, 0xf); + ret = request_irq(port->irq, s3c64xx_serial_handle_irq, IRQF_SHARED, s3c24xx_serial_portname(port), ourport); if (ret) { -- cgit v1.1 From d09a7308e9887a83abfd3176f4416d4142a265dc Mon Sep 17 00:00:00 2001 From: Michael Spang Date: Wed, 27 Mar 2013 19:34:24 -0400 Subject: serial: samsung: Restore IRQ mask during noirq resume This closes a window where the system may hang in resume as soon as the UART interrupt is enabled and before the mask is restored. The hang occurs because the driver can't handle IRQs it thinks are masked. Signed-off-by: Michael Spang Signed-off-by: Greg Kroah-Hartman --- drivers/tty/serial/samsung.c | 20 ++++++++++++++++++++ 1 file changed, 20 insertions(+) (limited to 'drivers/tty/serial') diff --git a/drivers/tty/serial/samsung.c b/drivers/tty/serial/samsung.c index b386fc8..78d9c55 100644 --- a/drivers/tty/serial/samsung.c +++ b/drivers/tty/serial/samsung.c @@ -1311,9 +1311,29 @@ static int s3c24xx_serial_resume(struct device *dev) return 0; } +static int s3c24xx_serial_resume_noirq(struct device *dev) +{ + struct uart_port *port = s3c24xx_dev_to_port(dev); + + if (port) { + /* restore IRQ mask */ + if (s3c24xx_serial_has_interrupt_mask(port)) { + unsigned int uintm = 0xf; + if (tx_enabled(port)) + uintm &= ~S3C64XX_UINTM_TXD_MSK; + if (rx_enabled(port)) + uintm &= ~S3C64XX_UINTM_RXD_MSK; + wr_regl(port, S3C64XX_UINTM, uintm); + } + } + + return 0; +} + static const struct dev_pm_ops s3c24xx_serial_pm_ops = { .suspend = s3c24xx_serial_suspend, .resume = s3c24xx_serial_resume, + .resume_noirq = s3c24xx_serial_resume_noirq, }; #define SERIAL_SAMSUNG_PM_OPS (&s3c24xx_serial_pm_ops) -- cgit v1.1 From 38adbc54cea90e220c9212f961a621b2c6af9ae0 Mon Sep 17 00:00:00 2001 From: Michael Spang Date: Wed, 27 Mar 2013 19:34:25 -0400 Subject: serial: samsung: Avoid waiting forever for TX ready The no_console_suspend option allows the console to write to the UART during early resume, before the serial port itself is resumed. Such writes hang indefinitely waiting for TX ready. This adds a check to the console putchar function to drop characters instead of hanging if the port hasn't been initialized. That way, we can use no_console_suspend without risk of hanging. Signed-off-by: Michael Spang Signed-off-by: Greg Kroah-Hartman --- drivers/tty/serial/samsung.c | 22 +++++++++++++++++++--- 1 file changed, 19 insertions(+), 3 deletions(-) (limited to 'drivers/tty/serial') diff --git a/drivers/tty/serial/samsung.c b/drivers/tty/serial/samsung.c index 78d9c55..7883f11 100644 --- a/drivers/tty/serial/samsung.c +++ b/drivers/tty/serial/samsung.c @@ -1367,6 +1367,13 @@ s3c24xx_serial_console_txrdy(struct uart_port *port, unsigned int ufcon) return (utrstat & S3C2410_UTRSTAT_TXE) ? 1 : 0; } +static bool +s3c24xx_port_configured(unsigned int ucon) +{ + /* consider the serial port configured if the tx/rx mode set */ + return (ucon & 0xf) != 0; +} + #ifdef CONFIG_CONSOLE_POLL /* * Console polling routines for writing and reading from the uart while @@ -1389,6 +1396,11 @@ static void s3c24xx_serial_put_poll_char(struct uart_port *port, unsigned char c) { unsigned int ufcon = rd_regl(cons_uart, S3C2410_UFCON); + unsigned int ucon = rd_regl(cons_uart, S3C2410_UCON); + + /* not possible to xmit on unconfigured port */ + if (!s3c24xx_port_configured(ucon)) + return; while (!s3c24xx_serial_console_txrdy(port, ufcon)) cpu_relax(); @@ -1401,6 +1413,12 @@ static void s3c24xx_serial_console_putchar(struct uart_port *port, int ch) { unsigned int ufcon = rd_regl(cons_uart, S3C2410_UFCON); + unsigned int ucon = rd_regl(cons_uart, S3C2410_UCON); + + /* not possible to xmit on unconfigured port */ + if (!s3c24xx_port_configured(ucon)) + return; + while (!s3c24xx_serial_console_txrdy(port, ufcon)) barrier(); wr_regb(cons_uart, S3C2410_UTXH, ch); @@ -1433,9 +1451,7 @@ s3c24xx_serial_get_options(struct uart_port *port, int *baud, "registers: ulcon=%08x, ucon=%08x, ubdriv=%08x\n", port, ulcon, ucon, ubrdiv); - if ((ucon & 0xf) != 0) { - /* consider the serial port configured if the tx/rx mode set */ - + if (s3c24xx_port_configured(ucon)) { switch (ulcon & S3C2410_LCON_CSMASK) { case S3C2410_LCON_CS5: *bits = 5; -- cgit v1.1 From e302cd932094fa59463b5891814d2a5ace56cfc1 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Emilio=20L=C3=B3pez?= Date: Fri, 29 Mar 2013 00:15:49 +0100 Subject: serial: 8250_dw: add support for clk api MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit This commit implements support for using the clk api; this lets us use the "clocks" property with device tree, instead of having to use clock-frequency. Signed-off-by: Emilio López Signed-off-by: Maxime Ripard Reviewed-by: Heikki Krogerus Signed-off-by: Greg Kroah-Hartman --- drivers/tty/serial/8250/8250_dw.c | 33 ++++++++++++++++++++++++--------- 1 file changed, 24 insertions(+), 9 deletions(-) (limited to 'drivers/tty/serial') diff --git a/drivers/tty/serial/8250/8250_dw.c b/drivers/tty/serial/8250/8250_dw.c index db0e66f..3dedd24 100644 --- a/drivers/tty/serial/8250/8250_dw.c +++ b/drivers/tty/serial/8250/8250_dw.c @@ -26,6 +26,7 @@ #include #include #include +#include #include "8250.h" @@ -55,8 +56,9 @@ struct dw8250_data { - int last_lcr; - int line; + int last_lcr; + int line; + struct clk *clk; }; static void dw8250_serial_out(struct uart_port *p, int offset, int value) @@ -136,8 +138,13 @@ static int dw8250_probe_of(struct uart_port *p) if (!of_property_read_u32(np, "reg-shift", &val)) p->regshift = val; + /* clock got configured through clk api, all done */ + if (p->uartclk) + return 0; + + /* try to find out clock frequency from DT as fallback */ if (of_property_read_u32(np, "clock-frequency", &val)) { - dev_err(p->dev, "no clock-frequency property set\n"); + dev_err(p->dev, "clk or clock-frequency not defined\n"); return -EINVAL; } p->uartclk = val; @@ -294,9 +301,20 @@ static int dw8250_probe(struct platform_device *pdev) if (!uart.port.membase) return -ENOMEM; + data = devm_kzalloc(&pdev->dev, sizeof(*data), GFP_KERNEL); + if (!data) + return -ENOMEM; + + data->clk = devm_clk_get(&pdev->dev, NULL); + if (!IS_ERR(data->clk)) { + clk_prepare_enable(data->clk); + uart.port.uartclk = clk_get_rate(data->clk); + } + uart.port.iotype = UPIO_MEM; uart.port.serial_in = dw8250_serial_in; uart.port.serial_out = dw8250_serial_out; + uart.port.private_data = data; dw8250_setup_port(&uart); @@ -312,12 +330,6 @@ static int dw8250_probe(struct platform_device *pdev) return -ENODEV; } - data = devm_kzalloc(&pdev->dev, sizeof(*data), GFP_KERNEL); - if (!data) - return -ENOMEM; - - uart.port.private_data = data; - data->line = serial8250_register_8250_port(&uart); if (data->line < 0) return data->line; @@ -333,6 +345,9 @@ static int dw8250_remove(struct platform_device *pdev) serial8250_unregister_port(data->line); + if (!IS_ERR(data->clk)) + clk_disable_unprepare(data->clk); + return 0; } -- cgit v1.1 From cb06ff102e2d79a82cf780aa5e6947b2e0529ac0 Mon Sep 17 00:00:00 2001 From: Chanho Min Date: Wed, 27 Mar 2013 18:38:11 +0900 Subject: ARM: PL011: Add support for Rx DMA buffer polling. In DMA support, The received data is not pushed to tty until the DMA buffer is filled. But some megabyte rate chips such as BT expect fast response and data should be pushed immediately. In order to fix this issue, We suggest the use of the timer for polling DMA buffer. In our test, no data loss occurred at high-baudrate as compared with interrupt- driven (We tested with 3Mbps). We changes: - We add timer for polling. If we set poll_timer to 10, every 10ms, timer handler checks the residue in the dma buffer and transfer data to the tty. Also, last_residue is updated for the next polling. - poll_timeout is used to prevent the timer's system cost. If poll_timeout is set to 3000 and no data is received in 3 seconds, we inactivate poll timer and driver falls back to interrupt-driven. When data is received again in FIFO and UART irq is occurred, we switch back to DMA mode and start polling. - We use consistent DMA mappings to avoid from the frequent cache operation of the timer function for default. - pl011_dma_rx_chars is modified. the pending size is recalculated because data can be taken by polling. - the polling time is adjusted if dma rx poll is enabled but no rate is specified. Ideal polling interval to push 1 character at every interval is the reciprocal of 'baud rate / 10 line bits per character / 1000 ms per sec'. But It is very aggressive to system. Experimentally, '10000000 / baud' is suitable to receive dozens of characters. the poll rate can be specified statically by dma_rx_poll_rate of the platform data as well. Changes compared to v1: - Use of consistent DMA mappings. - Added dma_rx_poll_rate in platform data to specify the polling interval. - Added dma_rx_poll_timeout in platform data to specify the polling timeout. Changes compared to v2: - Use of consistent DMA mappings for default. - Added dma_rx_poll_enable in platform data to adjust the polling time according to the baud rate. - remove unnecessary lock from the polling function. Signed-off-by: Chanho Min Signed-off-by: Greg Kroah-Hartman --- drivers/tty/serial/amba-pl011.c | 157 +++++++++++++++++++++++++++++++++++----- 1 file changed, 138 insertions(+), 19 deletions(-) (limited to 'drivers/tty/serial') diff --git a/drivers/tty/serial/amba-pl011.c b/drivers/tty/serial/amba-pl011.c index 3ea5408..b031abf 100644 --- a/drivers/tty/serial/amba-pl011.c +++ b/drivers/tty/serial/amba-pl011.c @@ -29,6 +29,7 @@ * and hooked into this driver. */ + #if defined(CONFIG_SERIAL_AMBA_PL011_CONSOLE) && defined(CONFIG_MAGIC_SYSRQ) #define SUPPORT_SYSRQ #endif @@ -117,6 +118,12 @@ struct pl011_dmarx_data { struct pl011_sgbuf sgbuf_b; dma_cookie_t cookie; bool running; + struct timer_list timer; + unsigned int last_residue; + unsigned long last_jiffies; + bool auto_poll_rate; + unsigned int poll_rate; + unsigned int poll_timeout; }; struct pl011_dmatx_data { @@ -223,16 +230,18 @@ static int pl011_fifo_to_tty(struct uart_amba_port *uap) static int pl011_sgbuf_init(struct dma_chan *chan, struct pl011_sgbuf *sg, enum dma_data_direction dir) { - sg->buf = kmalloc(PL011_DMA_BUFFER_SIZE, GFP_KERNEL); + dma_addr_t dma_addr; + + sg->buf = dma_alloc_coherent(chan->device->dev, + PL011_DMA_BUFFER_SIZE, &dma_addr, GFP_KERNEL); if (!sg->buf) return -ENOMEM; - sg_init_one(&sg->sg, sg->buf, PL011_DMA_BUFFER_SIZE); + sg_init_table(&sg->sg, 1); + sg_set_page(&sg->sg, phys_to_page(dma_addr), + PL011_DMA_BUFFER_SIZE, offset_in_page(dma_addr)); + sg_dma_address(&sg->sg) = dma_addr; - if (dma_map_sg(chan->device->dev, &sg->sg, 1, dir) != 1) { - kfree(sg->buf); - return -EINVAL; - } return 0; } @@ -240,8 +249,9 @@ static void pl011_sgbuf_free(struct dma_chan *chan, struct pl011_sgbuf *sg, enum dma_data_direction dir) { if (sg->buf) { - dma_unmap_sg(chan->device->dev, &sg->sg, 1, dir); - kfree(sg->buf); + dma_free_coherent(chan->device->dev, + PL011_DMA_BUFFER_SIZE, sg->buf, + sg_dma_address(&sg->sg)); } } @@ -300,6 +310,29 @@ static void pl011_dma_probe_initcall(struct uart_amba_port *uap) dmaengine_slave_config(chan, &rx_conf); uap->dmarx.chan = chan; + if (plat->dma_rx_poll_enable) { + /* Set poll rate if specified. */ + if (plat->dma_rx_poll_rate) { + uap->dmarx.auto_poll_rate = false; + uap->dmarx.poll_rate = plat->dma_rx_poll_rate; + } else { + /* + * 100 ms defaults to poll rate if not + * specified. This will be adjusted with + * the baud rate at set_termios. + */ + uap->dmarx.auto_poll_rate = true; + uap->dmarx.poll_rate = 100; + } + /* 3 secs defaults poll_timeout if not specified. */ + if (plat->dma_rx_poll_timeout) + uap->dmarx.poll_timeout = + plat->dma_rx_poll_timeout; + else + uap->dmarx.poll_timeout = 3000; + } else + uap->dmarx.auto_poll_rate = false; + dev_info(uap->port.dev, "DMA channel RX %s\n", dma_chan_name(uap->dmarx.chan)); } @@ -701,24 +734,30 @@ static void pl011_dma_rx_chars(struct uart_amba_port *uap, struct tty_port *port = &uap->port.state->port; struct pl011_sgbuf *sgbuf = use_buf_b ? &uap->dmarx.sgbuf_b : &uap->dmarx.sgbuf_a; - struct device *dev = uap->dmarx.chan->device->dev; int dma_count = 0; u32 fifotaken = 0; /* only used for vdbg() */ - /* Pick everything from the DMA first */ + struct pl011_dmarx_data *dmarx = &uap->dmarx; + int dmataken = 0; + + if (uap->dmarx.poll_rate) { + /* The data can be taken by polling */ + dmataken = sgbuf->sg.length - dmarx->last_residue; + /* Recalculate the pending size */ + if (pending >= dmataken) + pending -= dmataken; + } + + /* Pick the remain data from the DMA */ if (pending) { - /* Sync in buffer */ - dma_sync_sg_for_cpu(dev, &sgbuf->sg, 1, DMA_FROM_DEVICE); /* * First take all chars in the DMA pipe, then look in the FIFO. * Note that tty_insert_flip_buf() tries to take as many chars * as it can. */ - dma_count = tty_insert_flip_string(port, sgbuf->buf, pending); - - /* Return buffer to device */ - dma_sync_sg_for_device(dev, &sgbuf->sg, 1, DMA_FROM_DEVICE); + dma_count = tty_insert_flip_string(port, sgbuf->buf + dmataken, + pending); uap->port.icount.rx += dma_count; if (dma_count < pending) @@ -726,6 +765,10 @@ static void pl011_dma_rx_chars(struct uart_amba_port *uap, "couldn't insert all characters (TTY is full?)\n"); } + /* Reset the last_residue for Rx DMA poll */ + if (uap->dmarx.poll_rate) + dmarx->last_residue = sgbuf->sg.length; + /* * Only continue with trying to read the FIFO if all DMA chars have * been taken first. @@ -865,6 +908,57 @@ static inline void pl011_dma_rx_stop(struct uart_amba_port *uap) writew(uap->dmacr, uap->port.membase + UART011_DMACR); } +/* + * Timer handler for Rx DMA polling. + * Every polling, It checks the residue in the dma buffer and transfer + * data to the tty. Also, last_residue is updated for the next polling. + */ +static void pl011_dma_rx_poll(unsigned long args) +{ + struct uart_amba_port *uap = (struct uart_amba_port *)args; + struct tty_port *port = &uap->port.state->port; + struct pl011_dmarx_data *dmarx = &uap->dmarx; + struct dma_chan *rxchan = uap->dmarx.chan; + unsigned long flags = 0; + unsigned int dmataken = 0; + unsigned int size = 0; + struct pl011_sgbuf *sgbuf; + int dma_count; + struct dma_tx_state state; + + sgbuf = dmarx->use_buf_b ? &uap->dmarx.sgbuf_b : &uap->dmarx.sgbuf_a; + rxchan->device->device_tx_status(rxchan, dmarx->cookie, &state); + if (likely(state.residue < dmarx->last_residue)) { + dmataken = sgbuf->sg.length - dmarx->last_residue; + size = dmarx->last_residue - state.residue; + dma_count = tty_insert_flip_string(port, sgbuf->buf + dmataken, + size); + if (dma_count == size) + dmarx->last_residue = state.residue; + dmarx->last_jiffies = jiffies; + } + tty_flip_buffer_push(port); + + /* + * If no data is received in poll_timeout, the driver will fall back + * to interrupt mode. We will retrigger DMA at the first interrupt. + */ + if (jiffies_to_msecs(jiffies - dmarx->last_jiffies) + > uap->dmarx.poll_timeout) { + + spin_lock_irqsave(&uap->port.lock, flags); + pl011_dma_rx_stop(uap); + spin_unlock_irqrestore(&uap->port.lock, flags); + + uap->dmarx.running = false; + dmaengine_terminate_all(rxchan); + del_timer(&uap->dmarx.timer); + } else { + mod_timer(&uap->dmarx.timer, + jiffies + msecs_to_jiffies(uap->dmarx.poll_rate)); + } +} + static void pl011_dma_startup(struct uart_amba_port *uap) { int ret; @@ -927,6 +1021,16 @@ skip_rx: if (pl011_dma_rx_trigger_dma(uap)) dev_dbg(uap->port.dev, "could not trigger initial " "RX DMA job, fall back to interrupt mode\n"); + if (uap->dmarx.poll_rate) { + init_timer(&(uap->dmarx.timer)); + uap->dmarx.timer.function = pl011_dma_rx_poll; + uap->dmarx.timer.data = (unsigned long)uap; + mod_timer(&uap->dmarx.timer, + jiffies + + msecs_to_jiffies(uap->dmarx.poll_rate)); + uap->dmarx.last_residue = PL011_DMA_BUFFER_SIZE; + uap->dmarx.last_jiffies = jiffies; + } } } @@ -962,6 +1066,8 @@ static void pl011_dma_shutdown(struct uart_amba_port *uap) /* Clean up the RX DMA */ pl011_sgbuf_free(uap->dmarx.chan, &uap->dmarx.sgbuf_a, DMA_FROM_DEVICE); pl011_sgbuf_free(uap->dmarx.chan, &uap->dmarx.sgbuf_b, DMA_FROM_DEVICE); + if (uap->dmarx.poll_rate) + del_timer_sync(&uap->dmarx.timer); uap->using_rx_dma = false; } } @@ -976,7 +1082,6 @@ static inline bool pl011_dma_rx_running(struct uart_amba_port *uap) return uap->using_rx_dma && uap->dmarx.running; } - #else /* Blank functions if the DMA engine is not available */ static inline void pl011_dma_probe(struct uart_amba_port *uap) @@ -1088,8 +1193,18 @@ static void pl011_rx_chars(struct uart_amba_port *uap) dev_dbg(uap->port.dev, "could not trigger RX DMA job " "fall back to interrupt mode again\n"); uap->im |= UART011_RXIM; - } else + } else { uap->im &= ~UART011_RXIM; + /* Start Rx DMA poll */ + if (uap->dmarx.poll_rate) { + uap->dmarx.last_jiffies = jiffies; + uap->dmarx.last_residue = PL011_DMA_BUFFER_SIZE; + mod_timer(&uap->dmarx.timer, + jiffies + + msecs_to_jiffies(uap->dmarx.poll_rate)); + } + } + writew(uap->im, uap->port.membase + UART011_IMSC); } spin_lock(&uap->port.lock); @@ -1164,7 +1279,6 @@ static irqreturn_t pl011_int(int irq, void *dev_id) unsigned int dummy_read; spin_lock_irqsave(&uap->port.lock, flags); - status = readw(uap->port.membase + UART011_MIS); if (status) { do { @@ -1551,6 +1665,11 @@ pl011_set_termios(struct uart_port *port, struct ktermios *termios, */ baud = uart_get_baud_rate(port, termios, old, 0, port->uartclk / clkdiv); + /* + * Adjust RX DMA polling rate with baud rate if not specified. + */ + if (uap->dmarx.auto_poll_rate) + uap->dmarx.poll_rate = DIV_ROUND_UP(10000000, baud); if (baud > port->uartclk/16) quot = DIV_ROUND_CLOSEST(port->uartclk * 8, baud); -- cgit v1.1 From 89fa28dbe0395ee06f3aacfe27655323ebad43d1 Mon Sep 17 00:00:00 2001 From: Chanho Min Date: Wed, 3 Apr 2013 11:10:37 +0900 Subject: amba-pl011: fix build error if CONFIG_DMA_ENGINE is not enabled Following patch will fix build error if CONFIG_DMA_ENGINE is unset. Reported-by: Stephen Rothwell Signed-off-by: Chanho Min Signed-off-by: Greg Kroah-Hartman --- drivers/tty/serial/amba-pl011.c | 4 ++++ 1 file changed, 4 insertions(+) (limited to 'drivers/tty/serial') diff --git a/drivers/tty/serial/amba-pl011.c b/drivers/tty/serial/amba-pl011.c index b031abf..6cf861e 100644 --- a/drivers/tty/serial/amba-pl011.c +++ b/drivers/tty/serial/amba-pl011.c @@ -1195,6 +1195,7 @@ static void pl011_rx_chars(struct uart_amba_port *uap) uap->im |= UART011_RXIM; } else { uap->im &= ~UART011_RXIM; +#ifdef CONFIG_DMA_ENGINE /* Start Rx DMA poll */ if (uap->dmarx.poll_rate) { uap->dmarx.last_jiffies = jiffies; @@ -1203,6 +1204,7 @@ static void pl011_rx_chars(struct uart_amba_port *uap) jiffies + msecs_to_jiffies(uap->dmarx.poll_rate)); } +#endif } writew(uap->im, uap->port.membase + UART011_IMSC); @@ -1665,11 +1667,13 @@ pl011_set_termios(struct uart_port *port, struct ktermios *termios, */ baud = uart_get_baud_rate(port, termios, old, 0, port->uartclk / clkdiv); +#ifdef CONFIG_DMA_ENGINE /* * Adjust RX DMA polling rate with baud rate if not specified. */ if (uap->dmarx.auto_poll_rate) uap->dmarx.poll_rate = DIV_ROUND_UP(10000000, baud); +#endif if (baud > port->uartclk/16) quot = DIV_ROUND_CLOSEST(port->uartclk * 8, baud); -- cgit v1.1 From 31bdfc649f4577c9b1120c67b7b1e85f7777aad0 Mon Sep 17 00:00:00 2001 From: Jingoo Han Date: Fri, 5 Apr 2013 10:54:05 +0900 Subject: serial: max3100: use spi_get_drvdata() and spi_set_drvdata() Use the wrapper functions for getting and setting the driver data using spi_device instead of using dev_{get|set}_drvdata with &spi->dev, so we can directly pass a struct spi_device. Signed-off-by: Jingoo Han Signed-off-by: Greg Kroah-Hartman --- drivers/tty/serial/max3100.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'drivers/tty/serial') diff --git a/drivers/tty/serial/max3100.c b/drivers/tty/serial/max3100.c index 57da9bb..35866d5 100644 --- a/drivers/tty/serial/max3100.c +++ b/drivers/tty/serial/max3100.c @@ -778,7 +778,7 @@ static int max3100_probe(struct spi_device *spi) max3100s[i]->spi = spi; max3100s[i]->irq = spi->irq; spin_lock_init(&max3100s[i]->conf_lock); - dev_set_drvdata(&spi->dev, max3100s[i]); + spi_set_drvdata(spi, max3100s[i]); pdata = spi->dev.platform_data; max3100s[i]->crystal = pdata->crystal; max3100s[i]->loopback = pdata->loopback; @@ -819,7 +819,7 @@ static int max3100_probe(struct spi_device *spi) static int max3100_remove(struct spi_device *spi) { - struct max3100_port *s = dev_get_drvdata(&spi->dev); + struct max3100_port *s = spi_get_drvdata(spi); int i; mutex_lock(&max3100s_lock); -- cgit v1.1 From 17efd2b7867b5ee1076d3c9ae5a6c937907d9198 Mon Sep 17 00:00:00 2001 From: Arnd Bergmann Date: Thu, 11 Apr 2013 02:04:47 +0200 Subject: tty: serial/samsung: prepare for common clock API With the common clock interface, there is no way to provide the "clock_source" sysfs attribute for the samsung serial ports. Given that this file was purely informational and had fixed contents, we have reason to believe that no user space programs were relying on it. The sysfs file is not documented in the ABI docs. Signed-off-by: Arnd Bergmann Signed-off-by: Greg Kroah-Hartman --- drivers/tty/serial/samsung.c | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) (limited to 'drivers/tty/serial') diff --git a/drivers/tty/serial/samsung.c b/drivers/tty/serial/samsung.c index 7883f11..e91378b 100644 --- a/drivers/tty/serial/samsung.c +++ b/drivers/tty/serial/samsung.c @@ -1183,6 +1183,7 @@ static int s3c24xx_serial_init_port(struct s3c24xx_uart_port *ourport, return 0; } +#ifdef CONFIG_SAMSUNG_CLOCK static ssize_t s3c24xx_serial_show_clksrc(struct device *dev, struct device_attribute *attr, char *buf) @@ -1198,7 +1199,7 @@ static ssize_t s3c24xx_serial_show_clksrc(struct device *dev, } static DEVICE_ATTR(clock_source, S_IRUGO, s3c24xx_serial_show_clksrc, NULL); - +#endif /* Device driver serial port probe */ @@ -1256,9 +1257,11 @@ static int s3c24xx_serial_probe(struct platform_device *pdev) uart_add_one_port(&s3c24xx_uart_drv, &ourport->port); platform_set_drvdata(pdev, &ourport->port); +#ifdef CONFIG_SAMSUNG_CLOCK ret = device_create_file(&pdev->dev, &dev_attr_clock_source); if (ret < 0) dev_err(&pdev->dev, "failed to add clock source attr.\n"); +#endif ret = s3c24xx_serial_cpufreq_register(ourport); if (ret < 0) @@ -1276,7 +1279,9 @@ static int s3c24xx_serial_remove(struct platform_device *dev) if (port) { s3c24xx_serial_cpufreq_deregister(to_ourport(port)); +#ifdef CONFIG_SAMSUNG_CLOCK device_remove_file(&dev->dev, &dev_attr_clock_source); +#endif uart_remove_one_port(&s3c24xx_uart_drv, port); } -- cgit v1.1 From 9ee51f01eee84a108510ac2794b9a9dff8be6d3f Mon Sep 17 00:00:00 2001 From: Arnd Bergmann Date: Thu, 11 Apr 2013 02:04:48 +0200 Subject: tty: serial/samsung: make register definitions global The registers for the Samsung S3C serial port are currently defined in the platform specific arch/arm/plat-samsung/include/plat/regs-serial.h file, which is not visible to multiplatform capable drivers. Unfortunately, it is not possible to move the file into a more local place as we should normally try to, because the same registers may be used in one of four places: * In the driver itself * In platform-independent ARM code for early debug output * In platform_data definitions * In the Samsung platform power management code I have also found no way to logically split out a platform_data file, other than possibly move everything into include/linux/platform_data, which also felt wrong. The only part of this file that makes sense to keep specific to the s3c24xx platform are the virtual and physical addresses defined here, which are needed in no other location. Signed-off-by: Arnd Bergmann Signed-off-by: Greg Kroah-Hartman --- drivers/tty/serial/samsung.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) (limited to 'drivers/tty/serial') diff --git a/drivers/tty/serial/samsung.c b/drivers/tty/serial/samsung.c index e91378b..6a36956 100644 --- a/drivers/tty/serial/samsung.c +++ b/drivers/tty/serial/samsung.c @@ -39,6 +39,7 @@ #include #include #include +#include #include #include #include @@ -46,10 +47,9 @@ #include -#include - -#include +#ifdef CONFIG_SAMSUNG_CLOCK #include +#endif #include "samsung.h" -- cgit v1.1 From 84f57d9e3685500a7447fc09a6891ce218869174 Mon Sep 17 00:00:00 2001 From: Arnd Bergmann Date: Thu, 11 Apr 2013 02:04:49 +0200 Subject: tty: serial/samsung: fix modular build There are a few bugs in the samsung serial driver when built as a loadable module, which makes the console code unavailable, as well as giving no access to the 'printascii' early debug function. This adds the appropriate compile time conditionals. Signed-off-by: Arnd Bergmann Signed-off-by: Greg Kroah-Hartman --- drivers/tty/serial/samsung.c | 4 ++-- drivers/tty/serial/samsung.h | 4 +++- 2 files changed, 5 insertions(+), 3 deletions(-) (limited to 'drivers/tty/serial') diff --git a/drivers/tty/serial/samsung.c b/drivers/tty/serial/samsung.c index 6a36956..074b919 100644 --- a/drivers/tty/serial/samsung.c +++ b/drivers/tty/serial/samsung.c @@ -898,7 +898,7 @@ console_initcall(s3c24xx_serial_console_init); #define S3C24XX_SERIAL_CONSOLE NULL #endif -#ifdef CONFIG_CONSOLE_POLL +#if defined(CONFIG_SERIAL_SAMSUNG_CONSOLE) && defined(CONFIG_CONSOLE_POLL) static int s3c24xx_serial_get_poll_char(struct uart_port *port); static void s3c24xx_serial_put_poll_char(struct uart_port *port, unsigned char c); @@ -922,7 +922,7 @@ static struct uart_ops s3c24xx_serial_ops = { .request_port = s3c24xx_serial_request_port, .config_port = s3c24xx_serial_config_port, .verify_port = s3c24xx_serial_verify_port, -#ifdef CONFIG_CONSOLE_POLL +#if defined(CONFIG_SERIAL_SAMSUNG_CONSOLE) && defined(CONFIG_CONSOLE_POLL) .poll_get_char = s3c24xx_serial_get_poll_char, .poll_put_char = s3c24xx_serial_put_poll_char, #endif diff --git a/drivers/tty/serial/samsung.h b/drivers/tty/serial/samsung.h index 1a4bca3..00a499e 100644 --- a/drivers/tty/serial/samsung.h +++ b/drivers/tty/serial/samsung.h @@ -76,7 +76,9 @@ struct s3c24xx_uart_port { #define wr_regb(port, reg, val) __raw_writeb(val, portaddr(port, reg)) #define wr_regl(port, reg, val) __raw_writel(val, portaddr(port, reg)) -#ifdef CONFIG_SERIAL_SAMSUNG_DEBUG +#if defined(CONFIG_SERIAL_SAMSUNG_DEBUG) && \ + defined(CONFIG_DEBUG_LL) && \ + !defined(MODULE) extern void printascii(const char *); -- cgit v1.1 From 5ea5b24da80322b8136cb000a7340cdc29a3d6dc Mon Sep 17 00:00:00 2001 From: Heikki Krogerus Date: Wed, 10 Apr 2013 16:58:24 +0300 Subject: serial: 8250_dma: TX cleanup Removing one unneeded uart_write_wakeup(). There is no need to start PIO transfer unless DMA fails, so this also changes serial8250_tx_dma() to return 0 unless that is the case. Signed-off-by: Heikki Krogerus Signed-off-by: Greg Kroah-Hartman --- drivers/tty/serial/8250/8250_dma.c | 11 ++++------- 1 file changed, 4 insertions(+), 7 deletions(-) (limited to 'drivers/tty/serial') diff --git a/drivers/tty/serial/8250/8250_dma.c b/drivers/tty/serial/8250/8250_dma.c index b9f7fd2..ce2518d 100644 --- a/drivers/tty/serial/8250/8250_dma.c +++ b/drivers/tty/serial/8250/8250_dma.c @@ -33,10 +33,8 @@ static void __dma_tx_complete(void *param) if (uart_circ_chars_pending(xmit) < WAKEUP_CHARS) uart_write_wakeup(&p->port); - if (!uart_circ_empty(xmit) && !uart_tx_stopped(&p->port)) { + if (!uart_circ_empty(xmit) && !uart_tx_stopped(&p->port)) serial8250_tx_dma(p); - uart_write_wakeup(&p->port); - } } static void __dma_rx_complete(void *param) @@ -67,12 +65,11 @@ int serial8250_tx_dma(struct uart_8250_port *p) struct circ_buf *xmit = &p->port.state->xmit; struct dma_async_tx_descriptor *desc; - if (dma->tx_running) - return -EBUSY; + if (uart_tx_stopped(&p->port) || dma->tx_running || + uart_circ_empty(xmit)) + return 0; dma->tx_size = CIRC_CNT_TO_END(xmit->head, xmit->tail, UART_XMIT_SIZE); - if (!dma->tx_size) - return -EINVAL; desc = dmaengine_prep_slave_single(dma->txchan, dma->tx_addr + xmit->tail, -- cgit v1.1 From 75df022b5f8982a375adb04e9e4c0a34a9689ed9 Mon Sep 17 00:00:00 2001 From: Heikki Krogerus Date: Wed, 10 Apr 2013 16:58:25 +0300 Subject: serial: 8250_dma: Fix RX handling Overrun, parity and framing errors should be handled in 8250_core. This also adds check for the dma_status and exits if the channel is not idle. Signed-off-by: Heikki Krogerus Signed-off-by: Greg Kroah-Hartman --- drivers/tty/serial/8250/8250_dma.c | 23 ++++++++++++++++------- 1 file changed, 16 insertions(+), 7 deletions(-) (limited to 'drivers/tty/serial') diff --git a/drivers/tty/serial/8250/8250_dma.c b/drivers/tty/serial/8250/8250_dma.c index ce2518d..6643061 100644 --- a/drivers/tty/serial/8250/8250_dma.c +++ b/drivers/tty/serial/8250/8250_dma.c @@ -101,20 +101,29 @@ int serial8250_rx_dma(struct uart_8250_port *p, unsigned int iir) struct dma_tx_state state; int dma_status; - /* - * If RCVR FIFO trigger level was not reached, complete the transfer and - * let 8250.c copy the remaining data. - */ - if ((iir & 0x3f) == UART_IIR_RX_TIMEOUT) { - dma_status = dmaengine_tx_status(dma->rxchan, dma->rx_cookie, - &state); + dma_status = dmaengine_tx_status(dma->rxchan, dma->rx_cookie, &state); + + switch (iir & 0x3f) { + case UART_IIR_RLSI: + /* 8250_core handles errors and break interrupts */ + return -EIO; + case UART_IIR_RX_TIMEOUT: + /* + * If RCVR FIFO trigger level was not reached, complete the + * transfer and let 8250_core copy the remaining data. + */ if (dma_status == DMA_IN_PROGRESS) { dmaengine_pause(dma->rxchan); __dma_rx_complete(p); } return -ETIMEDOUT; + default: + break; } + if (dma_status) + return 0; + desc = dmaengine_prep_slave_single(dma->rxchan, dma->rx_addr, dma->rx_size, DMA_DEV_TO_MEM, DMA_PREP_INTERRUPT | DMA_CTRL_ACK); -- cgit v1.1 From e4fb3b88ebf21e6127ed0e91336752352ba0931e Mon Sep 17 00:00:00 2001 From: Heikki Krogerus Date: Wed, 10 Apr 2013 16:58:26 +0300 Subject: serial: 8250_dma: Use dmaengine helpers to get the slave channels The helper functions in dmaengine API allow the drivers to request slave channels without the filter parameters. They will attempt to extract the needed DMA client information from DT or ACPI, but if such information is not available the filter parameters can still be used. Signed-off-by: Heikki Krogerus Signed-off-by: Greg Kroah-Hartman --- drivers/tty/serial/8250/8250_dma.c | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) (limited to 'drivers/tty/serial') diff --git a/drivers/tty/serial/8250/8250_dma.c b/drivers/tty/serial/8250/8250_dma.c index 6643061..fdb6139e 100644 --- a/drivers/tty/serial/8250/8250_dma.c +++ b/drivers/tty/serial/8250/8250_dma.c @@ -156,14 +156,18 @@ int serial8250_request_dma(struct uart_8250_port *p) dma_cap_set(DMA_SLAVE, mask); /* Get a channel for RX */ - dma->rxchan = dma_request_channel(mask, dma->fn, dma->rx_param); + dma->rxchan = dma_request_slave_channel_compat(mask, + dma->fn, dma->rx_param, + p->port.dev, "rx"); if (!dma->rxchan) return -ENODEV; dmaengine_slave_config(dma->rxchan, &dma->rxconf); /* Get a channel for TX */ - dma->txchan = dma_request_channel(mask, dma->fn, dma->tx_param); + dma->txchan = dma_request_slave_channel_compat(mask, + dma->fn, dma->tx_param, + p->port.dev, "tx"); if (!dma->txchan) { dma_release_channel(dma->rxchan); return -ENODEV; -- cgit v1.1 From ab19479aa1b9708110bc90ba5b6c03b013feaa46 Mon Sep 17 00:00:00 2001 From: Heikki Krogerus Date: Wed, 10 Apr 2013 16:58:27 +0300 Subject: serial: 8250_dma: Provide default slave configuration parameters Some slave channel parameters will be always the same. For example, direction for the Rx channel will always be DMA_DEV_TO_MEM and DMA_MEM_TO_DEV for Tx channel. Signed-off-by: Heikki Krogerus Signed-off-by: Greg Kroah-Hartman --- drivers/tty/serial/8250/8250_dma.c | 10 ++++++++-- 1 file changed, 8 insertions(+), 2 deletions(-) (limited to 'drivers/tty/serial') diff --git a/drivers/tty/serial/8250/8250_dma.c b/drivers/tty/serial/8250/8250_dma.c index fdb6139e..7046769 100644 --- a/drivers/tty/serial/8250/8250_dma.c +++ b/drivers/tty/serial/8250/8250_dma.c @@ -149,8 +149,14 @@ int serial8250_request_dma(struct uart_8250_port *p) struct uart_8250_dma *dma = p->dma; dma_cap_mask_t mask; - dma->rxconf.src_addr = p->port.mapbase + UART_RX; - dma->txconf.dst_addr = p->port.mapbase + UART_TX; + /* Default slave configuration parameters */ + dma->rxconf.direction = DMA_DEV_TO_MEM; + dma->rxconf.src_addr_width = DMA_SLAVE_BUSWIDTH_1_BYTE; + dma->rxconf.src_addr = p->port.mapbase + UART_RX; + + dma->txconf.direction = DMA_MEM_TO_DEV; + dma->txconf.dst_addr_width = DMA_SLAVE_BUSWIDTH_1_BYTE; + dma->txconf.dst_addr = p->port.mapbase + UART_TX; dma_cap_zero(mask); dma_cap_set(DMA_SLAVE, mask); -- cgit v1.1 From ffc3ae6dd925b6a89b2f4f993a732e3b866e6aa0 Mon Sep 17 00:00:00 2001 From: Heikki Krogerus Date: Wed, 10 Apr 2013 16:58:28 +0300 Subject: serial: 8250_dw: Enable runtime PM This allows ACPI to put the device to D3 when it's not used. Signed-off-by: Heikki Krogerus Signed-off-by: Greg Kroah-Hartman --- drivers/tty/serial/8250/8250_dw.c | 61 +++++++++++++++++++++++++++++++++------ 1 file changed, 52 insertions(+), 9 deletions(-) (limited to 'drivers/tty/serial') diff --git a/drivers/tty/serial/8250/8250_dw.c b/drivers/tty/serial/8250/8250_dw.c index 3dedd24..d6aea85 100644 --- a/drivers/tty/serial/8250/8250_dw.c +++ b/drivers/tty/serial/8250/8250_dw.c @@ -27,6 +27,7 @@ #include #include #include +#include #include "8250.h" @@ -115,6 +116,18 @@ static int dw8250_handle_irq(struct uart_port *p) return 0; } +static void +dw8250_do_pm(struct uart_port *port, unsigned int state, unsigned int old) +{ + if (!state) + pm_runtime_get_sync(port->dev); + + serial8250_do_pm(port, state, old); + + if (state) + pm_runtime_put_sync_suspend(port->dev); +} + static int dw8250_probe_of(struct uart_port *p) { struct device_node *np = p->dev->of_node; @@ -293,6 +306,7 @@ static int dw8250_probe(struct platform_device *pdev) uart.port.mapbase = regs->start; uart.port.irq = irq->start; uart.port.handle_irq = dw8250_handle_irq; + uart.port.pm = dw8250_do_pm; uart.port.type = PORT_8250; uart.port.flags = UPF_SHARE_IRQ | UPF_BOOT_AUTOCONF | UPF_FIXED_PORT; uart.port.dev = &pdev->dev; @@ -336,6 +350,9 @@ static int dw8250_probe(struct platform_device *pdev) platform_set_drvdata(pdev, data); + pm_runtime_set_active(&pdev->dev); + pm_runtime_enable(&pdev->dev); + return 0; } @@ -343,37 +360,64 @@ static int dw8250_remove(struct platform_device *pdev) { struct dw8250_data *data = platform_get_drvdata(pdev); + pm_runtime_get_sync(&pdev->dev); + serial8250_unregister_port(data->line); if (!IS_ERR(data->clk)) clk_disable_unprepare(data->clk); + pm_runtime_disable(&pdev->dev); + pm_runtime_put_noidle(&pdev->dev); + return 0; } #ifdef CONFIG_PM -static int dw8250_suspend(struct platform_device *pdev, pm_message_t state) +static int dw8250_suspend(struct device *dev) { - struct dw8250_data *data = platform_get_drvdata(pdev); + struct dw8250_data *data = dev_get_drvdata(dev); serial8250_suspend_port(data->line); return 0; } -static int dw8250_resume(struct platform_device *pdev) +static int dw8250_resume(struct device *dev) { - struct dw8250_data *data = platform_get_drvdata(pdev); + struct dw8250_data *data = dev_get_drvdata(dev); serial8250_resume_port(data->line); return 0; } -#else -#define dw8250_suspend NULL -#define dw8250_resume NULL #endif /* CONFIG_PM */ +#ifdef CONFIG_PM_RUNTIME +static int dw8250_runtime_suspend(struct device *dev) +{ + struct dw8250_data *data = dev_get_drvdata(dev); + + clk_disable_unprepare(data->clk); + + return 0; +} + +static int dw8250_runtime_resume(struct device *dev) +{ + struct dw8250_data *data = dev_get_drvdata(dev); + + clk_prepare_enable(data->clk); + + return 0; +} +#endif + +static const struct dev_pm_ops dw8250_pm_ops = { + SET_SYSTEM_SLEEP_PM_OPS(dw8250_suspend, dw8250_resume) + SET_RUNTIME_PM_OPS(dw8250_runtime_suspend, dw8250_runtime_resume, NULL) +}; + static const struct of_device_id dw8250_of_match[] = { { .compatible = "snps,dw-apb-uart" }, { /* Sentinel */ } @@ -391,13 +435,12 @@ static struct platform_driver dw8250_platform_driver = { .driver = { .name = "dw-apb-uart", .owner = THIS_MODULE, + .pm = &dw8250_pm_ops, .of_match_table = dw8250_of_match, .acpi_match_table = ACPI_PTR(dw8250_acpi_match), }, .probe = dw8250_probe, .remove = dw8250_remove, - .suspend = dw8250_suspend, - .resume = dw8250_resume, }; module_platform_driver(dw8250_platform_driver); -- cgit v1.1 From aea02e87f6076f2a29d537829503e1344e92a3b8 Mon Sep 17 00:00:00 2001 From: Heikki Krogerus Date: Wed, 10 Apr 2013 16:58:29 +0300 Subject: serial: 8250_dw: Support clk framework also with ACPI The Lynxpoint LPSS peripheral clocks are now handled in clk framework so the drivers do not need to take care of them manually. In dw8250_probe_acpi(), the uartclk is now taken from the driver_data only if it was not already set. Signed-off-by: Heikki Krogerus Signed-off-by: Greg Kroah-Hartman --- drivers/tty/serial/8250/8250_dw.c | 18 +++++------------- 1 file changed, 5 insertions(+), 13 deletions(-) (limited to 'drivers/tty/serial') diff --git a/drivers/tty/serial/8250/8250_dw.c b/drivers/tty/serial/8250/8250_dw.c index d6aea85..de7a186 100644 --- a/drivers/tty/serial/8250/8250_dw.c +++ b/drivers/tty/serial/8250/8250_dw.c @@ -36,9 +36,6 @@ #define DW_UART_CPR 0xf4 /* Component Parameter Register */ #define DW_UART_UCV 0xf8 /* UART Component Version */ -/* Intel Low Power Subsystem specific */ -#define LPSS_PRV_CLOCK_PARAMS 0x800 - /* Component Parameter Register bits */ #define DW_UART_CPR_ABP_DATA_WIDTH (3 << 0) #define DW_UART_CPR_AFCE_MODE (1 << 4) @@ -226,7 +223,6 @@ static int dw8250_probe_acpi(struct uart_port *p) { const struct acpi_device_id *id; acpi_status status; - u32 reg; id = acpi_match_device(p->dev->driver->acpi_match_table, p->dev); if (!id) @@ -236,7 +232,9 @@ static int dw8250_probe_acpi(struct uart_port *p) p->serial_in = dw8250_serial_in32; p->serial_out = dw8250_serial_out32; p->regshift = 2; - p->uartclk = (unsigned int)id->driver_data; + + if (!p->uartclk) + p->uartclk = (unsigned int)id->driver_data; status = acpi_walk_resources(ACPI_HANDLE(p->dev), METHOD_NAME__CRS, dw8250_acpi_walk_resource, p); @@ -246,12 +244,6 @@ static int dw8250_probe_acpi(struct uart_port *p) return -ENODEV; } - /* Fix Haswell issue where the clocks do not get enabled */ - if (!strcmp(id->id, "INT33C4") || !strcmp(id->id, "INT33C5")) { - reg = readl(p->membase + LPSS_PRV_CLOCK_PARAMS); - writel(reg | 1, p->membase + LPSS_PRV_CLOCK_PARAMS); - } - return 0; } #else @@ -425,8 +417,8 @@ static const struct of_device_id dw8250_of_match[] = { MODULE_DEVICE_TABLE(of, dw8250_of_match); static const struct acpi_device_id dw8250_acpi_match[] = { - { "INT33C4", 100000000 }, - { "INT33C5", 100000000 }, + { "INT33C4", 0 }, + { "INT33C5", 0 }, { }, }; MODULE_DEVICE_TABLE(acpi, dw8250_acpi_match); -- cgit v1.1 From 94b2b47cf68ce4633a1dbe9d221617404b5de03b Mon Sep 17 00:00:00 2001 From: Heikki Krogerus Date: Wed, 10 Apr 2013 16:58:30 +0300 Subject: serial: 8250_dw: Let ACPI code extract the DMA client info The new ACPI DMA helpers in dmaengine API can take care of extracting all the necessary information regarding DMA. The driver does not need to do this separately any more. Signed-off-by: Heikki Krogerus Signed-off-by: Greg Kroah-Hartman --- drivers/tty/serial/8250/8250_dw.c | 75 +++++---------------------------------- 1 file changed, 9 insertions(+), 66 deletions(-) (limited to 'drivers/tty/serial') diff --git a/drivers/tty/serial/8250/8250_dw.c b/drivers/tty/serial/8250/8250_dw.c index de7a186..09aaea2 100644 --- a/drivers/tty/serial/8250/8250_dw.c +++ b/drivers/tty/serial/8250/8250_dw.c @@ -163,66 +163,10 @@ static int dw8250_probe_of(struct uart_port *p) } #ifdef CONFIG_ACPI -static bool dw8250_acpi_dma_filter(struct dma_chan *chan, void *parm) -{ - return chan->chan_id == *(int *)parm; -} - -static acpi_status -dw8250_acpi_walk_resource(struct acpi_resource *res, void *data) -{ - struct uart_port *p = data; - struct uart_8250_port *port; - struct uart_8250_dma *dma; - struct acpi_resource_fixed_dma *fixed_dma; - struct dma_slave_config *slave; - - port = container_of(p, struct uart_8250_port, port); - - switch (res->type) { - case ACPI_RESOURCE_TYPE_FIXED_DMA: - fixed_dma = &res->data.fixed_dma; - - /* TX comes first */ - if (!port->dma) { - dma = devm_kzalloc(p->dev, sizeof(*dma), GFP_KERNEL); - if (!dma) - return AE_NO_MEMORY; - - port->dma = dma; - slave = &dma->txconf; - - slave->direction = DMA_MEM_TO_DEV; - slave->dst_addr_width = DMA_SLAVE_BUSWIDTH_1_BYTE; - slave->slave_id = fixed_dma->request_lines; - slave->dst_maxburst = port->tx_loadsz / 4; - - dma->tx_chan_id = fixed_dma->channels; - dma->tx_param = &dma->tx_chan_id; - dma->fn = dw8250_acpi_dma_filter; - } else { - dma = port->dma; - slave = &dma->rxconf; - - slave->direction = DMA_DEV_TO_MEM; - slave->src_addr_width = DMA_SLAVE_BUSWIDTH_1_BYTE; - slave->slave_id = fixed_dma->request_lines; - slave->src_maxburst = p->fifosize / 4; - - dma->rx_chan_id = fixed_dma->channels; - dma->rx_param = &dma->rx_chan_id; - } - - break; - } - - return AE_OK; -} - -static int dw8250_probe_acpi(struct uart_port *p) +static int dw8250_probe_acpi(struct uart_8250_port *up) { const struct acpi_device_id *id; - acpi_status status; + struct uart_port *p = &up->port; id = acpi_match_device(p->dev->driver->acpi_match_table, p->dev); if (!id) @@ -236,13 +180,12 @@ static int dw8250_probe_acpi(struct uart_port *p) if (!p->uartclk) p->uartclk = (unsigned int)id->driver_data; - status = acpi_walk_resources(ACPI_HANDLE(p->dev), METHOD_NAME__CRS, - dw8250_acpi_walk_resource, p); - if (ACPI_FAILURE(status)) { - dev_err_ratelimited(p->dev, "%s failed \"%s\"\n", __func__, - acpi_format_exception(status)); - return -ENODEV; - } + up->dma = devm_kzalloc(p->dev, sizeof(*up->dma), GFP_KERNEL); + if (!up->dma) + return -ENOMEM; + + up->dma->rxconf.src_maxburst = p->fifosize / 4; + up->dma->txconf.dst_maxburst = p->fifosize / 4; return 0; } @@ -329,7 +272,7 @@ static int dw8250_probe(struct platform_device *pdev) if (err) return err; } else if (ACPI_HANDLE(&pdev->dev)) { - err = dw8250_probe_acpi(&uart.port); + err = dw8250_probe_acpi(&uart); if (err) return err; } else { -- cgit v1.1 From 2920adb6dfeded0b835a809a1a2c5772d97e5965 Mon Sep 17 00:00:00 2001 From: Heikki Krogerus Date: Wed, 10 Apr 2013 16:58:31 +0300 Subject: serial: 8250_dw: Set port capabilities based on CPR register The Designware UART has an optional support for 16750 compatible Auto Flow Control. This will enable it based on the AFCE bit in Component Parameter Register. Signed-off-by: Heikki Krogerus Signed-off-by: Greg Kroah-Hartman --- drivers/tty/serial/8250/8250_dw.c | 4 ++++ 1 file changed, 4 insertions(+) (limited to 'drivers/tty/serial') diff --git a/drivers/tty/serial/8250/8250_dw.c b/drivers/tty/serial/8250/8250_dw.c index 09aaea2..b7c7d6a 100644 --- a/drivers/tty/serial/8250/8250_dw.c +++ b/drivers/tty/serial/8250/8250_dw.c @@ -221,7 +221,11 @@ static void dw8250_setup_port(struct uart_8250_port *up) p->flags |= UPF_FIXED_TYPE; p->fifosize = DW_UART_CPR_FIFO_SIZE(reg); up->tx_loadsz = p->fifosize; + up->capabilities = UART_CAP_FIFO; } + + if (reg & DW_UART_CPR_AFCE_MODE) + up->capabilities |= UART_CAP_AFE; } static int dw8250_probe(struct platform_device *pdev) -- cgit v1.1 From b88d0826ecb949f62597d4733e50e589058c20b4 Mon Sep 17 00:00:00 2001 From: Heikki Krogerus Date: Thu, 11 Apr 2013 15:43:21 +0300 Subject: serial: 8250_dw: Convert to devm_ioremap() Use resource managed ioremap. Signed-off-by: Heikki Krogerus Signed-off-by: Greg Kroah-Hartman --- drivers/tty/serial/8250/8250_dw.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) (limited to 'drivers/tty/serial') diff --git a/drivers/tty/serial/8250/8250_dw.c b/drivers/tty/serial/8250/8250_dw.c index b7c7d6a..39b7ae4 100644 --- a/drivers/tty/serial/8250/8250_dw.c +++ b/drivers/tty/serial/8250/8250_dw.c @@ -250,7 +250,8 @@ static int dw8250_probe(struct platform_device *pdev) uart.port.flags = UPF_SHARE_IRQ | UPF_BOOT_AUTOCONF | UPF_FIXED_PORT; uart.port.dev = &pdev->dev; - uart.port.membase = ioremap(regs->start, resource_size(regs)); + uart.port.membase = devm_ioremap(&pdev->dev, regs->start, + resource_size(regs)); if (!uart.port.membase) return -ENOMEM; -- cgit v1.1 From 3ec857ffe3ba6e9f567a12d3575dd09d2d41a208 Mon Sep 17 00:00:00 2001 From: Heikki Krogerus Date: Fri, 12 Apr 2013 12:44:27 +0300 Subject: serial: 8250_dw: Fix the stub for dw8250_probe_acpi() This fixes the stub for dw8250_probe_acpi() that is used when compiling without ACPI enabled. The argument type was wrong. Reported-by: kbuild test robot Signed-off-by: Heikki Krogerus Signed-off-by: Greg Kroah-Hartman --- drivers/tty/serial/8250/8250_dw.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers/tty/serial') diff --git a/drivers/tty/serial/8250/8250_dw.c b/drivers/tty/serial/8250/8250_dw.c index 39b7ae4..beaa283 100644 --- a/drivers/tty/serial/8250/8250_dw.c +++ b/drivers/tty/serial/8250/8250_dw.c @@ -190,7 +190,7 @@ static int dw8250_probe_acpi(struct uart_8250_port *up) return 0; } #else -static inline int dw8250_probe_acpi(struct uart_port *p) +static inline int dw8250_probe_acpi(struct uart_8250_port *up) { return -ENODEV; } -- cgit v1.1 From 289b8dd695836fc295cf3cb4e1e520322495556c Mon Sep 17 00:00:00 2001 From: Alexander Shiyan Date: Sat, 13 Apr 2013 08:46:57 +0400 Subject: serial: sccnxp: Do not override device name Signed-off-by: Alexander Shiyan Signed-off-by: Greg Kroah-Hartman --- drivers/tty/serial/sccnxp.c | 2 -- 1 file changed, 2 deletions(-) (limited to 'drivers/tty/serial') diff --git a/drivers/tty/serial/sccnxp.c b/drivers/tty/serial/sccnxp.c index 08dbfb8..b1d04aab 100644 --- a/drivers/tty/serial/sccnxp.c +++ b/drivers/tty/serial/sccnxp.c @@ -789,8 +789,6 @@ static int sccnxp_probe(struct platform_device *pdev) return -EADDRNOTAVAIL; } - dev_set_name(&pdev->dev, SCCNXP_NAME); - s = devm_kzalloc(&pdev->dev, sizeof(struct sccnxp_port), GFP_KERNEL); if (!s) { dev_err(&pdev->dev, "Error allocating port structure\n"); -- cgit v1.1 From 31815c08fc90f44d6165034fd473f23df5d31449 Mon Sep 17 00:00:00 2001 From: Alexander Shiyan Date: Sat, 13 Apr 2013 08:46:58 +0400 Subject: serial: sccnxp: Replace pdata.init/exit with regulator API Typical usage of pdata.init/exit is enable/disable power and/or toggle reset for the target chip. This patch replaces these callbacks with regulator API. Signed-off-by: Alexander Shiyan Signed-off-by: Greg Kroah-Hartman --- drivers/tty/serial/sccnxp.c | 21 +++++++++++++++------ 1 file changed, 15 insertions(+), 6 deletions(-) (limited to 'drivers/tty/serial') diff --git a/drivers/tty/serial/sccnxp.c b/drivers/tty/serial/sccnxp.c index b1d04aab..c773041 100644 --- a/drivers/tty/serial/sccnxp.c +++ b/drivers/tty/serial/sccnxp.c @@ -27,6 +27,7 @@ #include #include #include +#include #define SCCNXP_NAME "uart-sccnxp" #define SCCNXP_MAJOR 204 @@ -131,6 +132,8 @@ struct sccnxp_port { struct timer_list timer; struct sccnxp_pdata pdata; + + struct regulator *regulator; }; static inline u8 sccnxp_raw_read(void __iomem *base, u8 reg, u8 shift) @@ -916,6 +919,16 @@ static int sccnxp_probe(struct platform_device *pdev) goto err_out; } + s->regulator = devm_regulator_get(&pdev->dev, "VCC"); + if (!IS_ERR(s->regulator)) { + ret = regulator_enable(s->regulator); + if (ret) { + dev_err(&pdev->dev, + "Failed to enable regulator: %i\n", ret); + return ret; + } + } + membase = devm_ioremap_resource(&pdev->dev, res); if (IS_ERR(membase)) { ret = PTR_ERR(membase); @@ -965,10 +978,6 @@ static int sccnxp_probe(struct platform_device *pdev) s->imr = 0; sccnxp_write(&s->port[0], SCCNXP_IMR_REG, 0); - /* Board specific configure */ - if (s->pdata.init) - s->pdata.init(); - if (!s->poll) { ret = devm_request_threaded_irq(&pdev->dev, s->irq, NULL, sccnxp_ist, @@ -1009,8 +1018,8 @@ static int sccnxp_remove(struct platform_device *pdev) uart_unregister_driver(&s->uart); platform_set_drvdata(pdev, NULL); - if (s->pdata.exit) - s->pdata.exit(); + if (!IS_ERR(s->regulator)) + return regulator_disable(s->regulator); return 0; } -- cgit v1.1 From 5a65dcc04cda41f4122aacc37a5a348454645399 Mon Sep 17 00:00:00 2001 From: Federico Vaga Date: Mon, 15 Apr 2013 16:01:07 +0200 Subject: serial_core.c: add put_device() after device_find_child() The serial core uses device_find_child() but does not drop the reference to the retrieved child after using it. This patch add the missing put_device(). What I have done to test this issue. I used a machine with an AMBA PL011 serial driver. I tested the patch on next-20120408 because the last branch [next-20120415] does not boot on this board. For test purpose, I added some pr_info() messages to print the refcount after device_find_child() (lines: 1937,2009), and after put_device() (lines: 1947, 2021). Boot the machine *without* put_device(). Then: echo reboot > /sys/power/disk echo disk > /sys/power/state [ 87.058575] uart_suspend_port:1937 refcount 4 [ 87.058582] uart_suspend_port:1947 refcount 4 [ 87.098083] uart_resume_port:2009refcount 5 [ 87.098088] uart_resume_port:2021 refcount 5 echo disk > /sys/power/state [ 103.055574] uart_suspend_port:1937 refcount 6 [ 103.055580] uart_suspend_port:1947 refcount 6 [ 103.095322] uart_resume_port:2009 refcount 7 [ 103.095327] uart_resume_port:2021 refcount 7 echo disk > /sys/power/state [ 252.459580] uart_suspend_port:1937 refcount 8 [ 252.459586] uart_suspend_port:1947 refcount 8 [ 252.499611] uart_resume_port:2009 refcount 9 [ 252.499616] uart_resume_port:2021 refcount 9 The refcount continuously increased. Boot the machine *with* this patch. Then: echo reboot > /sys/power/disk echo disk > /sys/power/state [ 159.333559] uart_suspend_port:1937 refcount 4 [ 159.333566] uart_suspend_port:1947 refcount 3 [ 159.372751] uart_resume_port:2009 refcount 4 [ 159.372755] uart_resume_port:2021 refcount 3 echo disk > /sys/power/state [ 185.713614] uart_suspend_port:1937 refcount 4 [ 185.713621] uart_suspend_port:1947 refcount 3 [ 185.752935] uart_resume_port:2009 refcount 4 [ 185.752940] uart_resume_port:2021 refcount 3 echo disk > /sys/power/state [ 207.458584] uart_suspend_port:1937 refcount 4 [ 207.458591] uart_suspend_port:1947 refcount 3 [ 207.498598] uart_resume_port:2009 refcount 4 [ 207.498605] uart_resume_port:2021 refcount 3 The refcount correctly handled. Signed-off-by: Federico Vaga Cc: stable Signed-off-by: Greg Kroah-Hartman --- drivers/tty/serial/serial_core.c | 4 ++++ 1 file changed, 4 insertions(+) (limited to 'drivers/tty/serial') diff --git a/drivers/tty/serial/serial_core.c b/drivers/tty/serial/serial_core.c index a400002..8fbb6d2 100644 --- a/drivers/tty/serial/serial_core.c +++ b/drivers/tty/serial/serial_core.c @@ -1941,6 +1941,8 @@ int uart_suspend_port(struct uart_driver *drv, struct uart_port *uport) mutex_unlock(&port->mutex); return 0; } + put_device(tty_dev); + if (console_suspend_enabled || !uart_console(uport)) uport->suspended = 1; @@ -2006,9 +2008,11 @@ int uart_resume_port(struct uart_driver *drv, struct uart_port *uport) disable_irq_wake(uport->irq); uport->irq_wake = 0; } + put_device(tty_dev); mutex_unlock(&port->mutex); return 0; } + put_device(tty_dev); uport->suspended = 0; /* -- cgit v1.1 From 78506f223a7bb7d47b1772592932921689adc6d8 Mon Sep 17 00:00:00 2001 From: Jongsung Kim Date: Mon, 15 Apr 2013 14:45:25 +0900 Subject: ARM: PL011: add support for extended FIFO-size of PL011-r1p5 The latest r1p5-revision of the ARM PL011 UART has 32-byte FIFOs, while all earlier ones have 16-byte FIFOs. This patch suggests a way to set the FIFO-size correctly & flexibly by using a member function named get_fifosize, rather than using the fifosize member variable. The function takes the UARTPeriphID, and returns the correct FIFO size. Signed-off-by: Jongsung Kim Signed-off-by: Greg Kroah-Hartman --- drivers/tty/serial/amba-pl011.c | 20 ++++++++++++++++---- 1 file changed, 16 insertions(+), 4 deletions(-) (limited to 'drivers/tty/serial') diff --git a/drivers/tty/serial/amba-pl011.c b/drivers/tty/serial/amba-pl011.c index 6cf861e..b2e9e17 100644 --- a/drivers/tty/serial/amba-pl011.c +++ b/drivers/tty/serial/amba-pl011.c @@ -73,32 +73,44 @@ /* There is by now at least one vendor with differing details, so handle it */ struct vendor_data { unsigned int ifls; - unsigned int fifosize; unsigned int lcrh_tx; unsigned int lcrh_rx; bool oversampling; bool dma_threshold; bool cts_event_workaround; + + unsigned int (*get_fifosize)(unsigned int periphid); }; +static unsigned int get_fifosize_arm(unsigned int periphid) +{ + unsigned int rev = (periphid >> 20) & 0xf; + return rev < 3 ? 16 : 32; +} + static struct vendor_data vendor_arm = { .ifls = UART011_IFLS_RX4_8|UART011_IFLS_TX4_8, - .fifosize = 16, .lcrh_tx = UART011_LCRH, .lcrh_rx = UART011_LCRH, .oversampling = false, .dma_threshold = false, .cts_event_workaround = false, + .get_fifosize = get_fifosize_arm, }; +static unsigned int get_fifosize_st(unsigned int periphid) +{ + return 64; +} + static struct vendor_data vendor_st = { .ifls = UART011_IFLS_RX_HALF|UART011_IFLS_TX_HALF, - .fifosize = 64, .lcrh_tx = ST_UART011_LCRH_TX, .lcrh_rx = ST_UART011_LCRH_RX, .oversampling = true, .dma_threshold = true, .cts_event_workaround = true, + .get_fifosize = get_fifosize_st, }; static struct uart_amba_port *amba_ports[UART_NR]; @@ -2133,7 +2145,7 @@ static int pl011_probe(struct amba_device *dev, const struct amba_id *id) uap->lcrh_rx = vendor->lcrh_rx; uap->lcrh_tx = vendor->lcrh_tx; uap->old_cr = 0; - uap->fifosize = vendor->fifosize; + uap->fifosize = vendor->get_fifosize(dev->periphid); uap->port.dev = &dev->dev; uap->port.mapbase = dev->res.start; uap->port.membase = base; -- cgit v1.1 From 4829e7650f8a40645e4e32b26a37fb833a5e75f0 Mon Sep 17 00:00:00 2001 From: Wolfram Sang Date: Fri, 19 Apr 2013 21:12:17 +0200 Subject: serial: mxs: fix buffer overflow SMATCH correctly found an off-by-one error: drivers/tty/serial/mxs-auart.c:889 auart_console_write() error: buffer overflow 'auart_port' 5 <= 5 Signed-off-by: Wolfram Sang Signed-off-by: Greg Kroah-Hartman --- drivers/tty/serial/mxs-auart.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers/tty/serial') diff --git a/drivers/tty/serial/mxs-auart.c b/drivers/tty/serial/mxs-auart.c index d549fe1..9d357da 100644 --- a/drivers/tty/serial/mxs-auart.c +++ b/drivers/tty/serial/mxs-auart.c @@ -883,7 +883,7 @@ auart_console_write(struct console *co, const char *str, unsigned int count) unsigned int old_ctrl0, old_ctrl2; unsigned int to = 1000; - if (co->index > MXS_AUART_PORTS || co->index < 0) + if (co->index >= MXS_AUART_PORTS || co->index < 0) return; s = auart_port[co->index]; -- cgit v1.1 From 4c24f2c9b671a1dacf2e25a3b059b54bb8899de1 Mon Sep 17 00:00:00 2001 From: Wolfram Sang Date: Fri, 19 Apr 2013 21:06:20 +0200 Subject: serial: mxs: drop superfluous {get|put}_device Driver core already takes care of refcounting, no need to do this on driver level again. Signed-off-by: Wolfram Sang Signed-off-by: Greg Kroah-Hartman --- drivers/tty/serial/mxs-auart.c | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) (limited to 'drivers/tty/serial') diff --git a/drivers/tty/serial/mxs-auart.c b/drivers/tty/serial/mxs-auart.c index 9d357da..62e7d3b 100644 --- a/drivers/tty/serial/mxs-auart.c +++ b/drivers/tty/serial/mxs-auart.c @@ -1103,7 +1103,7 @@ static int mxs_auart_probe(struct platform_device *pdev) s->port.fifosize = 16; s->port.uartclk = clk_get_rate(s->clk); s->port.type = PORT_IMX; - s->port.dev = s->dev = get_device(&pdev->dev); + s->port.dev = s->dev = &pdev->dev; s->ctrl = 0; @@ -1134,7 +1134,6 @@ out_free_irq: auart_port[pdev->id] = NULL; free_irq(s->irq, s); out_free_clk: - put_device(s->dev); clk_put(s->clk); out_free: kfree(s); @@ -1150,7 +1149,6 @@ static int mxs_auart_remove(struct platform_device *pdev) auart_port[pdev->id] = NULL; - put_device(s->dev); clk_put(s->clk); free_irq(s->irq, s); kfree(s); -- cgit v1.1 From 45efcb2d32d35f6509543e477568842d8467035d Mon Sep 17 00:00:00 2001 From: Arnd Bergmann Date: Tue, 23 Apr 2013 18:30:49 +0200 Subject: tty/serial/sirf: fix MODULE_DEVICE_TABLE This fixes building the sirfsorc-uart driver as a loadable module, which uses an incorrect MODULE_DEVICE_TABLE, by changing the reference to the correct symbol. Signed-off-by: Arnd Bergmann Cc: Jiri Slaby Signed-off-by: Greg Kroah-Hartman --- drivers/tty/serial/sirfsoc_uart.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers/tty/serial') diff --git a/drivers/tty/serial/sirfsoc_uart.c b/drivers/tty/serial/sirfsoc_uart.c index 6bbfe99..03465b6 100644 --- a/drivers/tty/serial/sirfsoc_uart.c +++ b/drivers/tty/serial/sirfsoc_uart.c @@ -758,7 +758,7 @@ static struct of_device_id sirfsoc_uart_ids[] = { { .compatible = "sirf,marco-uart", }, {} }; -MODULE_DEVICE_TABLE(of, sirfsoc_serial_of_match); +MODULE_DEVICE_TABLE(of, sirfsoc_uart_ids); static struct platform_driver sirfsoc_uart_driver = { .probe = sirfsoc_uart_probe, -- cgit v1.1