diff options
Diffstat (limited to 'drivers/tty')
-rw-r--r-- | drivers/tty/n_gsm.c | 231 | ||||
-rw-r--r-- | drivers/tty/n_tty.c | 6 | ||||
-rw-r--r-- | drivers/tty/serial/8250/8250_omap.c | 75 | ||||
-rw-r--r-- | drivers/tty/serial/clps711x.c | 23 | ||||
-rw-r--r-- | drivers/tty/serial/earlycon-riscv-sbi.c | 13 | ||||
-rw-r--r-- | drivers/tty/serial/fsl_lpuart.c | 16 | ||||
-rw-r--r-- | drivers/tty/serial/lpc32xx_hs.c | 4 | ||||
-rw-r--r-- | drivers/tty/serial/max310x.c | 7 | ||||
-rw-r--r-- | drivers/tty/serial/meson_uart.c | 13 | ||||
-rw-r--r-- | drivers/tty/serial/qcom_geni_serial.c | 279 | ||||
-rw-r--r-- | drivers/tty/serial/sc16is7xx.c | 4 | ||||
-rw-r--r-- | drivers/tty/serial/sh-sci.c | 71 | ||||
-rw-r--r-- | drivers/tty/sysrq.c | 8 | ||||
-rw-r--r-- | drivers/tty/vt/vc_screen.c | 48 | ||||
-rw-r--r-- | drivers/tty/vt/vt.c | 62 |
15 files changed, 446 insertions, 414 deletions
diff --git a/drivers/tty/n_gsm.c b/drivers/tty/n_gsm.c index 6f7da9a9d76f..d9662848a297 100644 --- a/drivers/tty/n_gsm.c +++ b/drivers/tty/n_gsm.c @@ -143,8 +143,8 @@ struct gsm_dlci { struct sk_buff *skb; /* Frame being sent */ struct sk_buff_head skb_list; /* Queued frames */ /* Data handling callback */ - void (*data)(struct gsm_dlci *dlci, u8 *data, int len); - void (*prev_data)(struct gsm_dlci *dlci, u8 *data, int len); + void (*data)(struct gsm_dlci *dlci, const u8 *data, int len); + void (*prev_data)(struct gsm_dlci *dlci, const u8 *data, int len); struct net_device *net; /* network interface, if created */ }; @@ -988,7 +988,7 @@ static void gsm_dlci_data_kick(struct gsm_dlci *dlci) * Encode up and queue a UI/UIH frame containing our response. */ -static void gsm_control_reply(struct gsm_mux *gsm, int cmd, u8 *data, +static void gsm_control_reply(struct gsm_mux *gsm, int cmd, const u8 *data, int dlen) { struct gsm_msg *msg; @@ -1073,14 +1073,14 @@ static void gsm_process_modem(struct tty_struct *tty, struct gsm_dlci *dlci, * and if need be stuff a break message down the tty. */ -static void gsm_control_modem(struct gsm_mux *gsm, u8 *data, int clen) +static void gsm_control_modem(struct gsm_mux *gsm, const u8 *data, int clen) { unsigned int addr = 0; unsigned int modem = 0; unsigned int brk = 0; struct gsm_dlci *dlci; int len = clen; - u8 *dp = data; + const u8 *dp = data; struct tty_struct *tty; while (gsm_read_ea(&addr, *dp++) == 0) { @@ -1134,13 +1134,13 @@ static void gsm_control_modem(struct gsm_mux *gsm, u8 *data, int clen) * this into the uplink tty if present */ -static void gsm_control_rls(struct gsm_mux *gsm, u8 *data, int clen) +static void gsm_control_rls(struct gsm_mux *gsm, const u8 *data, int clen) { struct tty_port *port; unsigned int addr = 0; u8 bits; int len = clen; - u8 *dp = data; + const u8 *dp = data; while (gsm_read_ea(&addr, *dp++) == 0) { len--; @@ -1189,7 +1189,7 @@ static void gsm_dlci_begin_close(struct gsm_dlci *dlci); */ static void gsm_control_message(struct gsm_mux *gsm, unsigned int command, - u8 *data, int clen) + const u8 *data, int clen) { u8 buf[1]; unsigned long flags; @@ -1261,7 +1261,7 @@ static void gsm_control_message(struct gsm_mux *gsm, unsigned int command, */ static void gsm_control_response(struct gsm_mux *gsm, unsigned int command, - u8 *data, int clen) + const u8 *data, int clen) { struct gsm_control *ctrl; unsigned long flags; @@ -1553,7 +1553,7 @@ static void gsm_dlci_begin_close(struct gsm_dlci *dlci) * open we shovel the bits down it, if not we drop them. */ -static void gsm_dlci_data(struct gsm_dlci *dlci, u8 *data, int clen) +static void gsm_dlci_data(struct gsm_dlci *dlci, const u8 *data, int clen) { /* krefs .. */ struct tty_port *port = &dlci->port; @@ -1603,7 +1603,7 @@ static void gsm_dlci_data(struct gsm_dlci *dlci, u8 *data, int clen) * and we divide up the work accordingly. */ -static void gsm_dlci_command(struct gsm_dlci *dlci, u8 *data, int len) +static void gsm_dlci_command(struct gsm_dlci *dlci, const u8 *data, int len) { /* See what command is involved */ unsigned int command = 0; @@ -2214,6 +2214,111 @@ static struct gsm_mux *gsm_alloc_mux(void) return gsm; } +static void gsm_copy_config_values(struct gsm_mux *gsm, + struct gsm_config *c) +{ + memset(c, 0, sizeof(*c)); + c->adaption = gsm->adaption; + c->encapsulation = gsm->encoding; + c->initiator = gsm->initiator; + c->t1 = gsm->t1; + c->t2 = gsm->t2; + c->t3 = 0; /* Not supported */ + c->n2 = gsm->n2; + if (gsm->ftype == UIH) + c->i = 1; + else + c->i = 2; + pr_debug("Ftype %d i %d\n", gsm->ftype, c->i); + c->mru = gsm->mru; + c->mtu = gsm->mtu; + c->k = 0; +} + +static int gsm_config(struct gsm_mux *gsm, struct gsm_config *c) +{ + int need_close = 0; + int need_restart = 0; + + /* Stuff we don't support yet - UI or I frame transport, windowing */ + if ((c->adaption != 1 && c->adaption != 2) || c->k) + return -EOPNOTSUPP; + /* Check the MRU/MTU range looks sane */ + if (c->mru > MAX_MRU || c->mtu > MAX_MTU || c->mru < 8 || c->mtu < 8) + return -EINVAL; + if (c->n2 < 3) + return -EINVAL; + if (c->encapsulation > 1) /* Basic, advanced, no I */ + return -EINVAL; + if (c->initiator > 1) + return -EINVAL; + if (c->i == 0 || c->i > 2) /* UIH and UI only */ + return -EINVAL; + /* + * See what is needed for reconfiguration + */ + + /* Timing fields */ + if (c->t1 != 0 && c->t1 != gsm->t1) + need_restart = 1; + if (c->t2 != 0 && c->t2 != gsm->t2) + need_restart = 1; + if (c->encapsulation != gsm->encoding) + need_restart = 1; + if (c->adaption != gsm->adaption) + need_restart = 1; + /* Requires care */ + if (c->initiator != gsm->initiator) + need_close = 1; + if (c->mru != gsm->mru) + need_restart = 1; + if (c->mtu != gsm->mtu) + need_restart = 1; + + /* + * Close down what is needed, restart and initiate the new + * configuration + */ + + if (need_close || need_restart) { + int ret; + + ret = gsm_disconnect(gsm); + + if (ret) + return ret; + } + if (need_restart) + gsm_cleanup_mux(gsm); + + gsm->initiator = c->initiator; + gsm->mru = c->mru; + gsm->mtu = c->mtu; + gsm->encoding = c->encapsulation; + gsm->adaption = c->adaption; + gsm->n2 = c->n2; + + if (c->i == 1) + gsm->ftype = UIH; + else if (c->i == 2) + gsm->ftype = UI; + + if (c->t1) + gsm->t1 = c->t1; + if (c->t2) + gsm->t2 = c->t2; + + /* + * FIXME: We need to separate activation/deactivation from adding + * and removing from the mux array + */ + if (need_restart) + gsm_activate_mux(gsm); + if (gsm->initiator && need_close) + gsm_dlci_begin_open(gsm->dlci[0]); + return 0; +} + /** * gsmld_output - write to link * @gsm: our mux @@ -2495,89 +2600,6 @@ static __poll_t gsmld_poll(struct tty_struct *tty, struct file *file, return mask; } -static int gsmld_config(struct tty_struct *tty, struct gsm_mux *gsm, - struct gsm_config *c) -{ - int need_close = 0; - int need_restart = 0; - - /* Stuff we don't support yet - UI or I frame transport, windowing */ - if ((c->adaption != 1 && c->adaption != 2) || c->k) - return -EOPNOTSUPP; - /* Check the MRU/MTU range looks sane */ - if (c->mru > MAX_MRU || c->mtu > MAX_MTU || c->mru < 8 || c->mtu < 8) - return -EINVAL; - if (c->n2 < 3) - return -EINVAL; - if (c->encapsulation > 1) /* Basic, advanced, no I */ - return -EINVAL; - if (c->initiator > 1) - return -EINVAL; - if (c->i == 0 || c->i > 2) /* UIH and UI only */ - return -EINVAL; - /* - * See what is needed for reconfiguration - */ - - /* Timing fields */ - if (c->t1 != 0 && c->t1 != gsm->t1) - need_restart = 1; - if (c->t2 != 0 && c->t2 != gsm->t2) - need_restart = 1; - if (c->encapsulation != gsm->encoding) - need_restart = 1; - if (c->adaption != gsm->adaption) - need_restart = 1; - /* Requires care */ - if (c->initiator != gsm->initiator) - need_close = 1; - if (c->mru != gsm->mru) - need_restart = 1; - if (c->mtu != gsm->mtu) - need_restart = 1; - - /* - * Close down what is needed, restart and initiate the new - * configuration - */ - - if (need_close || need_restart) { - int ret; - - ret = gsm_disconnect(gsm); - - if (ret) - return ret; - } - if (need_restart) - gsm_cleanup_mux(gsm); - - gsm->initiator = c->initiator; - gsm->mru = c->mru; - gsm->mtu = c->mtu; - gsm->encoding = c->encapsulation; - gsm->adaption = c->adaption; - gsm->n2 = c->n2; - - if (c->i == 1) - gsm->ftype = UIH; - else if (c->i == 2) - gsm->ftype = UI; - - if (c->t1) - gsm->t1 = c->t1; - if (c->t2) - gsm->t2 = c->t2; - - /* FIXME: We need to separate activation/deactivation from adding - and removing from the mux array */ - if (need_restart) - gsm_activate_mux(gsm); - if (gsm->initiator && need_close) - gsm_dlci_begin_open(gsm->dlci[0]); - return 0; -} - static int gsmld_ioctl(struct tty_struct *tty, struct file *file, unsigned int cmd, unsigned long arg) { @@ -2586,29 +2608,14 @@ static int gsmld_ioctl(struct tty_struct *tty, struct file *file, switch (cmd) { case GSMIOC_GETCONF: - memset(&c, 0, sizeof(c)); - c.adaption = gsm->adaption; - c.encapsulation = gsm->encoding; - c.initiator = gsm->initiator; - c.t1 = gsm->t1; - c.t2 = gsm->t2; - c.t3 = 0; /* Not supported */ - c.n2 = gsm->n2; - if (gsm->ftype == UIH) - c.i = 1; - else - c.i = 2; - pr_debug("Ftype %d i %d\n", gsm->ftype, c.i); - c.mru = gsm->mru; - c.mtu = gsm->mtu; - c.k = 0; + gsm_copy_config_values(gsm, &c); if (copy_to_user((void *)arg, &c, sizeof(c))) return -EFAULT; return 0; case GSMIOC_SETCONF: if (copy_from_user(&c, (void *)arg, sizeof(c))) return -EFAULT; - return gsmld_config(tty, gsm, &c); + return gsm_config(gsm, &c); default: return n_tty_ioctl_helper(tty, file, cmd, arg); } @@ -2695,7 +2702,7 @@ static void gsm_mux_net_tx_timeout(struct net_device *net) } static void gsm_mux_rx_netchar(struct gsm_dlci *dlci, - unsigned char *in_buf, int size) + const unsigned char *in_buf, int size) { struct net_device *net = dlci->net; struct sk_buff *skb; diff --git a/drivers/tty/n_tty.c b/drivers/tty/n_tty.c index 5dc9686697cf..9cdb0fa3c4bf 100644 --- a/drivers/tty/n_tty.c +++ b/drivers/tty/n_tty.c @@ -50,8 +50,10 @@ #include <linux/ratelimit.h> #include <linux/vmalloc.h> - -/* number of characters left in xmit buffer before select has we have room */ +/* + * Until this number of characters is queued in the xmit buffer, select will + * return "we have room for writes". + */ #define WAKEUP_CHARS 256 /* diff --git a/drivers/tty/serial/8250/8250_omap.c b/drivers/tty/serial/8250/8250_omap.c index ad7ba7d0f28d..0a8316632d75 100644 --- a/drivers/tty/serial/8250/8250_omap.c +++ b/drivers/tty/serial/8250/8250_omap.c @@ -12,6 +12,7 @@ #define SUPPORT_SYSRQ #endif +#include <linux/clk.h> #include <linux/device.h> #include <linux/io.h> #include <linux/module.h> @@ -1134,10 +1135,12 @@ static int omap8250_probe(struct platform_device *pdev) { struct resource *regs = platform_get_resource(pdev, IORESOURCE_MEM, 0); struct resource *irq = platform_get_resource(pdev, IORESOURCE_IRQ, 0); + struct device_node *np = pdev->dev.of_node; struct omap8250_priv *priv; struct uart_8250_port up; int ret; void __iomem *membase; + const struct of_device_id *id; if (!regs || !irq) { dev_err(&pdev->dev, "missing registers or irq\n"); @@ -1194,27 +1197,31 @@ static int omap8250_probe(struct platform_device *pdev) up.port.unthrottle = omap_8250_unthrottle; up.port.rs485_config = omap_8250_rs485_config; - if (pdev->dev.of_node) { - const struct of_device_id *id; - - ret = of_alias_get_id(pdev->dev.of_node, "serial"); - - of_property_read_u32(pdev->dev.of_node, "clock-frequency", - &up.port.uartclk); - priv->wakeirq = irq_of_parse_and_map(pdev->dev.of_node, 1); - - id = of_match_device(of_match_ptr(omap8250_dt_ids), &pdev->dev); - if (id && id->data) - priv->habit |= *(u8 *)id->data; - } else { - ret = pdev->id; - } + ret = of_alias_get_id(np, "serial"); if (ret < 0) { - dev_err(&pdev->dev, "failed to get alias/pdev id\n"); + dev_err(&pdev->dev, "failed to get alias\n"); return ret; } up.port.line = ret; + if (of_property_read_u32(np, "clock-frequency", &up.port.uartclk)) { + struct clk *clk; + + clk = devm_clk_get(&pdev->dev, NULL); + if (IS_ERR(clk)) { + if (PTR_ERR(clk) == -EPROBE_DEFER) + return -EPROBE_DEFER; + } else { + up.port.uartclk = clk_get_rate(clk); + } + } + + priv->wakeirq = irq_of_parse_and_map(np, 1); + + id = of_match_device(of_match_ptr(omap8250_dt_ids), &pdev->dev); + if (id && id->data) + priv->habit |= *(u8 *)id->data; + if (!up.port.uartclk) { up.port.uartclk = DEFAULT_CLK_SPEED; dev_warn(&pdev->dev, @@ -1242,25 +1249,23 @@ static int omap8250_probe(struct platform_device *pdev) omap_serial_fill_features_erratas(&up, priv); up.port.handle_irq = omap8250_no_handle_irq; #ifdef CONFIG_SERIAL_8250_DMA - if (pdev->dev.of_node) { - /* - * Oh DMA support. If there are no DMA properties in the DT then - * we will fall back to a generic DMA channel which does not - * really work here. To ensure that we do not get a generic DMA - * channel assigned, we have the the_no_dma_filter_fn() here. - * To avoid "failed to request DMA" messages we check for DMA - * properties in DT. - */ - ret = of_property_count_strings(pdev->dev.of_node, "dma-names"); - if (ret == 2) { - up.dma = &priv->omap8250_dma; - priv->omap8250_dma.fn = the_no_dma_filter_fn; - priv->omap8250_dma.tx_dma = omap_8250_tx_dma; - priv->omap8250_dma.rx_dma = omap_8250_rx_dma; - priv->omap8250_dma.rx_size = RX_TRIGGER; - priv->omap8250_dma.rxconf.src_maxburst = RX_TRIGGER; - priv->omap8250_dma.txconf.dst_maxburst = TX_TRIGGER; - } + /* + * Oh DMA support. If there are no DMA properties in the DT then + * we will fall back to a generic DMA channel which does not + * really work here. To ensure that we do not get a generic DMA + * channel assigned, we have the the_no_dma_filter_fn() here. + * To avoid "failed to request DMA" messages we check for DMA + * properties in DT. + */ + ret = of_property_count_strings(np, "dma-names"); + if (ret == 2) { + up.dma = &priv->omap8250_dma; + priv->omap8250_dma.fn = the_no_dma_filter_fn; + priv->omap8250_dma.tx_dma = omap_8250_tx_dma; + priv->omap8250_dma.rx_dma = omap_8250_rx_dma; + priv->omap8250_dma.rx_size = RX_TRIGGER; + priv->omap8250_dma.rxconf.src_maxburst = RX_TRIGGER; + priv->omap8250_dma.txconf.dst_maxburst = TX_TRIGGER; } #endif ret = serial8250_register_8250_port(&up); diff --git a/drivers/tty/serial/clps711x.c b/drivers/tty/serial/clps711x.c index 98f193a83392..061590795680 100644 --- a/drivers/tty/serial/clps711x.c +++ b/drivers/tty/serial/clps711x.c @@ -442,14 +442,10 @@ static struct console clps711x_console = { static int uart_clps711x_probe(struct platform_device *pdev) { struct device_node *np = pdev->dev.of_node; - int ret, index = np ? of_alias_get_id(np, "serial") : pdev->id; struct clps711x_port *s; struct resource *res; struct clk *uart_clk; - int irq; - - if (index < 0 || index >= UART_CLPS711X_NR) - return -EINVAL; + int irq, ret; s = devm_kzalloc(&pdev->dev, sizeof(*s), GFP_KERNEL); if (!s) @@ -473,20 +469,11 @@ static int uart_clps711x_probe(struct platform_device *pdev) if (s->rx_irq < 0) return s->rx_irq; - if (!np) { - char syscon_name[9]; - - sprintf(syscon_name, "syscon.%i", index + 1); - s->syscon = syscon_regmap_lookup_by_pdevname(syscon_name); - if (IS_ERR(s->syscon)) - return PTR_ERR(s->syscon); - } else { - s->syscon = syscon_regmap_lookup_by_phandle(np, "syscon"); - if (IS_ERR(s->syscon)) - return PTR_ERR(s->syscon); - } + s->syscon = syscon_regmap_lookup_by_phandle(np, "syscon"); + if (IS_ERR(s->syscon)) + return PTR_ERR(s->syscon); - s->port.line = index; + s->port.line = of_alias_get_id(np, "serial"); s->port.dev = &pdev->dev; s->port.iotype = UPIO_MEM32; s->port.mapbase = res->start; diff --git a/drivers/tty/serial/earlycon-riscv-sbi.c b/drivers/tty/serial/earlycon-riscv-sbi.c index e1a551aae336..ce81523c3113 100644 --- a/drivers/tty/serial/earlycon-riscv-sbi.c +++ b/drivers/tty/serial/earlycon-riscv-sbi.c @@ -10,13 +10,16 @@ #include <linux/serial_core.h> #include <asm/sbi.h> -static void sbi_console_write(struct console *con, - const char *s, unsigned int n) +static void sbi_putc(struct uart_port *port, int c) { - int i; + sbi_console_putchar(c); +} - for (i = 0; i < n; ++i) - sbi_console_putchar(s[i]); +static void sbi_console_write(struct console *con, + const char *s, unsigned n) +{ + struct earlycon_device *dev = con->data; + uart_console_write(&dev->port, s, n, sbi_putc); } static int __init early_sbi_setup(struct earlycon_device *device, diff --git a/drivers/tty/serial/fsl_lpuart.c b/drivers/tty/serial/fsl_lpuart.c index debdd1b9e01a..d0a98ec0ff6c 100644 --- a/drivers/tty/serial/fsl_lpuart.c +++ b/drivers/tty/serial/fsl_lpuart.c @@ -664,8 +664,18 @@ static unsigned int lpuart_tx_empty(struct uart_port *port) static unsigned int lpuart32_tx_empty(struct uart_port *port) { - return (lpuart32_read(port, UARTSTAT) & UARTSTAT_TC) ? - TIOCSER_TEMT : 0; + struct lpuart_port *sport = container_of(port, + struct lpuart_port, port); + unsigned long stat = lpuart32_read(port, UARTSTAT); + unsigned long sfifo = lpuart32_read(port, UARTFIFO); + + if (sport->dma_tx_in_progress) + return 0; + + if (stat & UARTSTAT_TC && sfifo & UARTFIFO_TXEMPT) + return TIOCSER_TEMT; + + return 0; } static bool lpuart_is_32(struct lpuart_port *sport) @@ -1334,6 +1344,8 @@ static int lpuart32_startup(struct uart_port *port) sport->txfifo_size = 0x1 << (((temp >> UARTFIFO_TXSIZE_OFF) & UARTFIFO_FIFOSIZE_MASK) - 1); + sport->port.fifosize = sport->txfifo_size; + sport->rxfifo_size = 0x1 << (((temp >> UARTFIFO_RXSIZE_OFF) & UARTFIFO_FIFOSIZE_MASK) - 1); diff --git a/drivers/tty/serial/lpc32xx_hs.c b/drivers/tty/serial/lpc32xx_hs.c index d1d73261575b..f4e27d0ad947 100644 --- a/drivers/tty/serial/lpc32xx_hs.c +++ b/drivers/tty/serial/lpc32xx_hs.c @@ -151,6 +151,8 @@ static void lpc32xx_hsuart_console_write(struct console *co, const char *s, local_irq_restore(flags); } +static void lpc32xx_loopback_set(resource_size_t mapbase, int state); + static int __init lpc32xx_hsuart_console_setup(struct console *co, char *options) { @@ -170,6 +172,8 @@ static int __init lpc32xx_hsuart_console_setup(struct console *co, if (options) uart_parse_options(options, &baud, &parity, &bits, &flow); + lpc32xx_loopback_set(port->mapbase, 0); /* get out of loopback mode */ + return uart_set_options(port, co, baud, parity, bits, flow); } diff --git a/drivers/tty/serial/max310x.c b/drivers/tty/serial/max310x.c index 4f479841769a..0a04c053654f 100644 --- a/drivers/tty/serial/max310x.c +++ b/drivers/tty/serial/max310x.c @@ -1197,8 +1197,7 @@ static int max310x_probe(struct device *dev, struct max310x_devtype *devtype, return PTR_ERR(regmap); /* Alloc port structure */ - s = devm_kzalloc(dev, sizeof(*s) + - sizeof(struct max310x_one) * devtype->nr, GFP_KERNEL); + s = devm_kzalloc(dev, struct_size(s, p, devtype->nr), GFP_KERNEL); if (!s) { dev_err(dev, "Error allocating port structure\n"); return -ENOMEM; @@ -1467,10 +1466,10 @@ static int __init max310x_uart_init(void) return ret; #ifdef CONFIG_SPI_MASTER - spi_register_driver(&max310x_spi_driver); + ret = spi_register_driver(&max310x_spi_driver); #endif - return 0; + return ret; } module_init(max310x_uart_init); diff --git a/drivers/tty/serial/meson_uart.c b/drivers/tty/serial/meson_uart.c index 8a842591b37c..fbc5bc022a39 100644 --- a/drivers/tty/serial/meson_uart.c +++ b/drivers/tty/serial/meson_uart.c @@ -72,7 +72,8 @@ #define AML_UART_BAUD_USE BIT(23) #define AML_UART_BAUD_XTAL BIT(24) -#define AML_UART_PORT_NUM 6 +#define AML_UART_PORT_NUM 12 +#define AML_UART_PORT_OFFSET 6 #define AML_UART_DEV_NAME "ttyAML" @@ -654,10 +655,20 @@ static int meson_uart_probe(struct platform_device *pdev) struct resource *res_mem, *res_irq; struct uart_port *port; int ret = 0; + int id = -1; if (pdev->dev.of_node) pdev->id = of_alias_get_id(pdev->dev.of_node, "serial"); + if (pdev->id < 0) { + for (id = AML_UART_PORT_OFFSET; id < AML_UART_PORT_NUM; id++) { + if (!meson_ports[id]) { + pdev->id = id; + break; + } + } + } + if (pdev->id < 0 || pdev->id >= AML_UART_PORT_NUM) return -EINVAL; diff --git a/drivers/tty/serial/qcom_geni_serial.c b/drivers/tty/serial/qcom_geni_serial.c index 38016609c7fa..3bcec1c20219 100644 --- a/drivers/tty/serial/qcom_geni_serial.c +++ b/drivers/tty/serial/qcom_geni_serial.c @@ -89,7 +89,7 @@ #define DEF_FIFO_DEPTH_WORDS 16 #define DEF_TX_WM 2 #define DEF_FIFO_WIDTH_BITS 32 -#define UART_CONSOLE_RX_WM 2 +#define UART_RX_WM 2 #define MAX_LOOPBACK_CFG 3 #ifdef CONFIG_CONSOLE_POLL @@ -105,10 +105,6 @@ struct qcom_geni_serial_port { u32 tx_fifo_depth; u32 tx_fifo_width; u32 rx_fifo_depth; - u32 tx_wm; - u32 rx_wm; - u32 rx_rfr; - enum geni_se_xfer_mode xfer_mode; bool setup; int (*handle_rx)(struct uart_port *uport, u32 bytes, bool drop); unsigned int baud; @@ -228,7 +224,7 @@ static unsigned int qcom_geni_serial_get_mctrl(struct uart_port *uport) if (uart_console(uport)) { mctrl |= TIOCM_CTS; } else { - geni_ios = readl_relaxed(uport->membase + SE_GENI_IOS); + geni_ios = readl(uport->membase + SE_GENI_IOS); if (!(geni_ios & IO2_DATA_IN)) mctrl |= TIOCM_CTS; } @@ -246,7 +242,7 @@ static void qcom_geni_serial_set_mctrl(struct uart_port *uport, if (!(mctrl & TIOCM_RTS)) uart_manual_rfr = UART_MANUAL_RFR_EN | UART_RFR_NOT_READY; - writel_relaxed(uart_manual_rfr, uport->membase + SE_UART_MANUAL_RFR); + writel(uart_manual_rfr, uport->membase + SE_UART_MANUAL_RFR); } static const char *qcom_geni_serial_get_type(struct uart_port *uport) @@ -275,9 +271,6 @@ static bool qcom_geni_serial_poll_bit(struct uart_port *uport, unsigned int fifo_bits; unsigned long timeout_us = 20000; - /* Ensure polling is not re-ordered before the prior writes/reads */ - mb(); - if (uport->private_data) { port = to_dev_port(uport, uport); baud = port->baud; @@ -297,7 +290,7 @@ static bool qcom_geni_serial_poll_bit(struct uart_port *uport, */ timeout_us = DIV_ROUND_UP(timeout_us, 10) * 10; while (timeout_us) { - reg = readl_relaxed(uport->membase + offset); + reg = readl(uport->membase + offset); if ((bool)(reg & field) == set) return true; udelay(10); @@ -310,7 +303,7 @@ static void qcom_geni_serial_setup_tx(struct uart_port *uport, u32 xmit_size) { u32 m_cmd; - writel_relaxed(xmit_size, uport->membase + SE_UART_TX_TRANS_LEN); + writel(xmit_size, uport->membase + SE_UART_TX_TRANS_LEN); m_cmd = UART_START_TX << M_OPCODE_SHFT; writel(m_cmd, uport->membase + SE_GENI_M_CMD0); } @@ -323,13 +316,13 @@ static void qcom_geni_serial_poll_tx_done(struct uart_port *uport) done = qcom_geni_serial_poll_bit(uport, SE_GENI_M_IRQ_STATUS, M_CMD_DONE_EN, true); if (!done) { - writel_relaxed(M_GENI_CMD_ABORT, uport->membase + + writel(M_GENI_CMD_ABORT, uport->membase + SE_GENI_M_CMD_CTRL_REG); irq_clear |= M_CMD_ABORT_EN; qcom_geni_serial_poll_bit(uport, SE_GENI_M_IRQ_STATUS, M_CMD_ABORT_EN, true); } - writel_relaxed(irq_clear, uport->membase + SE_GENI_M_IRQ_CLEAR); + writel(irq_clear, uport->membase + SE_GENI_M_IRQ_CLEAR); } static void qcom_geni_serial_abort_rx(struct uart_port *uport) @@ -339,8 +332,8 @@ static void qcom_geni_serial_abort_rx(struct uart_port *uport) writel(S_GENI_CMD_ABORT, uport->membase + SE_GENI_S_CMD_CTRL_REG); qcom_geni_serial_poll_bit(uport, SE_GENI_S_CMD_CTRL_REG, S_GENI_CMD_ABORT, false); - writel_relaxed(irq_clear, uport->membase + SE_GENI_S_IRQ_CLEAR); - writel_relaxed(FORCE_DEFAULT, uport->membase + GENI_FORCE_DEFAULT_REG); + writel(irq_clear, uport->membase + SE_GENI_S_IRQ_CLEAR); + writel(FORCE_DEFAULT, uport->membase + GENI_FORCE_DEFAULT_REG); } #ifdef CONFIG_CONSOLE_POLL @@ -349,19 +342,13 @@ static int qcom_geni_serial_get_char(struct uart_port *uport) u32 rx_fifo; u32 status; - status = readl_relaxed(uport->membase + SE_GENI_M_IRQ_STATUS); - writel_relaxed(status, uport->membase + SE_GENI_M_IRQ_CLEAR); + status = readl(uport->membase + SE_GENI_M_IRQ_STATUS); + writel(status, uport->membase + SE_GENI_M_IRQ_CLEAR); - status = readl_relaxed(uport->membase + SE_GENI_S_IRQ_STATUS); - writel_relaxed(status, uport->membase + SE_GENI_S_IRQ_CLEAR); + status = readl(uport->membase + SE_GENI_S_IRQ_STATUS); + writel(status, uport->membase + SE_GENI_S_IRQ_CLEAR); - /* - * Ensure the writes to clear interrupts is not re-ordered after - * reading the data. - */ - mb(); - - status = readl_relaxed(uport->membase + SE_GENI_RX_FIFO_STATUS); + status = readl(uport->membase + SE_GENI_RX_FIFO_STATUS); if (!(status & RX_FIFO_WC_MSK)) return NO_POLL_CHAR; @@ -372,15 +359,12 @@ static int qcom_geni_serial_get_char(struct uart_port *uport) static void qcom_geni_serial_poll_put_char(struct uart_port *uport, unsigned char c) { - struct qcom_geni_serial_port *port = to_dev_port(uport, uport); - - writel_relaxed(port->tx_wm, uport->membase + SE_GENI_TX_WATERMARK_REG); + writel(DEF_TX_WM, uport->membase + SE_GENI_TX_WATERMARK_REG); qcom_geni_serial_setup_tx(uport, 1); WARN_ON(!qcom_geni_serial_poll_bit(uport, SE_GENI_M_IRQ_STATUS, M_TX_FIFO_WATERMARK_EN, true)); - writel_relaxed(c, uport->membase + SE_GENI_TX_FIFOn); - writel_relaxed(M_TX_FIFO_WATERMARK_EN, uport->membase + - SE_GENI_M_IRQ_CLEAR); + writel(c, uport->membase + SE_GENI_TX_FIFOn); + writel(M_TX_FIFO_WATERMARK_EN, uport->membase + SE_GENI_M_IRQ_CLEAR); qcom_geni_serial_poll_tx_done(uport); } #endif @@ -388,7 +372,7 @@ static void qcom_geni_serial_poll_put_char(struct uart_port *uport, #ifdef CONFIG_SERIAL_QCOM_GENI_CONSOLE static void qcom_geni_serial_wr_char(struct uart_port *uport, int ch) { - writel_relaxed(ch, uport->membase + SE_GENI_TX_FIFOn); + writel(ch, uport->membase + SE_GENI_TX_FIFOn); } static void @@ -407,7 +391,7 @@ __qcom_geni_serial_console_write(struct uart_port *uport, const char *s, bytes_to_send++; } - writel_relaxed(DEF_TX_WM, uport->membase + SE_GENI_TX_WATERMARK_REG); + writel(DEF_TX_WM, uport->membase + SE_GENI_TX_WATERMARK_REG); qcom_geni_serial_setup_tx(uport, bytes_to_send); for (i = 0; i < count; ) { size_t chars_to_write = 0; @@ -425,7 +409,7 @@ __qcom_geni_serial_console_write(struct uart_port *uport, const char *s, chars_to_write = min_t(size_t, count - i, avail / 2); uart_console_write(uport, s + i, chars_to_write, qcom_geni_serial_wr_char); - writel_relaxed(M_TX_FIFO_WATERMARK_EN, uport->membase + + writel(M_TX_FIFO_WATERMARK_EN, uport->membase + SE_GENI_M_IRQ_CLEAR); i += chars_to_write; } @@ -454,7 +438,7 @@ static void qcom_geni_serial_console_write(struct console *co, const char *s, else spin_lock_irqsave(&uport->lock, flags); - geni_status = readl_relaxed(uport->membase + SE_GENI_STATUS); + geni_status = readl(uport->membase + SE_GENI_STATUS); /* Cancel the current write to log the fault */ if (!locked) { @@ -464,11 +448,10 @@ static void qcom_geni_serial_console_write(struct console *co, const char *s, geni_se_abort_m_cmd(&port->se); qcom_geni_serial_poll_bit(uport, SE_GENI_M_IRQ_STATUS, M_CMD_ABORT_EN, true); - writel_relaxed(M_CMD_ABORT_EN, uport->membase + + writel(M_CMD_ABORT_EN, uport->membase + SE_GENI_M_IRQ_CLEAR); } - writel_relaxed(M_CMD_CANCEL_EN, uport->membase + - SE_GENI_M_IRQ_CLEAR); + writel(M_CMD_CANCEL_EN, uport->membase + SE_GENI_M_IRQ_CLEAR); } else if ((geni_status & M_GENI_CMD_ACTIVE) && !port->tx_remaining) { /* * It seems we can't interrupt existing transfers if all data @@ -477,9 +460,8 @@ static void qcom_geni_serial_console_write(struct console *co, const char *s, qcom_geni_serial_poll_tx_done(uport); if (uart_circ_chars_pending(&uport->state->xmit)) { - irq_en = readl_relaxed(uport->membase + - SE_GENI_M_IRQ_EN); - writel_relaxed(irq_en | M_TX_FIFO_WATERMARK_EN, + irq_en = readl(uport->membase + SE_GENI_M_IRQ_EN); + writel(irq_en | M_TX_FIFO_WATERMARK_EN, uport->membase + SE_GENI_M_IRQ_EN); } } @@ -567,29 +549,20 @@ static int handle_rx_uart(struct uart_port *uport, u32 bytes, bool drop) static void qcom_geni_serial_start_tx(struct uart_port *uport) { u32 irq_en; - struct qcom_geni_serial_port *port = to_dev_port(uport, uport); u32 status; - if (port->xfer_mode == GENI_SE_FIFO) { - /* - * readl ensures reading & writing of IRQ_EN register - * is not re-ordered before checking the status of the - * Serial Engine. - */ - status = readl(uport->membase + SE_GENI_STATUS); - if (status & M_GENI_CMD_ACTIVE) - return; + status = readl(uport->membase + SE_GENI_STATUS); + if (status & M_GENI_CMD_ACTIVE) + return; - if (!qcom_geni_serial_tx_empty(uport)) - return; + if (!qcom_geni_serial_tx_empty(uport)) + return; - irq_en = readl_relaxed(uport->membase + SE_GENI_M_IRQ_EN); - irq_en |= M_TX_FIFO_WATERMARK_EN | M_CMD_DONE_EN; + irq_en = readl(uport->membase + SE_GENI_M_IRQ_EN); + irq_en |= M_TX_FIFO_WATERMARK_EN | M_CMD_DONE_EN; - writel_relaxed(port->tx_wm, uport->membase + - SE_GENI_TX_WATERMARK_REG); - writel_relaxed(irq_en, uport->membase + SE_GENI_M_IRQ_EN); - } + writel(DEF_TX_WM, uport->membase + SE_GENI_TX_WATERMARK_REG); + writel(irq_en, uport->membase + SE_GENI_M_IRQ_EN); } static void qcom_geni_serial_stop_tx(struct uart_port *uport) @@ -598,35 +571,24 @@ static void qcom_geni_serial_stop_tx(struct uart_port *uport) u32 status; struct qcom_geni_serial_port *port = to_dev_port(uport, uport); - irq_en = readl_relaxed(uport->membase + SE_GENI_M_IRQ_EN); - irq_en &= ~M_CMD_DONE_EN; - if (port->xfer_mode == GENI_SE_FIFO) { - irq_en &= ~M_TX_FIFO_WATERMARK_EN; - writel_relaxed(0, uport->membase + - SE_GENI_TX_WATERMARK_REG); - } - writel_relaxed(irq_en, uport->membase + SE_GENI_M_IRQ_EN); - status = readl_relaxed(uport->membase + SE_GENI_STATUS); + irq_en = readl(uport->membase + SE_GENI_M_IRQ_EN); + irq_en &= ~(M_CMD_DONE_EN | M_TX_FIFO_WATERMARK_EN); + writel(0, uport->membase + SE_GENI_TX_WATERMARK_REG); + writel(irq_en, uport->membase + SE_GENI_M_IRQ_EN); + status = readl(uport->membase + SE_GENI_STATUS); /* Possible stop tx is called multiple times. */ if (!(status & M_GENI_CMD_ACTIVE)) return; - /* - * Ensure cancel command write is not re-ordered before checking - * the status of the Primary Sequencer. - */ - mb(); - geni_se_cancel_m_cmd(&port->se); if (!qcom_geni_serial_poll_bit(uport, SE_GENI_M_IRQ_STATUS, M_CMD_CANCEL_EN, true)) { geni_se_abort_m_cmd(&port->se); qcom_geni_serial_poll_bit(uport, SE_GENI_M_IRQ_STATUS, M_CMD_ABORT_EN, true); - writel_relaxed(M_CMD_ABORT_EN, uport->membase + - SE_GENI_M_IRQ_CLEAR); + writel(M_CMD_ABORT_EN, uport->membase + SE_GENI_M_IRQ_CLEAR); } - writel_relaxed(M_CMD_CANCEL_EN, uport->membase + SE_GENI_M_IRQ_CLEAR); + writel(M_CMD_CANCEL_EN, uport->membase + SE_GENI_M_IRQ_CLEAR); } static void qcom_geni_serial_start_rx(struct uart_port *uport) @@ -635,27 +597,19 @@ static void qcom_geni_serial_start_rx(struct uart_port *uport) u32 status; struct qcom_geni_serial_port *port = to_dev_port(uport, uport); - status = readl_relaxed(uport->membase + SE_GENI_STATUS); + status = readl(uport->membase + SE_GENI_STATUS); if (status & S_GENI_CMD_ACTIVE) qcom_geni_serial_stop_rx(uport); - /* - * Ensure setup command write is not re-ordered before checking - * the status of the Secondary Sequencer. - */ - mb(); - geni_se_setup_s_cmd(&port->se, UART_START_READ, 0); - if (port->xfer_mode == GENI_SE_FIFO) { - irq_en = readl_relaxed(uport->membase + SE_GENI_S_IRQ_EN); - irq_en |= S_RX_FIFO_WATERMARK_EN | S_RX_FIFO_LAST_EN; - writel_relaxed(irq_en, uport->membase + SE_GENI_S_IRQ_EN); + irq_en = readl(uport->membase + SE_GENI_S_IRQ_EN); + irq_en |= S_RX_FIFO_WATERMARK_EN | S_RX_FIFO_LAST_EN; + writel(irq_en, uport->membase + SE_GENI_S_IRQ_EN); - irq_en = readl_relaxed(uport->membase + SE_GENI_M_IRQ_EN); - irq_en |= M_RX_FIFO_WATERMARK_EN | M_RX_FIFO_LAST_EN; - writel_relaxed(irq_en, uport->membase + SE_GENI_M_IRQ_EN); - } + irq_en = readl(uport->membase + SE_GENI_M_IRQ_EN); + irq_en |= M_RX_FIFO_WATERMARK_EN | M_RX_FIFO_LAST_EN; + writel(irq_en, uport->membase + SE_GENI_M_IRQ_EN); } static void qcom_geni_serial_stop_rx(struct uart_port *uport) @@ -665,32 +619,24 @@ static void qcom_geni_serial_stop_rx(struct uart_port *uport) struct qcom_geni_serial_port *port = to_dev_port(uport, uport); u32 irq_clear = S_CMD_DONE_EN; - if (port->xfer_mode == GENI_SE_FIFO) { - irq_en = readl_relaxed(uport->membase + SE_GENI_S_IRQ_EN); - irq_en &= ~(S_RX_FIFO_WATERMARK_EN | S_RX_FIFO_LAST_EN); - writel_relaxed(irq_en, uport->membase + SE_GENI_S_IRQ_EN); + irq_en = readl(uport->membase + SE_GENI_S_IRQ_EN); + irq_en &= ~(S_RX_FIFO_WATERMARK_EN | S_RX_FIFO_LAST_EN); + writel(irq_en, uport->membase + SE_GENI_S_IRQ_EN); - irq_en = readl_relaxed(uport->membase + SE_GENI_M_IRQ_EN); - irq_en &= ~(M_RX_FIFO_WATERMARK_EN | M_RX_FIFO_LAST_EN); - writel_relaxed(irq_en, uport->membase + SE_GENI_M_IRQ_EN); - } + irq_en = readl(uport->membase + SE_GENI_M_IRQ_EN); + irq_en &= ~(M_RX_FIFO_WATERMARK_EN | M_RX_FIFO_LAST_EN); + writel(irq_en, uport->membase + SE_GENI_M_IRQ_EN); - status = readl_relaxed(uport->membase + SE_GENI_STATUS); + status = readl(uport->membase + SE_GENI_STATUS); /* Possible stop rx is called multiple times. */ if (!(status & S_GENI_CMD_ACTIVE)) return; - /* - * Ensure cancel command write is not re-ordered before checking - * the status of the Secondary Sequencer. - */ - mb(); - geni_se_cancel_s_cmd(&port->se); qcom_geni_serial_poll_bit(uport, SE_GENI_S_CMD_CTRL_REG, S_GENI_CMD_CANCEL, false); - status = readl_relaxed(uport->membase + SE_GENI_STATUS); - writel_relaxed(irq_clear, uport->membase + SE_GENI_S_IRQ_CLEAR); + status = readl(uport->membase + SE_GENI_STATUS); + writel(irq_clear, uport->membase + SE_GENI_S_IRQ_CLEAR); if (status & S_GENI_CMD_ACTIVE) qcom_geni_serial_abort_rx(uport); } @@ -704,7 +650,7 @@ static void qcom_geni_serial_handle_rx(struct uart_port *uport, bool drop) u32 total_bytes; struct qcom_geni_serial_port *port = to_dev_port(uport, uport); - status = readl_relaxed(uport->membase + SE_GENI_RX_FIFO_STATUS); + status = readl(uport->membase + SE_GENI_RX_FIFO_STATUS); word_cnt = status & RX_FIFO_WC_MSK; last_word_partial = status & RX_LAST; last_word_byte_cnt = (status & RX_LAST_BYTE_VALID_MSK) >> @@ -734,7 +680,7 @@ static void qcom_geni_serial_handle_tx(struct uart_port *uport, bool done, unsigned int chunk; int tail; - status = readl_relaxed(uport->membase + SE_GENI_TX_FIFO_STATUS); + status = readl(uport->membase + SE_GENI_TX_FIFO_STATUS); /* Complete the current tx command before taking newly added data */ if (active) @@ -760,9 +706,9 @@ static void qcom_geni_serial_handle_tx(struct uart_port *uport, bool done, qcom_geni_serial_setup_tx(uport, pending); port->tx_remaining = pending; - irq_en = readl_relaxed(uport->membase + SE_GENI_M_IRQ_EN); + irq_en = readl(uport->membase + SE_GENI_M_IRQ_EN); if (!(irq_en & M_TX_FIFO_WATERMARK_EN)) - writel_relaxed(irq_en | M_TX_FIFO_WATERMARK_EN, + writel(irq_en | M_TX_FIFO_WATERMARK_EN, uport->membase + SE_GENI_M_IRQ_EN); } @@ -795,14 +741,14 @@ static void qcom_geni_serial_handle_tx(struct uart_port *uport, bool done, * cleared it in qcom_geni_serial_isr it will have already reasserted * so we must clear it again here after our writes. */ - writel_relaxed(M_TX_FIFO_WATERMARK_EN, + writel(M_TX_FIFO_WATERMARK_EN, uport->membase + SE_GENI_M_IRQ_CLEAR); out_write_wakeup: if (!port->tx_remaining) { - irq_en = readl_relaxed(uport->membase + SE_GENI_M_IRQ_EN); + irq_en = readl(uport->membase + SE_GENI_M_IRQ_EN); if (irq_en & M_TX_FIFO_WATERMARK_EN) - writel_relaxed(irq_en & ~M_TX_FIFO_WATERMARK_EN, + writel(irq_en & ~M_TX_FIFO_WATERMARK_EN, uport->membase + SE_GENI_M_IRQ_EN); } @@ -812,12 +758,12 @@ out_write_wakeup: static irqreturn_t qcom_geni_serial_isr(int isr, void *dev) { - unsigned int m_irq_status; - unsigned int s_irq_status; - unsigned int geni_status; + u32 m_irq_en; + u32 m_irq_status; + u32 s_irq_status; + u32 geni_status; struct uart_port *uport = dev; unsigned long flags; - unsigned int m_irq_en; bool drop_rx = false; struct tty_port *tport = &uport->state->port; struct qcom_geni_serial_port *port = to_dev_port(uport, uport); @@ -826,12 +772,12 @@ static irqreturn_t qcom_geni_serial_isr(int isr, void *dev) return IRQ_NONE; spin_lock_irqsave(&uport->lock, flags); - m_irq_status = readl_relaxed(uport->membase + SE_GENI_M_IRQ_STATUS); - s_irq_status = readl_relaxed(uport->membase + SE_GENI_S_IRQ_STATUS); - geni_status = readl_relaxed(uport->membase + SE_GENI_STATUS); - m_irq_en = readl_relaxed(uport->membase + SE_GENI_M_IRQ_EN); - writel_relaxed(m_irq_status, uport->membase + SE_GENI_M_IRQ_CLEAR); - writel_relaxed(s_irq_status, uport->membase + SE_GENI_S_IRQ_CLEAR); + m_irq_status = readl(uport->membase + SE_GENI_M_IRQ_STATUS); + s_irq_status = readl(uport->membase + SE_GENI_S_IRQ_STATUS); + geni_status = readl(uport->membase + SE_GENI_STATUS); + m_irq_en = readl(uport->membase + SE_GENI_M_IRQ_EN); + writel(m_irq_status, uport->membase + SE_GENI_M_IRQ_CLEAR); + writel(s_irq_status, uport->membase + SE_GENI_S_IRQ_CLEAR); if (WARN_ON(m_irq_status & M_ILLEGAL_CMD_EN)) goto out_unlock; @@ -877,17 +823,6 @@ static void get_tx_fifo_size(struct qcom_geni_serial_port *port) (port->tx_fifo_depth * port->tx_fifo_width) / BITS_PER_BYTE; } -static void set_rfr_wm(struct qcom_geni_serial_port *port) -{ - /* - * Set RFR (Flow off) to FIFO_DEPTH - 2. - * RX WM level at 10% RX_FIFO_DEPTH. - * TX WM level at 10% TX_FIFO_DEPTH. - */ - port->rx_rfr = port->rx_fifo_depth - 2; - port->rx_wm = UART_CONSOLE_RX_WM; - port->tx_wm = DEF_TX_WM; -} static void qcom_geni_serial_shutdown(struct uart_port *uport) { @@ -907,7 +842,7 @@ static void qcom_geni_serial_shutdown(struct uart_port *uport) static int qcom_geni_serial_port_setup(struct uart_port *uport) { struct qcom_geni_serial_port *port = to_dev_port(uport, uport); - unsigned int rxstale = DEFAULT_BITS_PER_CHAR * STALE_TIMEOUT; + u32 rxstale = DEFAULT_BITS_PER_CHAR * STALE_TIMEOUT; u32 proto; if (uart_console(uport)) { @@ -928,21 +863,19 @@ static int qcom_geni_serial_port_setup(struct uart_port *uport) get_tx_fifo_size(port); - set_rfr_wm(port); - writel_relaxed(rxstale, uport->membase + SE_UART_RX_STALE_CNT); + writel(rxstale, uport->membase + SE_UART_RX_STALE_CNT); /* * Make an unconditional cancel on the main sequencer to reset * it else we could end up in data loss scenarios. */ - port->xfer_mode = GENI_SE_FIFO; if (uart_console(uport)) qcom_geni_serial_poll_tx_done(uport); geni_se_config_packing(&port->se, BITS_PER_BYTE, port->tx_bytes_pw, false, true, false); geni_se_config_packing(&port->se, BITS_PER_BYTE, port->rx_bytes_pw, false, false, true); - geni_se_init(&port->se, port->rx_wm, port->rx_rfr); - geni_se_select_mode(&port->se, port->xfer_mode); + geni_se_init(&port->se, UART_RX_WM, port->rx_fifo_depth - 2); + geni_se_select_mode(&port->se, GENI_SE_FIFO); if (!uart_console(uport)) { port->rx_fifo = devm_kcalloc(uport->dev, port->rx_fifo_depth, sizeof(u32), GFP_KERNEL); @@ -1008,14 +941,14 @@ static void qcom_geni_serial_set_termios(struct uart_port *uport, struct ktermios *termios, struct ktermios *old) { unsigned int baud; - unsigned int bits_per_char; - unsigned int tx_trans_cfg; - unsigned int tx_parity_cfg; - unsigned int rx_trans_cfg; - unsigned int rx_parity_cfg; - unsigned int stop_bit_len; + u32 bits_per_char; + u32 tx_trans_cfg; + u32 tx_parity_cfg; + u32 rx_trans_cfg; + u32 rx_parity_cfg; + u32 stop_bit_len; unsigned int clk_div; - unsigned long ser_clk_cfg; + u32 ser_clk_cfg; struct qcom_geni_serial_port *port = to_dev_port(uport, uport); unsigned long clk_rate; @@ -1033,10 +966,10 @@ static void qcom_geni_serial_set_termios(struct uart_port *uport, ser_clk_cfg |= clk_div << CLK_DIV_SHFT; /* parity */ - tx_trans_cfg = readl_relaxed(uport->membase + SE_UART_TX_TRANS_CFG); - tx_parity_cfg = readl_relaxed(uport->membase + SE_UART_TX_PARITY_CFG); - rx_trans_cfg = readl_relaxed(uport->membase + SE_UART_RX_TRANS_CFG); - rx_parity_cfg = readl_relaxed(uport->membase + SE_UART_RX_PARITY_CFG); + tx_trans_cfg = readl(uport->membase + SE_UART_TX_TRANS_CFG); + tx_parity_cfg = readl(uport->membase + SE_UART_TX_PARITY_CFG); + rx_trans_cfg = readl(uport->membase + SE_UART_RX_TRANS_CFG); + rx_parity_cfg = readl(uport->membase + SE_UART_RX_PARITY_CFG); if (termios->c_cflag & PARENB) { tx_trans_cfg |= UART_TX_PAR_EN; rx_trans_cfg |= UART_RX_PAR_EN; @@ -1092,17 +1025,17 @@ static void qcom_geni_serial_set_termios(struct uart_port *uport, uart_update_timeout(uport, termios->c_cflag, baud); if (!uart_console(uport)) - writel_relaxed(port->loopback, + writel(port->loopback, uport->membase + SE_UART_LOOPBACK_CFG); - writel_relaxed(tx_trans_cfg, uport->membase + SE_UART_TX_TRANS_CFG); - writel_relaxed(tx_parity_cfg, uport->membase + SE_UART_TX_PARITY_CFG); - writel_relaxed(rx_trans_cfg, uport->membase + SE_UART_RX_TRANS_CFG); - writel_relaxed(rx_parity_cfg, uport->membase + SE_UART_RX_PARITY_CFG); - writel_relaxed(bits_per_char, uport->membase + SE_UART_TX_WORD_LEN); - writel_relaxed(bits_per_char, uport->membase + SE_UART_RX_WORD_LEN); - writel_relaxed(stop_bit_len, uport->membase + SE_UART_TX_STOP_BIT_LEN); - writel_relaxed(ser_clk_cfg, uport->membase + GENI_SER_M_CLK_CFG); - writel_relaxed(ser_clk_cfg, uport->membase + GENI_SER_S_CLK_CFG); + writel(tx_trans_cfg, uport->membase + SE_UART_TX_TRANS_CFG); + writel(tx_parity_cfg, uport->membase + SE_UART_TX_PARITY_CFG); + writel(rx_trans_cfg, uport->membase + SE_UART_RX_TRANS_CFG); + writel(rx_parity_cfg, uport->membase + SE_UART_RX_PARITY_CFG); + writel(bits_per_char, uport->membase + SE_UART_TX_WORD_LEN); + writel(bits_per_char, uport->membase + SE_UART_RX_WORD_LEN); + writel(stop_bit_len, uport->membase + SE_UART_TX_STOP_BIT_LEN); + writel(ser_clk_cfg, uport->membase + GENI_SER_M_CLK_CFG); + writel(ser_clk_cfg, uport->membase + GENI_SER_S_CLK_CFG); out_restart_rx: qcom_geni_serial_start_rx(uport); } @@ -1193,13 +1126,13 @@ static int __init qcom_geni_serial_earlycon_setup(struct earlycon_device *dev, geni_se_init(&se, DEF_FIFO_DEPTH_WORDS / 2, DEF_FIFO_DEPTH_WORDS - 2); geni_se_select_mode(&se, GENI_SE_FIFO); - writel_relaxed(tx_trans_cfg, uport->membase + SE_UART_TX_TRANS_CFG); - writel_relaxed(tx_parity_cfg, uport->membase + SE_UART_TX_PARITY_CFG); - writel_relaxed(rx_trans_cfg, uport->membase + SE_UART_RX_TRANS_CFG); - writel_relaxed(rx_parity_cfg, uport->membase + SE_UART_RX_PARITY_CFG); - writel_relaxed(bits_per_char, uport->membase + SE_UART_TX_WORD_LEN); - writel_relaxed(bits_per_char, uport->membase + SE_UART_RX_WORD_LEN); - writel_relaxed(stop_bit_len, uport->membase + SE_UART_TX_STOP_BIT_LEN); + writel(tx_trans_cfg, uport->membase + SE_UART_TX_TRANS_CFG); + writel(tx_parity_cfg, uport->membase + SE_UART_TX_PARITY_CFG); + writel(rx_trans_cfg, uport->membase + SE_UART_RX_TRANS_CFG); + writel(rx_parity_cfg, uport->membase + SE_UART_RX_PARITY_CFG); + writel(bits_per_char, uport->membase + SE_UART_TX_WORD_LEN); + writel(bits_per_char, uport->membase + SE_UART_RX_WORD_LEN); + writel(stop_bit_len, uport->membase + SE_UART_TX_STOP_BIT_LEN); dev->con->write = qcom_geni_serial_earlycon_write; dev->con->setup = NULL; diff --git a/drivers/tty/serial/sc16is7xx.c b/drivers/tty/serial/sc16is7xx.c index 268098681856..635178cf3eed 100644 --- a/drivers/tty/serial/sc16is7xx.c +++ b/drivers/tty/serial/sc16is7xx.c @@ -1187,9 +1187,7 @@ static int sc16is7xx_probe(struct device *dev, return PTR_ERR(regmap); /* Alloc port structure */ - s = devm_kzalloc(dev, sizeof(*s) + - sizeof(struct sc16is7xx_one) * devtype->nr_uart, - GFP_KERNEL); + s = devm_kzalloc(dev, struct_size(s, p, devtype->nr_uart), GFP_KERNEL); if (!s) { dev_err(dev, "Error allocating port structure\n"); return -ENOMEM; diff --git a/drivers/tty/serial/sh-sci.c b/drivers/tty/serial/sh-sci.c index 8df0fd824520..cb3d5d37674f 100644 --- a/drivers/tty/serial/sh-sci.c +++ b/drivers/tty/serial/sh-sci.c @@ -1243,12 +1243,22 @@ static int sci_dma_rx_find_active(struct sci_port *s) return -1; } -static void sci_rx_dma_release(struct sci_port *s) +static void sci_dma_rx_chan_invalidate(struct sci_port *s) +{ + unsigned int i; + + s->chan_rx = NULL; + for (i = 0; i < ARRAY_SIZE(s->cookie_rx); i++) + s->cookie_rx[i] = -EINVAL; + s->active_rx = 0; +} + +static void sci_dma_rx_release(struct sci_port *s) { struct dma_chan *chan = s->chan_rx_saved; - s->chan_rx_saved = s->chan_rx = NULL; - s->cookie_rx[0] = s->cookie_rx[1] = -EINVAL; + s->chan_rx_saved = NULL; + sci_dma_rx_chan_invalidate(s); dmaengine_terminate_sync(chan); dma_free_coherent(chan->device->dev, s->buf_len_rx * 2, s->rx_buf[0], sg_dma_address(&s->sg_rx[0])); @@ -1264,6 +1274,20 @@ static void start_hrtimer_us(struct hrtimer *hrt, unsigned long usec) hrtimer_start(hrt, t, HRTIMER_MODE_REL); } +static void sci_dma_rx_reenable_irq(struct sci_port *s) +{ + struct uart_port *port = &s->port; + u16 scr; + + /* Direct new serial port interrupts back to CPU */ + scr = serial_port_in(port, SCSCR); + if (port->type == PORT_SCIFA || port->type == PORT_SCIFB) { + scr &= ~SCSCR_RDRQE; + enable_irq(s->irqs[SCIx_RXI_IRQ]); + } + serial_port_out(port, SCSCR, scr | SCSCR_RIE); +} + static void sci_dma_rx_complete(void *arg) { struct sci_port *s = arg; @@ -1313,12 +1337,13 @@ fail: dev_warn(port->dev, "Failed submitting Rx DMA descriptor\n"); /* Switch to PIO */ spin_lock_irqsave(&port->lock, flags); - s->chan_rx = NULL; - sci_start_rx(port); + dmaengine_terminate_async(chan); + sci_dma_rx_chan_invalidate(s); + sci_dma_rx_reenable_irq(s); spin_unlock_irqrestore(&port->lock, flags); } -static void sci_tx_dma_release(struct sci_port *s) +static void sci_dma_tx_release(struct sci_port *s) { struct dma_chan *chan = s->chan_tx_saved; @@ -1331,7 +1356,7 @@ static void sci_tx_dma_release(struct sci_port *s) dma_release_channel(chan); } -static int sci_submit_rx(struct sci_port *s, bool port_lock_held) +static int sci_dma_rx_submit(struct sci_port *s, bool port_lock_held) { struct dma_chan *chan = s->chan_rx; struct uart_port *port = &s->port; @@ -1367,17 +1392,14 @@ fail: spin_lock_irqsave(&port->lock, flags); if (i) dmaengine_terminate_async(chan); - for (i = 0; i < 2; i++) - s->cookie_rx[i] = -EINVAL; - s->active_rx = 0; - s->chan_rx = NULL; + sci_dma_rx_chan_invalidate(s); sci_start_rx(port); if (!port_lock_held) spin_unlock_irqrestore(&port->lock, flags); return -EAGAIN; } -static void work_fn_tx(struct work_struct *work) +static void sci_dma_tx_work_fn(struct work_struct *work) { struct sci_port *s = container_of(work, struct sci_port, work_tx); struct dma_async_tx_descriptor *desc; @@ -1436,7 +1458,7 @@ switch_to_pio: return; } -static enum hrtimer_restart rx_timer_fn(struct hrtimer *t) +static enum hrtimer_restart sci_dma_rx_timer_fn(struct hrtimer *t) { struct sci_port *s = container_of(t, struct sci_port, rx_timer); struct dma_chan *chan = s->chan_rx; @@ -1446,7 +1468,6 @@ static enum hrtimer_restart rx_timer_fn(struct hrtimer *t) unsigned long flags; unsigned int read; int active, count; - u16 scr; dev_dbg(port->dev, "DMA Rx timed out\n"); @@ -1494,15 +1515,9 @@ static enum hrtimer_restart rx_timer_fn(struct hrtimer *t) } if (port->type == PORT_SCIFA || port->type == PORT_SCIFB) - sci_submit_rx(s, true); + sci_dma_rx_submit(s, true); - /* Direct new serial port interrupts back to CPU */ - scr = serial_port_in(port, SCSCR); - if (port->type == PORT_SCIFA || port->type == PORT_SCIFB) { - scr &= ~SCSCR_RDRQE; - enable_irq(s->irqs[SCIx_RXI_IRQ]); - } - serial_port_out(port, SCSCR, scr | SCSCR_RIE); + sci_dma_rx_reenable_irq(s); spin_unlock_irqrestore(&port->lock, flags); @@ -1580,7 +1595,7 @@ static void sci_request_dma(struct uart_port *port) __func__, UART_XMIT_SIZE, port->state->xmit.buf, &s->tx_dma_addr); - INIT_WORK(&s->work_tx, work_fn_tx); + INIT_WORK(&s->work_tx, sci_dma_tx_work_fn); s->chan_tx_saved = s->chan_tx = chan; } } @@ -1615,12 +1630,12 @@ static void sci_request_dma(struct uart_port *port) } hrtimer_init(&s->rx_timer, CLOCK_MONOTONIC, HRTIMER_MODE_REL); - s->rx_timer.function = rx_timer_fn; + s->rx_timer.function = sci_dma_rx_timer_fn; s->chan_rx_saved = s->chan_rx = chan; if (port->type == PORT_SCIFA || port->type == PORT_SCIFB) - sci_submit_rx(s, false); + sci_dma_rx_submit(s, false); } } @@ -1629,9 +1644,9 @@ static void sci_free_dma(struct uart_port *port) struct sci_port *s = to_sci_port(port); if (s->chan_tx_saved) - sci_tx_dma_release(s); + sci_dma_tx_release(s); if (s->chan_rx_saved) - sci_rx_dma_release(s); + sci_dma_rx_release(s); } static void sci_flush_buffer(struct uart_port *port) @@ -1669,7 +1684,7 @@ static irqreturn_t sci_rx_interrupt(int irq, void *ptr) disable_irq_nosync(irq); scr |= SCSCR_RDRQE; } else { - if (sci_submit_rx(s, false) < 0) + if (sci_dma_rx_submit(s, false) < 0) goto handle_pio; scr &= ~SCSCR_RIE; diff --git a/drivers/tty/sysrq.c b/drivers/tty/sysrq.c index 1f03078ec352..fa0ce7dd9e24 100644 --- a/drivers/tty/sysrq.c +++ b/drivers/tty/sysrq.c @@ -539,7 +539,6 @@ void __handle_sysrq(int key, bool check_mask) */ orig_log_level = console_loglevel; console_loglevel = CONSOLE_LOGLEVEL_DEFAULT; - pr_info("SysRq : "); op_p = __sysrq_get_key_op(key); if (op_p) { @@ -548,14 +547,15 @@ void __handle_sysrq(int key, bool check_mask) * should not) and is the invoked operation enabled? */ if (!check_mask || sysrq_on_mask(op_p->enable_mask)) { - pr_cont("%s\n", op_p->action_msg); + pr_info("%s\n", op_p->action_msg); console_loglevel = orig_log_level; op_p->handler(key); } else { - pr_cont("This sysrq operation is disabled.\n"); + pr_info("This sysrq operation is disabled.\n"); + console_loglevel = orig_log_level; } } else { - pr_cont("HELP : "); + pr_info("HELP : "); /* Only print the help msg once per handler */ for (i = 0; i < ARRAY_SIZE(sysrq_key_table); i++) { if (sysrq_key_table[i]) { diff --git a/drivers/tty/vt/vc_screen.c b/drivers/tty/vt/vc_screen.c index 2384ea85ffaf..160f46115aaa 100644 --- a/drivers/tty/vt/vc_screen.c +++ b/drivers/tty/vt/vc_screen.c @@ -80,7 +80,7 @@ struct vcs_poll_data { struct notifier_block notifier; unsigned int cons_num; - bool seen_last_update; + int event; wait_queue_head_t waitq; struct fasync_struct *fasync; }; @@ -93,9 +93,18 @@ vcs_notifier(struct notifier_block *nb, unsigned long code, void *_param) struct vcs_poll_data *poll = container_of(nb, struct vcs_poll_data, notifier); int currcons = poll->cons_num; - - if (code != VT_UPDATE) + int fa_band; + + switch (code) { + case VT_UPDATE: + fa_band = POLL_PRI; + break; + case VT_DEALLOCATE: + fa_band = POLL_HUP; + break; + default: return NOTIFY_DONE; + } if (currcons == 0) currcons = fg_console; @@ -104,9 +113,9 @@ vcs_notifier(struct notifier_block *nb, unsigned long code, void *_param) if (currcons != vc->vc_num) return NOTIFY_DONE; - poll->seen_last_update = false; + poll->event = code; wake_up_interruptible(&poll->waitq); - kill_fasync(&poll->fasync, SIGIO, POLL_IN); + kill_fasync(&poll->fasync, SIGIO, fa_band); return NOTIFY_OK; } @@ -131,6 +140,15 @@ vcs_poll_data_get(struct file *file) poll->cons_num = console(file_inode(file)); init_waitqueue_head(&poll->waitq); poll->notifier.notifier_call = vcs_notifier; + /* + * In order not to lose any update event, we must pretend one might + * have occurred before we have a chance to register our notifier. + * This is also how user space has come to detect which kernels + * support POLLPRI on /dev/vcs* devices i.e. using poll() with + * POLLPRI and a zero timeout. + */ + poll->event = VT_UPDATE; + if (register_vt_notifier(&poll->notifier) != 0) { kfree(poll); return NULL; @@ -261,7 +279,7 @@ vcs_read(struct file *file, char __user *buf, size_t count, loff_t *ppos) poll = file->private_data; if (count && poll) - poll->seen_last_update = true; + poll->event = 0; read = 0; ret = 0; while (count) { @@ -335,8 +353,9 @@ vcs_read(struct file *file, char __user *buf, size_t count, loff_t *ppos) if (p < HEADER_SIZE) { size_t tmp_count; - con_buf0[0] = (char)vc->vc_rows; - con_buf0[1] = (char)vc->vc_cols; + /* clamp header values if they don't fit */ + con_buf0[0] = min(vc->vc_rows, 0xFFu); + con_buf0[1] = min(vc->vc_cols, 0xFFu); getconsxy(vc, con_buf0 + 2); con_buf_start += p; @@ -615,12 +634,21 @@ static __poll_t vcs_poll(struct file *file, poll_table *wait) { struct vcs_poll_data *poll = vcs_poll_data_get(file); - __poll_t ret = DEFAULT_POLLMASK|EPOLLERR|EPOLLPRI; + __poll_t ret = DEFAULT_POLLMASK|EPOLLERR; if (poll) { poll_wait(file, &poll->waitq, wait); - if (poll->seen_last_update) + switch (poll->event) { + case VT_UPDATE: + ret = DEFAULT_POLLMASK|EPOLLPRI; + break; + case VT_DEALLOCATE: + ret = DEFAULT_POLLMASK|EPOLLHUP|EPOLLERR; + break; + case 0: ret = DEFAULT_POLLMASK; + break; + } } return ret; } diff --git a/drivers/tty/vt/vt.c b/drivers/tty/vt/vt.c index bba75560d11e..cbf6cb139dcb 100644 --- a/drivers/tty/vt/vt.c +++ b/drivers/tty/vt/vt.c @@ -1342,6 +1342,8 @@ struct vc_data *vc_deallocate(unsigned int currcons) * VT102 emulator */ +enum { EPecma = 0, EPdec, EPeq, EPgt, EPlt}; + #define set_kbd(vc, x) vt_set_kbd_mode_bit((vc)->vc_num, (x)) #define clr_kbd(vc, x) vt_clr_kbd_mode_bit((vc)->vc_num, (x)) #define is_kbd(vc, x) vt_get_kbd_mode_bit((vc)->vc_num, (x)) @@ -1628,9 +1630,9 @@ static void rgb_background(struct vc_data *vc, const struct rgb *c) /* * ITU T.416 Higher colour modes. They break the usual properties of SGR codes - * and thus need to be detected and ignored by hand. Strictly speaking, that - * standard also wants : rather than ; as separators, contrary to ECMA-48, but - * no one produces such codes and almost no one accepts them. + * and thus need to be detected and ignored by hand. That standard also + * wants : rather than ; as separators but sequences containing : are currently + * completely ignored by the parser. * * Subcommands 3 (CMY) and 4 (CMYK) are so insane there's no point in * supporting them. @@ -1815,7 +1817,7 @@ static void set_mode(struct vc_data *vc, int on_off) int i; for (i = 0; i <= vc->vc_npar; i++) - if (vc->vc_ques) { + if (vc->vc_priv == EPdec) { switch(vc->vc_par[i]) { /* DEC private modes set/reset */ case 1: /* Cursor keys send ^[Ox/^[[x */ if (on_off) @@ -2022,7 +2024,7 @@ static void restore_cur(struct vc_data *vc) } enum { ESnormal, ESesc, ESsquare, ESgetpars, ESfunckey, - EShash, ESsetG0, ESsetG1, ESpercent, ESignore, ESnonstd, + EShash, ESsetG0, ESsetG1, ESpercent, EScsiignore, ESnonstd, ESpalette, ESosc }; /* console_lock is held (except via vc_init()) */ @@ -2031,7 +2033,7 @@ static void reset_terminal(struct vc_data *vc, int do_clear) vc->vc_top = 0; vc->vc_bottom = vc->vc_rows; vc->vc_state = ESnormal; - vc->vc_ques = 0; + vc->vc_priv = EPecma; vc->vc_translate = set_translate(LAT1_MAP, vc); vc->vc_G0_charset = LAT1_MAP; vc->vc_G1_charset = GRAF_MAP; @@ -2112,6 +2114,7 @@ static void do_con_trol(struct tty_struct *tty, struct vc_data *vc, int c) lf(vc); if (!is_kbd(vc, lnm)) return; + /* fall through */ case 13: cr(vc); return; @@ -2234,9 +2237,22 @@ static void do_con_trol(struct tty_struct *tty, struct vc_data *vc, int c) vc->vc_state=ESfunckey; return; } - vc->vc_ques = (c == '?'); - if (vc->vc_ques) + switch (c) { + case '?': + vc->vc_priv = EPdec; + return; + case '>': + vc->vc_priv = EPgt; return; + case '=': + vc->vc_priv = EPeq; + return; + case '<': + vc->vc_priv = EPlt; + return; + } + vc->vc_priv = EPecma; + /* fall through */ case ESgetpars: if (c == ';' && vc->vc_npar < NPAR - 1) { vc->vc_npar++; @@ -2246,16 +2262,22 @@ static void do_con_trol(struct tty_struct *tty, struct vc_data *vc, int c) vc->vc_par[vc->vc_npar] += c - '0'; return; } + if (c >= 0x20 && c <= 0x3f) { /* 0x2x, 0x3a and 0x3c - 0x3f */ + vc->vc_state = EScsiignore; + return; + } vc->vc_state = ESnormal; switch(c) { case 'h': - set_mode(vc, 1); + if (vc->vc_priv <= EPdec) + set_mode(vc, 1); return; case 'l': - set_mode(vc, 0); + if (vc->vc_priv <= EPdec) + set_mode(vc, 0); return; case 'c': - if (vc->vc_ques) { + if (vc->vc_priv == EPdec) { if (vc->vc_par[0]) vc->vc_cursor_type = vc->vc_par[0] | (vc->vc_par[1] << 8) | (vc->vc_par[2] << 16); else @@ -2264,7 +2286,7 @@ static void do_con_trol(struct tty_struct *tty, struct vc_data *vc, int c) } break; case 'm': - if (vc->vc_ques) { + if (vc->vc_priv == EPdec) { clear_selection(); if (vc->vc_par[0]) vc->vc_complement_mask = vc->vc_par[0] << 8 | vc->vc_par[1]; @@ -2274,7 +2296,7 @@ static void do_con_trol(struct tty_struct *tty, struct vc_data *vc, int c) } break; case 'n': - if (!vc->vc_ques) { + if (vc->vc_priv == EPecma) { if (vc->vc_par[0] == 5) status_report(tty); else if (vc->vc_par[0] == 6) @@ -2282,8 +2304,8 @@ static void do_con_trol(struct tty_struct *tty, struct vc_data *vc, int c) } return; } - if (vc->vc_ques) { - vc->vc_ques = 0; + if (vc->vc_priv != EPecma) { + vc->vc_priv = EPecma; return; } switch(c) { @@ -2406,6 +2428,11 @@ static void do_con_trol(struct tty_struct *tty, struct vc_data *vc, int c) return; } return; + case EScsiignore: + if (c >= 20 && c <= 0x3f) + return; + vc->vc_state = ESnormal; + return; case ESpercent: vc->vc_state = ESnormal; switch (c) { @@ -4591,8 +4618,9 @@ EXPORT_SYMBOL_GPL(screen_pos); void getconsxy(struct vc_data *vc, unsigned char *p) { - p[0] = vc->vc_x; - p[1] = vc->vc_y; + /* clamp values if they don't fit */ + p[0] = min(vc->vc_x, 0xFFu); + p[1] = min(vc->vc_y, 0xFFu); } void putconsxy(struct vc_data *vc, unsigned char *p) |