From 7ee7482e60fd7a870ca7cd13f4c7bc3841f99815 Mon Sep 17 00:00:00 2001 From: Jing Yao Date: Thu, 4 Nov 2021 11:47:54 +0000 Subject: serial: 8250: replace snprintf in show functions with sysfs_emit coccicheck complains about the use of snprintf() in sysfs show functions: WARNING use scnprintf or sprintf Use sysfs_emit instead of scnprintf or sprintf makes more sense. Reported-by: Zeal Robot Reviewed-by: Johan Hovold Signed-off-by: Jing Yao Link: https://lore.kernel.org/r/20211104114754.30983-1-yao.jing2@zte.com.cn Signed-off-by: Greg Kroah-Hartman --- drivers/tty/serial/8250/8250_port.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers/tty') diff --git a/drivers/tty/serial/8250/8250_port.c b/drivers/tty/serial/8250/8250_port.c index 5775cbff8f6e..3d58f383152e 100644 --- a/drivers/tty/serial/8250/8250_port.c +++ b/drivers/tty/serial/8250/8250_port.c @@ -3099,7 +3099,7 @@ static ssize_t rx_trig_bytes_show(struct device *dev, if (rxtrig_bytes < 0) return rxtrig_bytes; - return snprintf(buf, PAGE_SIZE, "%d\n", rxtrig_bytes); + return sysfs_emit(buf, "%d\n", rxtrig_bytes); } static int do_set_rxtrig(struct tty_port *port, unsigned char bytes) -- cgit From 635e4172bd0a43af943fb164799965fc9a9a705d Mon Sep 17 00:00:00 2001 From: Lukas Bulwahn Date: Tue, 2 Nov 2021 07:38:10 +0100 Subject: arm: remove zte zx platform left-over Commit 89d4f98ae90d ("ARM: remove zte zx platform") missed to remove some definitions for this platform's debug and serial, e.g., code dependent on the config DEBUG_ZTE_ZX. Fortunately, ./scripts/checkkconfigsymbols.py detects this and warns: DEBUG_ZTE_ZX Referencing files: arch/arm/include/debug/pl01x.S Further review by Arnd Bergmann identified even more dead code in the amba serial driver. Remove all this left-over from the zte zx platform. Reviewed-by: Arnd Bergmann Signed-off-by: Lukas Bulwahn Link: https://lore.kernel.org/r/20211102063810.932-1-lukas.bulwahn@gmail.com Signed-off-by: Greg Kroah-Hartman --- drivers/tty/serial/amba-pl011.c | 37 ------------------------------------- 1 file changed, 37 deletions(-) (limited to 'drivers/tty') diff --git a/drivers/tty/serial/amba-pl011.c b/drivers/tty/serial/amba-pl011.c index d361cd84ff8c..c9534e229166 100644 --- a/drivers/tty/serial/amba-pl011.c +++ b/drivers/tty/serial/amba-pl011.c @@ -188,38 +188,6 @@ static struct vendor_data vendor_st = { .get_fifosize = get_fifosize_st, }; -static const u16 pl011_zte_offsets[REG_ARRAY_SIZE] = { - [REG_DR] = ZX_UART011_DR, - [REG_FR] = ZX_UART011_FR, - [REG_LCRH_RX] = ZX_UART011_LCRH, - [REG_LCRH_TX] = ZX_UART011_LCRH, - [REG_IBRD] = ZX_UART011_IBRD, - [REG_FBRD] = ZX_UART011_FBRD, - [REG_CR] = ZX_UART011_CR, - [REG_IFLS] = ZX_UART011_IFLS, - [REG_IMSC] = ZX_UART011_IMSC, - [REG_RIS] = ZX_UART011_RIS, - [REG_MIS] = ZX_UART011_MIS, - [REG_ICR] = ZX_UART011_ICR, - [REG_DMACR] = ZX_UART011_DMACR, -}; - -static unsigned int get_fifosize_zte(struct amba_device *dev) -{ - return 16; -} - -static struct vendor_data vendor_zte = { - .reg_offset = pl011_zte_offsets, - .access_32b = true, - .ifls = UART011_IFLS_RX4_8|UART011_IFLS_TX4_8, - .fr_busy = ZX_UART01x_FR_BUSY, - .fr_dsr = ZX_UART01x_FR_DSR, - .fr_cts = ZX_UART01x_FR_CTS, - .fr_ri = ZX_UART011_FR_RI, - .get_fifosize = get_fifosize_zte, -}; - /* Deals with DMA transactions */ struct pl011_sgbuf { @@ -2974,11 +2942,6 @@ static const struct amba_id pl011_ids[] = { .mask = 0x00ffffff, .data = &vendor_st, }, - { - .id = AMBA_LINUX_ID(0x00, 0x1, 0xffe), - .mask = 0x00ffffff, - .data = &vendor_zte, - }, { 0, 0 }, }; -- cgit From ea502201da45d3737a77d17e96d952d0a85cdc7d Mon Sep 17 00:00:00 2001 From: Jiri Slaby Date: Thu, 18 Nov 2021 08:17:16 +0100 Subject: n_gsm: remove unused parameters from gsm_error() data and flag are unused in gsm_error(), so remove them. Signed-off-by: Jiri Slaby Link: https://lore.kernel.org/r/20211118071716.11984-1-jslaby@suse.cz Signed-off-by: Greg Kroah-Hartman --- drivers/tty/n_gsm.c | 7 ++----- 1 file changed, 2 insertions(+), 5 deletions(-) (limited to 'drivers/tty') diff --git a/drivers/tty/n_gsm.c b/drivers/tty/n_gsm.c index 0b96b14bbfe1..68e6df27d2e3 100644 --- a/drivers/tty/n_gsm.c +++ b/drivers/tty/n_gsm.c @@ -2074,8 +2074,6 @@ static void gsm1_receive(struct gsm_mux *gsm, unsigned char c) /** * gsm_error - handle tty error * @gsm: ldisc data - * @data: byte received (may be invalid) - * @flag: error received * * Handle an error in the receipt of data for a frame. Currently we just * go back to hunting for a SOF. @@ -2083,8 +2081,7 @@ static void gsm1_receive(struct gsm_mux *gsm, unsigned char c) * FIXME: better diagnostics ? */ -static void gsm_error(struct gsm_mux *gsm, - unsigned char data, unsigned char flag) +static void gsm_error(struct gsm_mux *gsm) { gsm->state = GSM_SEARCH; gsm->io_error++; @@ -2504,7 +2501,7 @@ static void gsmld_receive_buf(struct tty_struct *tty, const unsigned char *cp, case TTY_BREAK: case TTY_PARITY: case TTY_FRAME: - gsm_error(gsm, *cp, flags); + gsm_error(gsm); break; default: WARN_ONCE(1, "%s: unknown flag %d\n", -- cgit From 463d4c74bffd7209914bf1eefb6d2fa991422863 Mon Sep 17 00:00:00 2001 From: Jiri Slaby Date: Thu, 18 Nov 2021 08:19:08 +0100 Subject: tty: remove TTY_SOFT_SAK part from __do_SAK() Remove the TTY_SOFT_SAK part. It is never defined, so this is only confusing. It was actually never defined since its introduction in 0.99.14g. Signed-off-by: Jiri Slaby Link: https://lore.kernel.org/r/20211118071911.12059-2-jslaby@suse.cz Signed-off-by: Greg Kroah-Hartman --- drivers/tty/tty_io.c | 4 ---- 1 file changed, 4 deletions(-) (limited to 'drivers/tty') diff --git a/drivers/tty/tty_io.c b/drivers/tty/tty_io.c index 6616d4a0d41d..829944dfaf48 100644 --- a/drivers/tty/tty_io.c +++ b/drivers/tty/tty_io.c @@ -3028,9 +3028,6 @@ static int this_tty(const void *t, struct file *file, unsigned fd) */ void __do_SAK(struct tty_struct *tty) { -#ifdef TTY_SOFT_SAK - tty_hangup(tty); -#else struct task_struct *g, *p; struct pid *session; int i; @@ -3074,7 +3071,6 @@ void __do_SAK(struct tty_struct *tty) } while_each_thread(g, p); read_unlock(&tasklist_lock); put_pid(session); -#endif } static void do_SAK_work(struct work_struct *work) -- cgit From 8cb28417dd2ce46938fea9aca9f56fb1f7b1934a Mon Sep 17 00:00:00 2001 From: Jiri Slaby Date: Thu, 18 Nov 2021 08:19:09 +0100 Subject: tty: remove tty NULL check from __do_SAK() Both do_SAK_work() and vc_SAK() provide a valid tty to __do_SAK(), so remove the check. Signed-off-by: Jiri Slaby Link: https://lore.kernel.org/r/20211118071911.12059-3-jslaby@suse.cz Signed-off-by: Greg Kroah-Hartman --- drivers/tty/tty_io.c | 3 --- 1 file changed, 3 deletions(-) (limited to 'drivers/tty') diff --git a/drivers/tty/tty_io.c b/drivers/tty/tty_io.c index 829944dfaf48..8e653bb4d7c7 100644 --- a/drivers/tty/tty_io.c +++ b/drivers/tty/tty_io.c @@ -3033,9 +3033,6 @@ void __do_SAK(struct tty_struct *tty) int i; unsigned long flags; - if (!tty) - return; - spin_lock_irqsave(&tty->ctrl.lock, flags); session = get_pid(tty->ctrl.session); spin_unlock_irqrestore(&tty->ctrl.lock, flags); -- cgit From 954a0881a9d4f92bd645ebb06a5f939a19c82056 Mon Sep 17 00:00:00 2001 From: Jiri Slaby Date: Thu, 18 Nov 2021 08:19:10 +0100 Subject: tty: clean up whitespace in __do_SAK() Remove spaces before the 'i' variable declaration and wrap parameters of group_send_sig_info(). Signed-off-by: Jiri Slaby Link: https://lore.kernel.org/r/20211118071911.12059-4-jslaby@suse.cz Signed-off-by: Greg Kroah-Hartman --- drivers/tty/tty_io.c | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) (limited to 'drivers/tty') diff --git a/drivers/tty/tty_io.c b/drivers/tty/tty_io.c index 8e653bb4d7c7..99cad1560876 100644 --- a/drivers/tty/tty_io.c +++ b/drivers/tty/tty_io.c @@ -3030,7 +3030,7 @@ void __do_SAK(struct tty_struct *tty) { struct task_struct *g, *p; struct pid *session; - int i; + int i; unsigned long flags; spin_lock_irqsave(&tty->ctrl.lock, flags); @@ -3054,7 +3054,8 @@ void __do_SAK(struct tty_struct *tty) if (p->signal->tty == tty) { tty_notice(tty, "SAK: killed process %d (%s): by controlling tty\n", task_pid_nr(p), p->comm); - group_send_sig_info(SIGKILL, SEND_SIG_PRIV, p, PIDTYPE_SID); + group_send_sig_info(SIGKILL, SEND_SIG_PRIV, p, + PIDTYPE_SID); continue; } task_lock(p); @@ -3062,7 +3063,8 @@ void __do_SAK(struct tty_struct *tty) if (i != 0) { tty_notice(tty, "SAK: killed process %d (%s): by fd#%d\n", task_pid_nr(p), p->comm, i - 1); - group_send_sig_info(SIGKILL, SEND_SIG_PRIV, p, PIDTYPE_SID); + group_send_sig_info(SIGKILL, SEND_SIG_PRIV, p, + PIDTYPE_SID); } task_unlock(p); } while_each_thread(g, p); -- cgit From 2765852e74c8cfb5317cd22331800f00ab71ff46 Mon Sep 17 00:00:00 2001 From: Jiri Slaby Date: Thu, 18 Nov 2021 08:19:11 +0100 Subject: tty: serial, join uport checks in uart_port_shutdown() There are two consequent checks of uport != NULL in uart_port_shutdown(). Join these two under a single block. De-multiline the comments when shuffling with them anyway. Signed-off-by: Jiri Slaby Link: https://lore.kernel.org/r/20211118071911.12059-5-jslaby@suse.cz Signed-off-by: Greg Kroah-Hartman --- drivers/tty/serial/serial_core.c | 12 ++++-------- 1 file changed, 4 insertions(+), 8 deletions(-) (limited to 'drivers/tty') diff --git a/drivers/tty/serial/serial_core.c b/drivers/tty/serial/serial_core.c index 1e738f265eea..a8750927f03c 100644 --- a/drivers/tty/serial/serial_core.c +++ b/drivers/tty/serial/serial_core.c @@ -1685,17 +1685,13 @@ static void uart_port_shutdown(struct tty_port *port) */ wake_up_interruptible(&port->delta_msr_wait); - /* - * Free the IRQ and disable the port. - */ - if (uport) + if (uport) { + /* Free the IRQ and disable the port. */ uport->ops->shutdown(uport); - /* - * Ensure that the IRQ handler isn't running on another CPU. - */ - if (uport) + /* Ensure that the IRQ handler isn't running on another CPU. */ synchronize_irq(uport->irq); + } } static int uart_carrier_raised(struct tty_port *port) -- cgit From 862f72187a41008df2cce3f8e97f57070cbc7060 Mon Sep 17 00:00:00 2001 From: Lad Prabhakar Date: Wed, 10 Nov 2021 23:29:20 +0000 Subject: serial: sh-sci: Add support to deassert/assert reset line On RZ/G2L SoC we need to explicitly deassert the reset line for the device to work, use this opportunity to deassert/assert reset line in sh-sci driver. This patch adds support to read the "resets" property (if available) from DT and perform deassert/assert when required. Also, propagate the error to the caller of sci_parse_dt() instead of returning NULL in case of failure. Reviewed-by: Biju Das Reviewed-by: Philipp Zabel Reviewed-by: Geert Uytterhoeven Signed-off-by: Lad Prabhakar Link: https://lore.kernel.org/r/20211110232920.19198-4-prabhakar.mahadev-lad.rj@bp.renesas.com Signed-off-by: Greg Kroah-Hartman --- drivers/tty/serial/sh-sci.c | 39 ++++++++++++++++++++++++++++++++------- 1 file changed, 32 insertions(+), 7 deletions(-) (limited to 'drivers/tty') diff --git a/drivers/tty/serial/sh-sci.c b/drivers/tty/serial/sh-sci.c index 89ee43061d3a..88005d2fc2a0 100644 --- a/drivers/tty/serial/sh-sci.c +++ b/drivers/tty/serial/sh-sci.c @@ -37,6 +37,7 @@ #include #include #include +#include #include #include #include @@ -3203,23 +3204,47 @@ static const struct of_device_id of_sci_match[] = { }; MODULE_DEVICE_TABLE(of, of_sci_match); +static void sci_reset_control_assert(void *data) +{ + reset_control_assert(data); +} + static struct plat_sci_port *sci_parse_dt(struct platform_device *pdev, unsigned int *dev_id) { struct device_node *np = pdev->dev.of_node; + struct reset_control *rstc; struct plat_sci_port *p; struct sci_port *sp; const void *data; - int id; + int id, ret; if (!IS_ENABLED(CONFIG_OF) || !np) - return NULL; + return ERR_PTR(-EINVAL); data = of_device_get_match_data(&pdev->dev); + rstc = devm_reset_control_get_optional_exclusive(&pdev->dev, NULL); + if (IS_ERR(rstc)) + return ERR_PTR(dev_err_probe(&pdev->dev, PTR_ERR(rstc), + "failed to get reset ctrl\n")); + + ret = reset_control_deassert(rstc); + if (ret) { + dev_err(&pdev->dev, "failed to deassert reset %d\n", ret); + return ERR_PTR(ret); + } + + ret = devm_add_action_or_reset(&pdev->dev, sci_reset_control_assert, rstc); + if (ret) { + dev_err(&pdev->dev, "failed to register assert devm action, %d\n", + ret); + return ERR_PTR(ret); + } + p = devm_kzalloc(&pdev->dev, sizeof(struct plat_sci_port), GFP_KERNEL); if (!p) - return NULL; + return ERR_PTR(-ENOMEM); /* Get the line number from the aliases node. */ id = of_alias_get_id(np, "serial"); @@ -3227,11 +3252,11 @@ static struct plat_sci_port *sci_parse_dt(struct platform_device *pdev, id = ffz(sci_ports_in_use); if (id < 0) { dev_err(&pdev->dev, "failed to get alias id (%d)\n", id); - return NULL; + return ERR_PTR(-EINVAL); } if (id >= ARRAY_SIZE(sci_ports)) { dev_err(&pdev->dev, "serial%d out of range\n", id); - return NULL; + return ERR_PTR(-EINVAL); } sp = &sci_ports[id]; @@ -3318,8 +3343,8 @@ static int sci_probe(struct platform_device *dev) if (dev->dev.of_node) { p = sci_parse_dt(dev, &dev_id); - if (p == NULL) - return -EINVAL; + if (IS_ERR(p)) + return PTR_ERR(p); } else { p = dev->dev.platform_data; if (p == NULL) { -- cgit From e25ed43b4b603c1f7727bfede684b165dc5cd18c Mon Sep 17 00:00:00 2001 From: Jiri Slaby Date: Thu, 18 Nov 2021 08:31:07 +0100 Subject: mxser: remove wait for sent from mxser_close_port mxser_close() behaves like this: -> tty_port_close_start() -> tty_wait_until_sent() -> mxser_wait_until_sent() -> mxser_close_port -> wait for TEMT So it is already waited for TEMT through mxser_wait_until_sent() and there is another round of waiting in mxser_close_port(). The latter one is superfluous as nothing could be filled into the output FIFO. Remove the call. This helps unification among drivers (so that all behave the same) and future use of tty_port_close(). Signed-off-by: Jiri Slaby Link: https://lore.kernel.org/r/20211118073125.12283-2-jslaby@suse.cz Signed-off-by: Greg Kroah-Hartman --- drivers/tty/mxser.c | 12 ------------ 1 file changed, 12 deletions(-) (limited to 'drivers/tty') diff --git a/drivers/tty/mxser.c b/drivers/tty/mxser.c index 93a95a135a71..f9615245a60a 100644 --- a/drivers/tty/mxser.c +++ b/drivers/tty/mxser.c @@ -878,7 +878,6 @@ static void mxser_flush_buffer(struct tty_struct *tty) static void mxser_close_port(struct tty_port *port) { struct mxser_port *info = container_of(port, struct mxser_port, port); - unsigned long timeout; /* * At this point we stop accepting input. To do this, we * disable the receive line status interrupts, and tell the @@ -890,17 +889,6 @@ static void mxser_close_port(struct tty_port *port) info->IER &= ~MOXA_MUST_RECV_ISR; outb(info->IER, info->ioaddr + UART_IER); - /* - * Before we drop DTR, make sure the UART transmitter - * has completely drained; this is especially - * important if there is a transmit FIFO! - */ - timeout = jiffies + HZ; - while (!(inb(info->ioaddr + UART_LSR) & UART_LSR_TEMT)) { - schedule_timeout_interruptible(5); - if (time_after(jiffies, timeout)) - break; - } } /* -- cgit From 568a2b9c1289dc090019d727b9af2285bc637353 Mon Sep 17 00:00:00 2001 From: Jiri Slaby Date: Thu, 18 Nov 2021 08:31:08 +0100 Subject: mxser: rename mxser_close_port() to mxser_stop_rx() As it is the only thing it does now. This is one of the future serial_core hooks. Signed-off-by: Jiri Slaby Link: https://lore.kernel.org/r/20211118073125.12283-3-jslaby@suse.cz Signed-off-by: Greg Kroah-Hartman --- drivers/tty/mxser.c | 17 +++++++---------- 1 file changed, 7 insertions(+), 10 deletions(-) (limited to 'drivers/tty') diff --git a/drivers/tty/mxser.c b/drivers/tty/mxser.c index f9615245a60a..e9248d39879c 100644 --- a/drivers/tty/mxser.c +++ b/drivers/tty/mxser.c @@ -874,16 +874,13 @@ static void mxser_flush_buffer(struct tty_struct *tty) tty_wakeup(tty); } - -static void mxser_close_port(struct tty_port *port) +/* + * To stop accepting input, we disable the receive line status interrupts, and + * tell the interrupt driver to stop checking the data ready bit in the line + * status register. + */ +static void mxser_stop_rx(struct mxser_port *info) { - struct mxser_port *info = container_of(port, struct mxser_port, port); - /* - * At this point we stop accepting input. To do this, we - * disable the receive line status interrupts, and tell the - * interrupt driver to stop checking the data ready bit in the - * line status register. - */ info->IER &= ~UART_IER_RLSI; if (info->board->must_hwid) info->IER &= ~MOXA_MUST_RECV_ISR; @@ -908,7 +905,7 @@ static void mxser_close(struct tty_struct *tty, struct file *filp) return; info->closing = 1; mutex_lock(&port->mutex); - mxser_close_port(port); + mxser_stop_rx(info); mxser_flush_buffer(tty); if (tty_port_initialized(port) && C_HUPCL(tty)) tty_port_lower_dtr_rts(port); -- cgit From 274ab58dc2b460cc474ffc7ccfcede4b2be1a3f5 Mon Sep 17 00:00:00 2001 From: Jiri Slaby Date: Thu, 18 Nov 2021 08:31:09 +0100 Subject: mxser: keep only !tty test in ISR The others are superfluous with tty refcounting in place now. And they are racy in fact: * tty_port_initialized() reports false for a small moment after interrupts are enabled. * closing is 1 while the port is still alive. The queues are flushed later during close anyway. So there is no need for this special handling. Actually, the ISR should not flush the queues. It should behave as every other driver, just queue the chars into tty buffer and go on. But this will be changed later. There is still a lot code depending on having tty in ISR (and not only tty_port). Signed-off-by: Jiri Slaby Link: https://lore.kernel.org/r/20211118073125.12283-4-jslaby@suse.cz Signed-off-by: Greg Kroah-Hartman --- drivers/tty/mxser.c | 5 +---- 1 file changed, 1 insertion(+), 4 deletions(-) (limited to 'drivers/tty') diff --git a/drivers/tty/mxser.c b/drivers/tty/mxser.c index e9248d39879c..c8a56b0d900d 100644 --- a/drivers/tty/mxser.c +++ b/drivers/tty/mxser.c @@ -262,7 +262,6 @@ struct mxser_port { unsigned int xmit_head; unsigned int xmit_tail; unsigned int xmit_cnt; - int closing; spinlock_t slock; }; @@ -903,7 +902,6 @@ static void mxser_close(struct tty_struct *tty, struct file *filp) return; if (tty_port_close_start(port, tty, filp) == 0) return; - info->closing = 1; mutex_lock(&port->mutex); mxser_stop_rx(info); mxser_flush_buffer(tty); @@ -912,7 +910,6 @@ static void mxser_close(struct tty_struct *tty, struct file *filp) mxser_shutdown_port(port); tty_port_set_initialized(port, 0); mutex_unlock(&port->mutex); - info->closing = 0; /* Right now the tty_port set is done outside of the close_end helper as we don't yet have everyone using refcounts */ tty_port_close_end(port, tty); @@ -1668,7 +1665,7 @@ static bool mxser_port_isr(struct mxser_port *port) iir &= MOXA_MUST_IIR_MASK; tty = tty_port_tty_get(&port->port); - if (!tty || port->closing || !tty_port_initialized(&port->port)) { + if (!tty) { status = inb(port->ioaddr + UART_LSR); outb(port->FCR | UART_FCR_CLEAR_RCVR | UART_FCR_CLEAR_XMIT, port->ioaddr + UART_FCR); -- cgit From 30f6027fe4643be955e4e9849f242e55ba993185 Mon Sep 17 00:00:00 2001 From: Jiri Slaby Date: Thu, 18 Nov 2021 08:31:10 +0100 Subject: mxser: move MSR read to mxser_check_modem_status() The MSR read is currently performed on both places where mxser_check_modem_status() is called. So move it there to avoid code duplication. Rename the variable to msr while we move it, to actually see what "status" we are testing. Signed-off-by: Jiri Slaby Link: https://lore.kernel.org/r/20211118073125.12283-5-jslaby@suse.cz Signed-off-by: Greg Kroah-Hartman --- drivers/tty/mxser.c | 46 +++++++++++++++++++++++++--------------------- 1 file changed, 25 insertions(+), 21 deletions(-) (limited to 'drivers/tty') diff --git a/drivers/tty/mxser.c b/drivers/tty/mxser.c index c8a56b0d900d..3d5c20e31836 100644 --- a/drivers/tty/mxser.c +++ b/drivers/tty/mxser.c @@ -683,27 +683,34 @@ static void mxser_change_speed(struct tty_struct *tty, struct ktermios *old_term outb(cval, info->ioaddr + UART_LCR); } -static void mxser_check_modem_status(struct tty_struct *tty, - struct mxser_port *port, int status) +static u8 mxser_check_modem_status(struct tty_struct *tty, + struct mxser_port *port) { + u8 msr = inb(port->ioaddr + UART_MSR); + + if (!(msr & UART_MSR_ANY_DELTA)) + return msr; + /* update input line counters */ - if (status & UART_MSR_TERI) + if (msr & UART_MSR_TERI) port->icount.rng++; - if (status & UART_MSR_DDSR) + if (msr & UART_MSR_DDSR) port->icount.dsr++; - if (status & UART_MSR_DDCD) + if (msr & UART_MSR_DDCD) port->icount.dcd++; - if (status & UART_MSR_DCTS) + if (msr & UART_MSR_DCTS) port->icount.cts++; wake_up_interruptible(&port->port.delta_msr_wait); - if (tty_port_check_carrier(&port->port) && (status & UART_MSR_DDCD)) { - if (status & UART_MSR_DCD) + if (tty_port_check_carrier(&port->port) && (msr & UART_MSR_DDCD)) { + if (msr & UART_MSR_DCD) wake_up_interruptible(&port->port.open_wait); } if (tty_port_cts_enabled(&port->port)) - mxser_handle_cts(tty, port, status); + mxser_handle_cts(tty, port, msr); + + return msr; } static void mxser_disable_and_clear_FIFO(struct mxser_port *info) @@ -1135,25 +1142,24 @@ static int mxser_get_lsr_info(struct mxser_port *info, static int mxser_tiocmget(struct tty_struct *tty) { struct mxser_port *info = tty->driver_data; - unsigned char control, status; + unsigned char control; unsigned long flags; + u8 msr; if (tty_io_error(tty)) return -EIO; spin_lock_irqsave(&info->slock, flags); control = info->MCR; - status = inb(info->ioaddr + UART_MSR); - if (status & UART_MSR_ANY_DELTA) - mxser_check_modem_status(tty, info, status); + msr = mxser_check_modem_status(tty, info); spin_unlock_irqrestore(&info->slock, flags); return ((control & UART_MCR_RTS) ? TIOCM_RTS : 0) | ((control & UART_MCR_DTR) ? TIOCM_DTR : 0) | - ((status & UART_MSR_DCD) ? TIOCM_CAR : 0) | - ((status & UART_MSR_RI) ? TIOCM_RNG : 0) | - ((status & UART_MSR_DSR) ? TIOCM_DSR : 0) | - ((status & UART_MSR_CTS) ? TIOCM_CTS : 0); + ((msr & UART_MSR_DCD) ? TIOCM_CAR : 0) | + ((msr & UART_MSR_RI) ? TIOCM_RNG : 0) | + ((msr & UART_MSR_DSR) ? TIOCM_DSR : 0) | + ((msr & UART_MSR_CTS) ? TIOCM_CTS : 0); } static int mxser_tiocmset(struct tty_struct *tty, @@ -1656,7 +1662,7 @@ static void mxser_transmit_chars(struct tty_struct *tty, struct mxser_port *port static bool mxser_port_isr(struct mxser_port *port) { struct tty_struct *tty; - u8 iir, msr, status; + u8 iir, status; bool error = false; iir = inb(port->ioaddr + UART_IIR); @@ -1689,9 +1695,7 @@ static bool mxser_port_isr(struct mxser_port *port) status = mxser_receive_chars(tty, port, status); } - msr = inb(port->ioaddr + UART_MSR); - if (msr & UART_MSR_ANY_DELTA) - mxser_check_modem_status(tty, port, msr); + mxser_check_modem_status(tty, port); if (port->board->must_hwid) { if (iir == 0x02 && (status & UART_LSR_THRE)) -- cgit From 3b88dbff1c4e7d8a78e11773f19869c598552fcb Mon Sep 17 00:00:00 2001 From: Jiri Slaby Date: Thu, 18 Nov 2021 08:31:11 +0100 Subject: mxser: clean up tx handling in mxser_transmit_chars() The port->icount.tx is handled in a too complicated manner. Instead of remembering the original count and subtracting the new one from it, simply increase tx for each character in the loop. No need for cnt variable then. Change also the "X = X & Y" assignment to simpler "X &= Y". Signed-off-by: Jiri Slaby Link: https://lore.kernel.org/r/20211118073125.12283-6-jslaby@suse.cz Signed-off-by: Greg Kroah-Hartman --- drivers/tty/mxser.c | 8 +++----- 1 file changed, 3 insertions(+), 5 deletions(-) (limited to 'drivers/tty') diff --git a/drivers/tty/mxser.c b/drivers/tty/mxser.c index 3d5c20e31836..eb5fb4fb2aef 100644 --- a/drivers/tty/mxser.c +++ b/drivers/tty/mxser.c @@ -1622,7 +1622,7 @@ static u8 mxser_receive_chars(struct tty_struct *tty, static void mxser_transmit_chars(struct tty_struct *tty, struct mxser_port *port) { - int count, cnt; + int count; if (port->x_char) { outb(port->x_char, port->ioaddr + UART_TX); @@ -1640,18 +1640,16 @@ static void mxser_transmit_chars(struct tty_struct *tty, struct mxser_port *port return; } - cnt = port->xmit_cnt; count = port->xmit_fifo_size; do { outb(port->port.xmit_buf[port->xmit_tail++], port->ioaddr + UART_TX); - port->xmit_tail = port->xmit_tail & (SERIAL_XMIT_SIZE - 1); + port->xmit_tail &= SERIAL_XMIT_SIZE - 1; + port->icount.tx++; if (!--port->xmit_cnt) break; } while (--count > 0); - port->icount.tx += (cnt - port->xmit_cnt); - if (port->xmit_cnt < WAKEUP_CHARS) tty_wakeup(tty); -- cgit From 5c338fbf21ebf2206a4d5abf3bc077c9a9018a79 Mon Sep 17 00:00:00 2001 From: Jiri Slaby Date: Thu, 18 Nov 2021 08:31:12 +0100 Subject: mxser: remove pointless xmit_buf checks xmit_buf is supposed to exist in all these functions. I.e. from tty_port_operations::activate() to ::shutdown(). So remove these checks. Signed-off-by: Jiri Slaby Link: https://lore.kernel.org/r/20211118073125.12283-7-jslaby@suse.cz Signed-off-by: Greg Kroah-Hartman --- drivers/tty/mxser.c | 13 ++----------- 1 file changed, 2 insertions(+), 11 deletions(-) (limited to 'drivers/tty') diff --git a/drivers/tty/mxser.c b/drivers/tty/mxser.c index eb5fb4fb2aef..6e5e1c74bf3e 100644 --- a/drivers/tty/mxser.c +++ b/drivers/tty/mxser.c @@ -929,9 +929,6 @@ static int mxser_write(struct tty_struct *tty, const unsigned char *buf, int cou struct mxser_port *info = tty->driver_data; unsigned long flags; - if (!info->port.xmit_buf) - return 0; - while (1) { c = min_t(int, count, min(SERIAL_XMIT_SIZE - info->xmit_cnt - 1, SERIAL_XMIT_SIZE - info->xmit_head)); @@ -962,9 +959,6 @@ static int mxser_put_char(struct tty_struct *tty, unsigned char ch) struct mxser_port *info = tty->driver_data; unsigned long flags; - if (!info->port.xmit_buf) - return 0; - if (info->xmit_cnt >= SERIAL_XMIT_SIZE - 1) return 0; @@ -982,7 +976,7 @@ static void mxser_flush_chars(struct tty_struct *tty) { struct mxser_port *info = tty->driver_data; - if (!info->xmit_cnt || tty->flow.stopped || !info->port.xmit_buf || + if (!info->xmit_cnt || tty->flow.stopped || (tty->hw_stopped && !mxser_16550A_or_MUST(info))) return; @@ -1397,7 +1391,7 @@ static void mxser_start(struct tty_struct *tty) unsigned long flags; spin_lock_irqsave(&info->slock, flags); - if (info->xmit_cnt && info->port.xmit_buf) + if (info->xmit_cnt) __mxser_start_tx(info); spin_unlock_irqrestore(&info->slock, flags); } @@ -1631,9 +1625,6 @@ static void mxser_transmit_chars(struct tty_struct *tty, struct mxser_port *port return; } - if (port->port.xmit_buf == NULL) - return; - if (!port->xmit_cnt || tty->flow.stopped || (tty->hw_stopped && !mxser_16550A_or_MUST(port))) { __mxser_stop_tx(port); -- cgit From 2fb19b957805e8d6b981cf339caecd7cb6a3893a Mon Sep 17 00:00:00 2001 From: Jiri Slaby Date: Thu, 18 Nov 2021 08:31:13 +0100 Subject: mxser: remove tty->driver_data NULL check Noone sets tty->driver_data to NULL in the driver, so there is no point to check that in mxser_close(). Remove the check. Signed-off-by: Jiri Slaby Link: https://lore.kernel.org/r/20211118073125.12283-8-jslaby@suse.cz Signed-off-by: Greg Kroah-Hartman --- drivers/tty/mxser.c | 2 -- 1 file changed, 2 deletions(-) (limited to 'drivers/tty') diff --git a/drivers/tty/mxser.c b/drivers/tty/mxser.c index 6e5e1c74bf3e..6b47a0607f59 100644 --- a/drivers/tty/mxser.c +++ b/drivers/tty/mxser.c @@ -905,8 +905,6 @@ static void mxser_close(struct tty_struct *tty, struct file *filp) struct mxser_port *info = tty->driver_data; struct tty_port *port = &info->port; - if (info == NULL) - return; if (tty_port_close_start(port, tty, filp) == 0) return; mutex_lock(&port->mutex); -- cgit From 47b722d473824e9c56b7487d47ea7423483258d9 Mon Sep 17 00:00:00 2001 From: Jiri Slaby Date: Thu, 18 Nov 2021 08:31:14 +0100 Subject: mxser: call stop_rx from mxser_shutdown_port() mxser_stop_rx() should be called from mxser_shutdown_port() for several reasons: 1) info->slock is held while manipulating IER (as on other places), 2) hangup now stops rx too, 3) mxser_close() will use tty_port_close() and there is no place except tty_port_operations::shutdown() where this can be done, 4) this is the same sequence as serial_core does. So we can map this code 1:1 when switching the driver to it. Signed-off-by: Jiri Slaby Link: https://lore.kernel.org/r/20211118073125.12283-9-jslaby@suse.cz Signed-off-by: Greg Kroah-Hartman --- drivers/tty/mxser.c | 31 ++++++++++++++++--------------- 1 file changed, 16 insertions(+), 15 deletions(-) (limited to 'drivers/tty') diff --git a/drivers/tty/mxser.c b/drivers/tty/mxser.c index 6b47a0607f59..45ee1122a5f7 100644 --- a/drivers/tty/mxser.c +++ b/drivers/tty/mxser.c @@ -807,6 +807,20 @@ static int mxser_activate(struct tty_port *port, struct tty_struct *tty) return 0; } +/* + * To stop accepting input, we disable the receive line status interrupts, and + * tell the interrupt driver to stop checking the data ready bit in the line + * status register. + */ +static void mxser_stop_rx(struct mxser_port *info) +{ + info->IER &= ~UART_IER_RLSI; + if (info->board->must_hwid) + info->IER &= ~MOXA_MUST_RECV_ISR; + + outb(info->IER, info->ioaddr + UART_IER); +} + /* * This routine will shutdown a serial port */ @@ -817,6 +831,8 @@ static void mxser_shutdown_port(struct tty_port *port) spin_lock_irqsave(&info->slock, flags); + mxser_stop_rx(info); + /* * clear delta_msr_wait queue to avoid mem leaks: we may free the irq * here so the queue might never be waken up @@ -880,20 +896,6 @@ static void mxser_flush_buffer(struct tty_struct *tty) tty_wakeup(tty); } -/* - * To stop accepting input, we disable the receive line status interrupts, and - * tell the interrupt driver to stop checking the data ready bit in the line - * status register. - */ -static void mxser_stop_rx(struct mxser_port *info) -{ - info->IER &= ~UART_IER_RLSI; - if (info->board->must_hwid) - info->IER &= ~MOXA_MUST_RECV_ISR; - - outb(info->IER, info->ioaddr + UART_IER); -} - /* * This routine is called when the serial port gets closed. First, we * wait for the last remaining data to be sent. Then, we unlink its @@ -908,7 +910,6 @@ static void mxser_close(struct tty_struct *tty, struct file *filp) if (tty_port_close_start(port, tty, filp) == 0) return; mutex_lock(&port->mutex); - mxser_stop_rx(info); mxser_flush_buffer(tty); if (tty_port_initialized(port) && C_HUPCL(tty)) tty_port_lower_dtr_rts(port); -- cgit From 467b4c47880dc8aaf26e31262d19271674fa862a Mon Sep 17 00:00:00 2001 From: Jiri Slaby Date: Thu, 18 Nov 2021 08:31:15 +0100 Subject: mxser: don't flush buffer from mxser_close() directly I fail to see the point of calling mxser_flush_buffer() from mxser_close(): 1) The SW xmit buffer is freed in mxser_shutdown_port() right after the call to mxser_flush_buffer(). And all 'cnt', 'head', and 'tail' are properly initialized to 0 in mxser_activate(). 2) The HW buffer is flushed in mxser_shutdown_port() via mxser_disable_and_clear_FIFO() too. So the effect of doing it by mxser_flush_buffer() in mxser_close() is none. Hence remove it, so that when we use tty_port_close() later, the code is 1:1 identical. Signed-off-by: Jiri Slaby Link: https://lore.kernel.org/r/20211118073125.12283-10-jslaby@suse.cz Signed-off-by: Greg Kroah-Hartman --- drivers/tty/mxser.c | 1 - 1 file changed, 1 deletion(-) (limited to 'drivers/tty') diff --git a/drivers/tty/mxser.c b/drivers/tty/mxser.c index 45ee1122a5f7..4dafa16aa29c 100644 --- a/drivers/tty/mxser.c +++ b/drivers/tty/mxser.c @@ -910,7 +910,6 @@ static void mxser_close(struct tty_struct *tty, struct file *filp) if (tty_port_close_start(port, tty, filp) == 0) return; mutex_lock(&port->mutex); - mxser_flush_buffer(tty); if (tty_port_initialized(port) && C_HUPCL(tty)) tty_port_lower_dtr_rts(port); mxser_shutdown_port(port); -- cgit From c7ec012f6c563a84fc5c3052d490292a129413b7 Mon Sep 17 00:00:00 2001 From: Jiri Slaby Date: Thu, 18 Nov 2021 08:31:16 +0100 Subject: mxser: use tty_port_close() in mxser_close() Finally, the mxser_close() code in is mostly identical to tty_port_close(), so replace the code by a single call to the function. Signed-off-by: Jiri Slaby Link: https://lore.kernel.org/r/20211118073125.12283-11-jslaby@suse.cz Signed-off-by: Greg Kroah-Hartman --- drivers/tty/mxser.c | 22 +--------------------- 1 file changed, 1 insertion(+), 21 deletions(-) (limited to 'drivers/tty') diff --git a/drivers/tty/mxser.c b/drivers/tty/mxser.c index 4dafa16aa29c..6ab8899ada9c 100644 --- a/drivers/tty/mxser.c +++ b/drivers/tty/mxser.c @@ -896,29 +896,9 @@ static void mxser_flush_buffer(struct tty_struct *tty) tty_wakeup(tty); } -/* - * This routine is called when the serial port gets closed. First, we - * wait for the last remaining data to be sent. Then, we unlink its - * async structure from the interrupt chain if necessary, and we free - * that IRQ if nothing is left in the chain. - */ static void mxser_close(struct tty_struct *tty, struct file *filp) { - struct mxser_port *info = tty->driver_data; - struct tty_port *port = &info->port; - - if (tty_port_close_start(port, tty, filp) == 0) - return; - mutex_lock(&port->mutex); - if (tty_port_initialized(port) && C_HUPCL(tty)) - tty_port_lower_dtr_rts(port); - mxser_shutdown_port(port); - tty_port_set_initialized(port, 0); - mutex_unlock(&port->mutex); - /* Right now the tty_port set is done outside of the close_end helper - as we don't yet have everyone using refcounts */ - tty_port_close_end(port, tty); - tty_port_tty_set(port, NULL); + tty_port_close(tty->port, tty, filp); } static int mxser_write(struct tty_struct *tty, const unsigned char *buf, int count) -- cgit From 239ef19ef040698ccbabf25582b40c43554542fd Mon Sep 17 00:00:00 2001 From: Jiri Slaby Date: Thu, 18 Nov 2021 08:31:17 +0100 Subject: mxser: extract TX empty check from mxser_wait_until_sent() And move it to new mxser_tx_empty(), because: 1) it simplifies the code (esp. the locking), and 2) serial_core needs such a hook anyway, so have it ready. Signed-off-by: Jiri Slaby Link: https://lore.kernel.org/r/20211118073125.12283-12-jslaby@suse.cz Signed-off-by: Greg Kroah-Hartman --- drivers/tty/mxser.c | 20 +++++++++++++------- 1 file changed, 13 insertions(+), 7 deletions(-) (limited to 'drivers/tty') diff --git a/drivers/tty/mxser.c b/drivers/tty/mxser.c index 6ab8899ada9c..fb26670b5a0b 100644 --- a/drivers/tty/mxser.c +++ b/drivers/tty/mxser.c @@ -1402,6 +1402,18 @@ static void mxser_set_termios(struct tty_struct *tty, struct ktermios *old_termi } } +static bool mxser_tx_empty(struct mxser_port *info) +{ + unsigned long flags; + u8 lsr; + + spin_lock_irqsave(&info->slock, flags); + lsr = inb(info->ioaddr + UART_LSR); + spin_unlock_irqrestore(&info->slock, flags); + + return !(lsr & UART_LSR_TEMT); +} + /* * mxser_wait_until_sent() --- wait until the transmitter is empty */ @@ -1409,8 +1421,6 @@ static void mxser_wait_until_sent(struct tty_struct *tty, int timeout) { struct mxser_port *info = tty->driver_data; unsigned long orig_jiffies, char_time; - unsigned long flags; - int lsr; if (info->type == PORT_UNKNOWN) return; @@ -1445,17 +1455,13 @@ static void mxser_wait_until_sent(struct tty_struct *tty, int timeout) if (!timeout || timeout > 2 * info->timeout) timeout = 2 * info->timeout; - spin_lock_irqsave(&info->slock, flags); - while (!((lsr = inb(info->ioaddr + UART_LSR)) & UART_LSR_TEMT)) { - spin_unlock_irqrestore(&info->slock, flags); + while (mxser_tx_empty(info)) { schedule_timeout_interruptible(char_time); - spin_lock_irqsave(&info->slock, flags); if (signal_pending(current)) break; if (timeout && time_after(jiffies, orig_jiffies + timeout)) break; } - spin_unlock_irqrestore(&info->slock, flags); set_current_state(TASK_RUNNING); } -- cgit From fe74bc619b0db23c4b513141acd3e3e45694bb08 Mon Sep 17 00:00:00 2001 From: Jiri Slaby Date: Thu, 18 Nov 2021 08:31:18 +0100 Subject: mxser: use msleep_interruptible() in mxser_wait_until_sent() Instead of schedule_timeout_interruptible(), because: 1) we don't have to bother with the task state, and 2) msleep* guarantees to sleep that time (if not interrupted). Signed-off-by: Jiri Slaby Link: https://lore.kernel.org/r/20211118073125.12283-13-jslaby@suse.cz Signed-off-by: Greg Kroah-Hartman --- drivers/tty/mxser.c | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) (limited to 'drivers/tty') diff --git a/drivers/tty/mxser.c b/drivers/tty/mxser.c index fb26670b5a0b..b3ae3b105af0 100644 --- a/drivers/tty/mxser.c +++ b/drivers/tty/mxser.c @@ -1443,6 +1443,9 @@ static void mxser_wait_until_sent(struct tty_struct *tty, int timeout) char_time = 1; if (timeout && timeout < char_time) char_time = timeout; + + char_time = jiffies_to_msecs(char_time); + /* * If the transmitter hasn't cleared in twice the approximate * amount of time to send the entire FIFO, it probably won't @@ -1456,13 +1459,12 @@ static void mxser_wait_until_sent(struct tty_struct *tty, int timeout) timeout = 2 * info->timeout; while (mxser_tx_empty(info)) { - schedule_timeout_interruptible(char_time); + msleep_interruptible(char_time); if (signal_pending(current)) break; if (timeout && time_after(jiffies, orig_jiffies + timeout)) break; } - set_current_state(TASK_RUNNING); } /* -- cgit From 49b798a69e2b1b8c9de6df66a5b8ccf090583551 Mon Sep 17 00:00:00 2001 From: Jiri Slaby Date: Thu, 18 Nov 2021 08:31:19 +0100 Subject: mxser: clean up timeout handling in mxser_wait_until_sent() timeout cannot be zero at the point of use. So no need to check for zero. Also precompute the expiration time (into expire) and use it. This makes the code more clear. Signed-off-by: Jiri Slaby Link: https://lore.kernel.org/r/20211118073125.12283-14-jslaby@suse.cz Signed-off-by: Greg Kroah-Hartman --- drivers/tty/mxser.c | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) (limited to 'drivers/tty') diff --git a/drivers/tty/mxser.c b/drivers/tty/mxser.c index b3ae3b105af0..c3f262dc936d 100644 --- a/drivers/tty/mxser.c +++ b/drivers/tty/mxser.c @@ -1420,7 +1420,7 @@ static bool mxser_tx_empty(struct mxser_port *info) static void mxser_wait_until_sent(struct tty_struct *tty, int timeout) { struct mxser_port *info = tty->driver_data; - unsigned long orig_jiffies, char_time; + unsigned long expire, char_time; if (info->type == PORT_UNKNOWN) return; @@ -1428,7 +1428,6 @@ static void mxser_wait_until_sent(struct tty_struct *tty, int timeout) if (info->xmit_fifo_size == 0) return; /* Just in case.... */ - orig_jiffies = jiffies; /* * Set the check interval to be 1/5 of the estimated time to * send a single character, and make it at least 1. The check @@ -1458,11 +1457,13 @@ static void mxser_wait_until_sent(struct tty_struct *tty, int timeout) if (!timeout || timeout > 2 * info->timeout) timeout = 2 * info->timeout; + expire = jiffies + timeout; + while (mxser_tx_empty(info)) { msleep_interruptible(char_time); if (signal_pending(current)) break; - if (timeout && time_after(jiffies, orig_jiffies + timeout)) + if (time_after(jiffies, expire)) break; } } -- cgit From c6693e6e07805f1b7822b13a5b482bf2b6a1f312 Mon Sep 17 00:00:00 2001 From: Jiri Slaby Date: Thu, 18 Nov 2021 08:31:20 +0100 Subject: mxser: don't throttle manually First, checking tty->receive_room to signalize whether there is enough space in the tty buffers does not make much sense. Provided the tty buffers are in tty_port and those are not checked at all. Second, if the rx path is throttled, with CRTSCTS, RTS is deasserted, but is never asserted again. This leads to port "lockup", not accepting any more input. So: 1) stty -F /dev/ttyMI0 crtscts # the mxser port 2) stty -F /dev/ttyS6 crtscts # the connected port 3) cat /dev/ttyMI0 4) "write in a loop" to /dev/ttyS6 5) cat from 3) produces the bytes from 4) 6) killall -STOP cat (the 3)'s one) 7) wait for RTS to drop on /dev/ttyMI0 8) killall -CONT cat (again the 3)'s one) cat erroneously produces no more output now (i.e. no data sent from ttyS6 to ttyMI can be seen). Note that the step 7) is performed twice: once from n_tty by tty_throttle_safe(), once by mxser_stoprx() from the receive path. Then after step 7), n_tty correctly unthrottles the input, but mxser calls mxser_stoprx() again as there is still only a little space in n_tty buffers (tty->receive_room mentioned at the beginning), but the device's FIFO is/can be already filled. After this patch, the output is correctly resumed, i.e. n_tty both throttles and unthrottles without interfering with mxser's attempts. This allows us to get rid of the non-standard ldisc_stop_rx flag from struct mxser_port. Signed-off-by: Jiri Slaby Link: https://lore.kernel.org/r/20211118073125.12283-15-jslaby@suse.cz Signed-off-by: Greg Kroah-Hartman --- drivers/tty/mxser.c | 36 ++++++------------------------------ 1 file changed, 6 insertions(+), 30 deletions(-) (limited to 'drivers/tty') diff --git a/drivers/tty/mxser.c b/drivers/tty/mxser.c index c3f262dc936d..2359b4aa68af 100644 --- a/drivers/tty/mxser.c +++ b/drivers/tty/mxser.c @@ -251,8 +251,6 @@ struct mxser_port { u8 MCR; /* Modem control register */ u8 FCR; /* FIFO control register */ - bool ldisc_stop_rx; - struct async_icount icount; /* kernel counters for 4 input interrupts */ unsigned int timeout; @@ -1286,11 +1284,14 @@ static int mxser_get_icount(struct tty_struct *tty, return 0; } -static void mxser_stoprx(struct tty_struct *tty) +/* + * This routine is called by the upper-layer tty layer to signal that + * incoming characters should be throttled. + */ +static void mxser_throttle(struct tty_struct *tty) { struct mxser_port *info = tty->driver_data; - info->ldisc_stop_rx = true; if (I_IXOFF(tty)) { if (info->board->must_hwid) { info->IER &= ~MOXA_MUST_RECV_ISR; @@ -1309,21 +1310,11 @@ static void mxser_stoprx(struct tty_struct *tty) } } -/* - * This routine is called by the upper-layer tty layer to signal that - * incoming characters should be throttled. - */ -static void mxser_throttle(struct tty_struct *tty) -{ - mxser_stoprx(tty); -} - static void mxser_unthrottle(struct tty_struct *tty) { struct mxser_port *info = tty->driver_data; /* startrx */ - info->ldisc_stop_rx = false; if (I_IXOFF(tty)) { if (info->x_char) info->x_char = 0; @@ -1515,9 +1506,6 @@ static bool mxser_receive_chars_new(struct tty_struct *tty, if (hwid == MOXA_MUST_MU150_HWID) gdl &= MOXA_MUST_GDL_MASK; - if (gdl >= tty->receive_room && !port->ldisc_stop_rx) - mxser_stoprx(tty); - while (gdl--) { u8 ch = inb(port->ioaddr + UART_RX); tty_insert_flip_char(&port->port, ch, 0); @@ -1530,10 +1518,8 @@ static u8 mxser_receive_chars_old(struct tty_struct *tty, struct mxser_port *port, u8 status) { enum mxser_must_hwid hwid = port->board->must_hwid; - int recv_room = tty->receive_room; int ignored = 0; int max = 256; - int cnt = 0; u8 ch; do { @@ -1568,14 +1554,8 @@ static u8 mxser_receive_chars_old(struct tty_struct *tty, port->icount.overrun++; } } - tty_insert_flip_char(&port->port, ch, flag); - cnt++; - if (cnt >= recv_room) { - if (!port->ldisc_stop_rx) - mxser_stoprx(tty); + if (!tty_insert_flip_char(&port->port, ch, flag)) break; - } - } if (hwid) @@ -1590,9 +1570,6 @@ static u8 mxser_receive_chars_old(struct tty_struct *tty, static u8 mxser_receive_chars(struct tty_struct *tty, struct mxser_port *port, u8 status) { - if (tty->receive_room == 0 && !port->ldisc_stop_rx) - mxser_stoprx(tty); - if (!mxser_receive_chars_new(tty, port, status)) status = mxser_receive_chars_old(tty, port, status); @@ -1798,7 +1775,6 @@ static void mxser_initbrd(struct mxser_board *brd, bool high_baud) tty_port_init(&info->port); info->port.ops = &mxser_port_ops; info->board = brd; - info->ldisc_stop_rx = false; /* Enhance mode enabled here */ if (brd->must_hwid != MOXA_OTHER_UART) -- cgit From 9dd6f3063a733e0df2ff66f9c35419eb217d9af5 Mon Sep 17 00:00:00 2001 From: Jiri Slaby Date: Thu, 18 Nov 2021 08:31:21 +0100 Subject: mxser: remove tty parameter from mxser_receive_chars_new() After the previous change (no plays with of tty->receive_room), the tty parameter is unused. Signed-off-by: Jiri Slaby Link: https://lore.kernel.org/r/20211118073125.12283-16-jslaby@suse.cz Signed-off-by: Greg Kroah-Hartman --- drivers/tty/mxser.c | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) (limited to 'drivers/tty') diff --git a/drivers/tty/mxser.c b/drivers/tty/mxser.c index 2359b4aa68af..10862d4bb885 100644 --- a/drivers/tty/mxser.c +++ b/drivers/tty/mxser.c @@ -1491,8 +1491,7 @@ static int mxser_rs_break(struct tty_struct *tty, int break_state) return 0; } -static bool mxser_receive_chars_new(struct tty_struct *tty, - struct mxser_port *port, u8 status) +static bool mxser_receive_chars_new(struct mxser_port *port, u8 status) { enum mxser_must_hwid hwid = port->board->must_hwid; u8 gdl; @@ -1570,7 +1569,7 @@ static u8 mxser_receive_chars_old(struct tty_struct *tty, static u8 mxser_receive_chars(struct tty_struct *tty, struct mxser_port *port, u8 status) { - if (!mxser_receive_chars_new(tty, port, status)) + if (!mxser_receive_chars_new(port, status)) status = mxser_receive_chars_old(tty, port, status); tty_flip_buffer_push(&port->port); -- cgit From eb68ac0462bffc2ceb63b3a76737d6c9f186e6de Mon Sep 17 00:00:00 2001 From: Jiri Slaby Date: Thu, 18 Nov 2021 08:31:22 +0100 Subject: mxser: increase buf_overrun if tty_insert_flip_char() fails mxser doesn't increase port->icount.buf_overrun at all. Do so if overrun happens, so that it can be read from the stats. Signed-off-by: Jiri Slaby Link: https://lore.kernel.org/r/20211118073125.12283-17-jslaby@suse.cz Signed-off-by: Greg Kroah-Hartman --- drivers/tty/mxser.c | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) (limited to 'drivers/tty') diff --git a/drivers/tty/mxser.c b/drivers/tty/mxser.c index 10862d4bb885..65ea4baee5eb 100644 --- a/drivers/tty/mxser.c +++ b/drivers/tty/mxser.c @@ -1507,7 +1507,8 @@ static bool mxser_receive_chars_new(struct mxser_port *port, u8 status) while (gdl--) { u8 ch = inb(port->ioaddr + UART_RX); - tty_insert_flip_char(&port->port, ch, 0); + if (!tty_insert_flip_char(&port->port, ch, 0)) + port->icount.buf_overrun++; } return true; @@ -1553,8 +1554,10 @@ static u8 mxser_receive_chars_old(struct tty_struct *tty, port->icount.overrun++; } } - if (!tty_insert_flip_char(&port->port, ch, flag)) + if (!tty_insert_flip_char(&port->port, ch, flag)) { + port->icount.buf_overrun++; break; + } } if (hwid) -- cgit From 16add04f7bff891eebc7d34bc404600c0fc41db1 Mon Sep 17 00:00:00 2001 From: Jiri Slaby Date: Thu, 18 Nov 2021 08:31:23 +0100 Subject: mxser: add MOXA prefix to some PCI device IDs Some of the MOXA PCI device IDs contain _MOXA_, some don't. Add it to the latter, so that they are all unified. Signed-off-by: Jiri Slaby Link: https://lore.kernel.org/r/20211118073125.12283-18-jslaby@suse.cz Signed-off-by: Greg Kroah-Hartman --- drivers/tty/mxser.c | 32 ++++++++++++++++---------------- 1 file changed, 16 insertions(+), 16 deletions(-) (limited to 'drivers/tty') diff --git a/drivers/tty/mxser.c b/drivers/tty/mxser.c index 65ea4baee5eb..f6842089459a 100644 --- a/drivers/tty/mxser.c +++ b/drivers/tty/mxser.c @@ -159,14 +159,14 @@ #define MXSER_BAUD_BASE 921600 #define MXSER_CUSTOM_DIVISOR (MXSER_BAUD_BASE * 16) -#define PCI_DEVICE_ID_POS104UL 0x1044 -#define PCI_DEVICE_ID_CB108 0x1080 -#define PCI_DEVICE_ID_CP102UF 0x1023 -#define PCI_DEVICE_ID_CP112UL 0x1120 -#define PCI_DEVICE_ID_CB114 0x1142 -#define PCI_DEVICE_ID_CP114UL 0x1143 -#define PCI_DEVICE_ID_CB134I 0x1341 -#define PCI_DEVICE_ID_CP138U 0x1380 +#define PCI_DEVICE_ID_MOXA_POS104UL 0x1044 +#define PCI_DEVICE_ID_MOXA_CB108 0x1080 +#define PCI_DEVICE_ID_MOXA_CP102UF 0x1023 +#define PCI_DEVICE_ID_MOXA_CP112UL 0x1120 +#define PCI_DEVICE_ID_MOXA_CB114 0x1142 +#define PCI_DEVICE_ID_MOXA_CP114UL 0x1143 +#define PCI_DEVICE_ID_MOXA_CB134I 0x1341 +#define PCI_DEVICE_ID_MOXA_CP138U 0x1380 #define MXSER_NPORTS(ddata) ((ddata) & 0xffU) #define MXSER_HIGHBAUD 0x0100 @@ -212,14 +212,14 @@ static const struct pci_device_id mxser_pcibrds[] = { { PCI_VDEVICE(MOXA, PCI_DEVICE_ID_MOXA_CP118EL),.driver_data = 8 }, { PCI_VDEVICE(MOXA, PCI_DEVICE_ID_MOXA_CP168EL),.driver_data = 8 }, { PCI_VDEVICE(MOXA, PCI_DEVICE_ID_MOXA_CP104EL),.driver_data = 4 }, - { PCI_VDEVICE(MOXA, PCI_DEVICE_ID_CB108), .driver_data = 8 }, - { PCI_VDEVICE(MOXA, PCI_DEVICE_ID_CB114), .driver_data = 4 }, - { PCI_VDEVICE(MOXA, PCI_DEVICE_ID_CB134I), .driver_data = 4 }, - { PCI_VDEVICE(MOXA, PCI_DEVICE_ID_CP138U), .driver_data = 8 }, - { PCI_VDEVICE(MOXA, PCI_DEVICE_ID_POS104UL), .driver_data = 4 }, - { PCI_VDEVICE(MOXA, PCI_DEVICE_ID_CP114UL), .driver_data = 4 }, - { PCI_VDEVICE(MOXA, PCI_DEVICE_ID_CP102UF), .driver_data = 2 }, - { PCI_VDEVICE(MOXA, PCI_DEVICE_ID_CP112UL), .driver_data = 2 }, + { PCI_VDEVICE(MOXA, PCI_DEVICE_ID_MOXA_CB108), .driver_data = 8 }, + { PCI_VDEVICE(MOXA, PCI_DEVICE_ID_MOXA_CB114), .driver_data = 4 }, + { PCI_VDEVICE(MOXA, PCI_DEVICE_ID_MOXA_CB134I), .driver_data = 4 }, + { PCI_VDEVICE(MOXA, PCI_DEVICE_ID_MOXA_CP138U), .driver_data = 8 }, + { PCI_VDEVICE(MOXA, PCI_DEVICE_ID_MOXA_POS104UL),.driver_data = 4 }, + { PCI_VDEVICE(MOXA, PCI_DEVICE_ID_MOXA_CP114UL),.driver_data = 4 }, + { PCI_VDEVICE(MOXA, PCI_DEVICE_ID_MOXA_CP102UF),.driver_data = 2 }, + { PCI_VDEVICE(MOXA, PCI_DEVICE_ID_MOXA_CP112UL),.driver_data = 2 }, { } }; MODULE_DEVICE_TABLE(pci, mxser_pcibrds); -- cgit From 4167bd25ec3bc221387ec6811c05eadfe3cf1d3e Mon Sep 17 00:00:00 2001 From: Jiri Slaby Date: Thu, 18 Nov 2021 08:31:24 +0100 Subject: mxser: move ids from pci_ids.h here There is no point having MOXA PCI device IDs in include/linux/pci_ids.h. Move them to the driver and sort them all by the ID. Cc: Bjorn Helgaas Cc: linux-pci@vger.kernel.org Acked-by: Bjorn Helgaas Signed-off-by: Jiri Slaby Link: https://lore.kernel.org/r/20211118073125.12283-19-jslaby@suse.cz Signed-off-by: Greg Kroah-Hartman --- drivers/tty/mxser.c | 20 +++++++++++++++++++- 1 file changed, 19 insertions(+), 1 deletion(-) (limited to 'drivers/tty') diff --git a/drivers/tty/mxser.c b/drivers/tty/mxser.c index f6842089459a..ba96ffed193a 100644 --- a/drivers/tty/mxser.c +++ b/drivers/tty/mxser.c @@ -159,14 +159,32 @@ #define MXSER_BAUD_BASE 921600 #define MXSER_CUSTOM_DIVISOR (MXSER_BAUD_BASE * 16) +#define PCI_DEVICE_ID_MOXA_RC7000 0x0001 +#define PCI_DEVICE_ID_MOXA_CP102 0x1020 +#define PCI_DEVICE_ID_MOXA_CP102UL 0x1021 +#define PCI_DEVICE_ID_MOXA_CP102U 0x1022 +#define PCI_DEVICE_ID_MOXA_CP102UF 0x1023 +#define PCI_DEVICE_ID_MOXA_C104 0x1040 +#define PCI_DEVICE_ID_MOXA_CP104U 0x1041 +#define PCI_DEVICE_ID_MOXA_CP104JU 0x1042 +#define PCI_DEVICE_ID_MOXA_CP104EL 0x1043 #define PCI_DEVICE_ID_MOXA_POS104UL 0x1044 #define PCI_DEVICE_ID_MOXA_CB108 0x1080 -#define PCI_DEVICE_ID_MOXA_CP102UF 0x1023 #define PCI_DEVICE_ID_MOXA_CP112UL 0x1120 +#define PCI_DEVICE_ID_MOXA_CT114 0x1140 +#define PCI_DEVICE_ID_MOXA_CP114 0x1141 #define PCI_DEVICE_ID_MOXA_CB114 0x1142 #define PCI_DEVICE_ID_MOXA_CP114UL 0x1143 +#define PCI_DEVICE_ID_MOXA_CP118U 0x1180 +#define PCI_DEVICE_ID_MOXA_CP118EL 0x1181 +#define PCI_DEVICE_ID_MOXA_CP132 0x1320 +#define PCI_DEVICE_ID_MOXA_CP132U 0x1321 +#define PCI_DEVICE_ID_MOXA_CP134U 0x1340 #define PCI_DEVICE_ID_MOXA_CB134I 0x1341 #define PCI_DEVICE_ID_MOXA_CP138U 0x1380 +#define PCI_DEVICE_ID_MOXA_C168 0x1680 +#define PCI_DEVICE_ID_MOXA_CP168U 0x1681 +#define PCI_DEVICE_ID_MOXA_CP168EL 0x1682 #define MXSER_NPORTS(ddata) ((ddata) & 0xffU) #define MXSER_HIGHBAUD 0x0100 -- cgit From c668d5676461b9449b7a3e11912db3fba9ace94d Mon Sep 17 00:00:00 2001 From: Jiri Slaby Date: Thu, 18 Nov 2021 08:31:25 +0100 Subject: mxser: use PCI_DEVICE_DATA Now that we have all the PCI device IDs unified, we can use PCI_DEVICE_DATA() macro to simplify mxser's pci_device_id list, i.e. mxser_pcibrds. Signed-off-by: Jiri Slaby Link: https://lore.kernel.org/r/20211118073125.12283-20-jslaby@suse.cz Signed-off-by: Greg Kroah-Hartman --- drivers/tty/mxser.c | 52 ++++++++++++++++++++++++++-------------------------- 1 file changed, 26 insertions(+), 26 deletions(-) (limited to 'drivers/tty') diff --git a/drivers/tty/mxser.c b/drivers/tty/mxser.c index ba96ffed193a..c858aff721c4 100644 --- a/drivers/tty/mxser.c +++ b/drivers/tty/mxser.c @@ -212,32 +212,32 @@ static const struct { /* driver_data correspond to the lines in the structure above see also ISA probe function before you change something */ static const struct pci_device_id mxser_pcibrds[] = { - { PCI_VDEVICE(MOXA, PCI_DEVICE_ID_MOXA_C168), .driver_data = 8 }, - { PCI_VDEVICE(MOXA, PCI_DEVICE_ID_MOXA_C104), .driver_data = 4 }, - { PCI_VDEVICE(MOXA, PCI_DEVICE_ID_MOXA_CP132), .driver_data = 2 }, - { PCI_VDEVICE(MOXA, PCI_DEVICE_ID_MOXA_CP114), .driver_data = 4 }, - { PCI_VDEVICE(MOXA, PCI_DEVICE_ID_MOXA_CT114), .driver_data = 4 }, - { PCI_VDEVICE(MOXA, PCI_DEVICE_ID_MOXA_CP102), .driver_data = 2 | MXSER_HIGHBAUD }, - { PCI_VDEVICE(MOXA, PCI_DEVICE_ID_MOXA_CP104U), .driver_data = 4 }, - { PCI_VDEVICE(MOXA, PCI_DEVICE_ID_MOXA_CP168U), .driver_data = 8 }, - { PCI_VDEVICE(MOXA, PCI_DEVICE_ID_MOXA_CP132U), .driver_data = 2 }, - { PCI_VDEVICE(MOXA, PCI_DEVICE_ID_MOXA_CP134U), .driver_data = 4 }, - { PCI_VDEVICE(MOXA, PCI_DEVICE_ID_MOXA_CP104JU),.driver_data = 4 }, - { PCI_VDEVICE(MOXA, PCI_DEVICE_ID_MOXA_RC7000), .driver_data = 8 }, /* RC7000 */ - { PCI_VDEVICE(MOXA, PCI_DEVICE_ID_MOXA_CP118U), .driver_data = 8 }, - { PCI_VDEVICE(MOXA, PCI_DEVICE_ID_MOXA_CP102UL),.driver_data = 2 }, - { PCI_VDEVICE(MOXA, PCI_DEVICE_ID_MOXA_CP102U), .driver_data = 2 }, - { PCI_VDEVICE(MOXA, PCI_DEVICE_ID_MOXA_CP118EL),.driver_data = 8 }, - { PCI_VDEVICE(MOXA, PCI_DEVICE_ID_MOXA_CP168EL),.driver_data = 8 }, - { PCI_VDEVICE(MOXA, PCI_DEVICE_ID_MOXA_CP104EL),.driver_data = 4 }, - { PCI_VDEVICE(MOXA, PCI_DEVICE_ID_MOXA_CB108), .driver_data = 8 }, - { PCI_VDEVICE(MOXA, PCI_DEVICE_ID_MOXA_CB114), .driver_data = 4 }, - { PCI_VDEVICE(MOXA, PCI_DEVICE_ID_MOXA_CB134I), .driver_data = 4 }, - { PCI_VDEVICE(MOXA, PCI_DEVICE_ID_MOXA_CP138U), .driver_data = 8 }, - { PCI_VDEVICE(MOXA, PCI_DEVICE_ID_MOXA_POS104UL),.driver_data = 4 }, - { PCI_VDEVICE(MOXA, PCI_DEVICE_ID_MOXA_CP114UL),.driver_data = 4 }, - { PCI_VDEVICE(MOXA, PCI_DEVICE_ID_MOXA_CP102UF),.driver_data = 2 }, - { PCI_VDEVICE(MOXA, PCI_DEVICE_ID_MOXA_CP112UL),.driver_data = 2 }, + { PCI_DEVICE_DATA(MOXA, C168, 8) }, + { PCI_DEVICE_DATA(MOXA, C104, 4) }, + { PCI_DEVICE_DATA(MOXA, CP132, 2) }, + { PCI_DEVICE_DATA(MOXA, CP114, 4) }, + { PCI_DEVICE_DATA(MOXA, CT114, 4) }, + { PCI_DEVICE_DATA(MOXA, CP102, 2 | MXSER_HIGHBAUD) }, + { PCI_DEVICE_DATA(MOXA, CP104U, 4) }, + { PCI_DEVICE_DATA(MOXA, CP168U, 8) }, + { PCI_DEVICE_DATA(MOXA, CP132U, 2) }, + { PCI_DEVICE_DATA(MOXA, CP134U, 4) }, + { PCI_DEVICE_DATA(MOXA, CP104JU, 4) }, + { PCI_DEVICE_DATA(MOXA, RC7000, 8) }, /* RC7000 */ + { PCI_DEVICE_DATA(MOXA, CP118U, 8) }, + { PCI_DEVICE_DATA(MOXA, CP102UL, 2) }, + { PCI_DEVICE_DATA(MOXA, CP102U, 2) }, + { PCI_DEVICE_DATA(MOXA, CP118EL, 8) }, + { PCI_DEVICE_DATA(MOXA, CP168EL, 8) }, + { PCI_DEVICE_DATA(MOXA, CP104EL, 4) }, + { PCI_DEVICE_DATA(MOXA, CB108, 8) }, + { PCI_DEVICE_DATA(MOXA, CB114, 4) }, + { PCI_DEVICE_DATA(MOXA, CB134I, 4) }, + { PCI_DEVICE_DATA(MOXA, CP138U, 8) }, + { PCI_DEVICE_DATA(MOXA, POS104UL, 4) }, + { PCI_DEVICE_DATA(MOXA, CP114UL, 4) }, + { PCI_DEVICE_DATA(MOXA, CP102UF, 2) }, + { PCI_DEVICE_DATA(MOXA, CP112UL, 2) }, { } }; MODULE_DEVICE_TABLE(pci, mxser_pcibrds); -- cgit From 57dcb6ec85d59e04285b7dcf10924bb819c8e46f Mon Sep 17 00:00:00 2001 From: Emil Renner Berthing Date: Tue, 16 Nov 2021 16:01:17 +0100 Subject: serial: 8250_dw: Add StarFive JH7100 quirk On the StarFive JH7100 RISC-V SoC the UART core clocks can't be set to exactly 16 * 115200Hz and many other common bitrates. Trying this will only result in a higher input clock, but low enough that the UART's internal divisor can't come close enough to the baud rate target. So rather than try to set the input clock it's better to skip the clk_set_rate call and rely solely on the UART's internal divisor. Signed-off-by: Emil Renner Berthing Reviewed-by: Andy Shevchenko Reviewed-by: Geert Uytterhoeven Link: https://lore.kernel.org/r/20211116150119.2171-15-kernel@esmil.dk Signed-off-by: Greg Kroah-Hartman --- drivers/tty/serial/8250/8250_dw.c | 3 +++ 1 file changed, 3 insertions(+) (limited to 'drivers/tty') diff --git a/drivers/tty/serial/8250/8250_dw.c b/drivers/tty/serial/8250/8250_dw.c index 53f57c3b9f42..1769808031c5 100644 --- a/drivers/tty/serial/8250/8250_dw.c +++ b/drivers/tty/serial/8250/8250_dw.c @@ -414,6 +414,8 @@ static void dw8250_quirks(struct uart_port *p, struct dw8250_data *data) if (of_device_is_compatible(np, "marvell,armada-38x-uart")) p->serial_out = dw8250_serial_out38x; + if (of_device_is_compatible(np, "starfive,jh7100-uart")) + p->set_termios = dw8250_do_set_termios; } else if (acpi_dev_present("APMC0D08", NULL, -1)) { p->iotype = UPIO_MEM32; @@ -696,6 +698,7 @@ static const struct of_device_id dw8250_of_match[] = { { .compatible = "cavium,octeon-3860-uart" }, { .compatible = "marvell,armada-38x-uart" }, { .compatible = "renesas,rzn1-uart" }, + { .compatible = "starfive,jh7100-uart" }, { /* Sentinel */ } }; MODULE_DEVICE_TABLE(of, dw8250_of_match); -- cgit From 5f6a85158ccacc3f09744b3aafe8b11ab3b6c6f6 Mon Sep 17 00:00:00 2001 From: Jiri Slaby Date: Mon, 22 Nov 2021 12:16:46 +0100 Subject: tty: drivers/tty/, stop using tty_schedule_flip() Since commit a9c3f68f3cd8d (tty: Fix low_latency BUG) in 2014, tty_flip_buffer_push() is only a wrapper to tty_schedule_flip(). We are going to remove the latter (as it is used less), so call the former in drivers/tty/. Cc: Vladimir Zapolskiy Reviewed-by: Johan Hovold Signed-off-by: Jiri Slaby Link: https://lore.kernel.org/r/20211122111648.30379-2-jslaby@suse.cz Signed-off-by: Greg Kroah-Hartman --- drivers/tty/goldfish.c | 2 +- drivers/tty/moxa.c | 4 ++-- drivers/tty/serial/lpc32xx_hs.c | 2 +- drivers/tty/vt/keyboard.c | 6 +++--- drivers/tty/vt/vt.c | 2 +- 5 files changed, 8 insertions(+), 8 deletions(-) (limited to 'drivers/tty') diff --git a/drivers/tty/goldfish.c b/drivers/tty/goldfish.c index d24af649a8bb..c01cd36dda41 100644 --- a/drivers/tty/goldfish.c +++ b/drivers/tty/goldfish.c @@ -151,7 +151,7 @@ static irqreturn_t goldfish_tty_interrupt(int irq, void *dev_id) address = (unsigned long)(void *)buf; goldfish_tty_rw(qtty, address, count, 0); - tty_schedule_flip(&qtty->port); + tty_flip_buffer_push(&qtty->port); return IRQ_HANDLED; } diff --git a/drivers/tty/moxa.c b/drivers/tty/moxa.c index e37683e25055..f3c72ab1476c 100644 --- a/drivers/tty/moxa.c +++ b/drivers/tty/moxa.c @@ -1683,7 +1683,7 @@ static int moxa_poll_port(struct moxa_port *p, unsigned int handle, if (inited && !tty_throttled(tty) && MoxaPortRxQueue(p) > 0) { /* RX */ MoxaPortReadData(p); - tty_schedule_flip(&p->port); + tty_flip_buffer_push(&p->port); } } else { clear_bit(EMPTYWAIT, &p->statusflags); @@ -1708,7 +1708,7 @@ static int moxa_poll_port(struct moxa_port *p, unsigned int handle, if (tty && (intr & IntrBreak) && !I_IGNBRK(tty)) { /* BREAK */ tty_insert_flip_char(&p->port, 0, TTY_BREAK); - tty_schedule_flip(&p->port); + tty_flip_buffer_push(&p->port); } if (intr & IntrLine) diff --git a/drivers/tty/serial/lpc32xx_hs.c b/drivers/tty/serial/lpc32xx_hs.c index b199d7859961..07c4161eb4cc 100644 --- a/drivers/tty/serial/lpc32xx_hs.c +++ b/drivers/tty/serial/lpc32xx_hs.c @@ -341,7 +341,7 @@ static irqreturn_t serial_lpc32xx_interrupt(int irq, void *dev_id) LPC32XX_HSUART_IIR(port->membase)); port->icount.overrun++; tty_insert_flip_char(tport, 0, TTY_OVERRUN); - tty_schedule_flip(tport); + tty_flip_buffer_push(tport); } /* Data received? */ diff --git a/drivers/tty/vt/keyboard.c b/drivers/tty/vt/keyboard.c index c7fbbcdcc346..3700cd057f27 100644 --- a/drivers/tty/vt/keyboard.c +++ b/drivers/tty/vt/keyboard.c @@ -324,13 +324,13 @@ int kbd_rate(struct kbd_repeat *rpt) static void put_queue(struct vc_data *vc, int ch) { tty_insert_flip_char(&vc->port, ch, 0); - tty_schedule_flip(&vc->port); + tty_flip_buffer_push(&vc->port); } static void puts_queue(struct vc_data *vc, const char *cp) { tty_insert_flip_string(&vc->port, cp, strlen(cp)); - tty_schedule_flip(&vc->port); + tty_flip_buffer_push(&vc->port); } static void applkey(struct vc_data *vc, int key, char mode) @@ -584,7 +584,7 @@ static void fn_inc_console(struct vc_data *vc) static void fn_send_intr(struct vc_data *vc) { tty_insert_flip_char(&vc->port, 0, TTY_BREAK); - tty_schedule_flip(&vc->port); + tty_flip_buffer_push(&vc->port); } static void fn_scroll_forw(struct vc_data *vc) diff --git a/drivers/tty/vt/vt.c b/drivers/tty/vt/vt.c index 7359c3e80d63..f8c87c4d7399 100644 --- a/drivers/tty/vt/vt.c +++ b/drivers/tty/vt/vt.c @@ -1833,7 +1833,7 @@ static void csi_m(struct vc_data *vc) static void respond_string(const char *p, size_t len, struct tty_port *port) { tty_insert_flip_string(port, p, len); - tty_schedule_flip(port); + tty_flip_buffer_push(port); } static void cursor_report(struct vc_data *vc, struct tty_struct *tty) -- cgit From 5db96ef23bda6c2a61a51693c85b78b52d03f654 Mon Sep 17 00:00:00 2001 From: Jiri Slaby Date: Mon, 22 Nov 2021 12:16:48 +0100 Subject: tty: drop tty_schedule_flip() Since commit a9c3f68f3cd8d (tty: Fix low_latency BUG) in 2014, tty_flip_buffer_push() is only a wrapper to tty_schedule_flip(). All users were converted in the previous patches, so remove tty_schedule_flip() completely while inlining its body into tty_flip_buffer_push(). One less exported function. Reviewed-by: Johan Hovold Signed-off-by: Jiri Slaby Link: https://lore.kernel.org/r/20211122111648.30379-4-jslaby@suse.cz Signed-off-by: Greg Kroah-Hartman --- drivers/tty/tty_buffer.c | 30 ++++++++---------------------- 1 file changed, 8 insertions(+), 22 deletions(-) (limited to 'drivers/tty') diff --git a/drivers/tty/tty_buffer.c b/drivers/tty/tty_buffer.c index 6c7e65b1d9a1..5b6875057ce2 100644 --- a/drivers/tty/tty_buffer.c +++ b/drivers/tty/tty_buffer.c @@ -401,27 +401,6 @@ int __tty_insert_flip_char(struct tty_port *port, unsigned char ch, char flag) } EXPORT_SYMBOL(__tty_insert_flip_char); -/** - * tty_schedule_flip - push characters to ldisc - * @port: tty port to push from - * - * Takes any pending buffers and transfers their ownership to the - * ldisc side of the queue. It then schedules those characters for - * processing by the line discipline. - */ - -void tty_schedule_flip(struct tty_port *port) -{ - struct tty_bufhead *buf = &port->buf; - - /* paired w/ acquire in flush_to_ldisc(); ensures - * flush_to_ldisc() sees buffer data. - */ - smp_store_release(&buf->tail->commit, buf->tail->used); - queue_work(system_unbound_wq, &buf->work); -} -EXPORT_SYMBOL(tty_schedule_flip); - /** * tty_prepare_flip_string - make room for characters * @port: tty port @@ -566,7 +545,14 @@ static void flush_to_ldisc(struct work_struct *work) void tty_flip_buffer_push(struct tty_port *port) { - tty_schedule_flip(port); + struct tty_bufhead *buf = &port->buf; + + /* + * Paired w/ acquire in flush_to_ldisc(); ensures flush_to_ldisc() sees + * buffer data. + */ + smp_store_release(&buf->tail->commit, buf->tail->used); + queue_work(system_unbound_wq, &buf->work); } EXPORT_SYMBOL(tty_flip_buffer_push); -- cgit From d78328bcc4d0e677f2ff83f4ae1f43c933fbd143 Mon Sep 17 00:00:00 2001 From: Jiri Slaby Date: Mon, 22 Nov 2021 10:45:29 +0100 Subject: tty: remove file from tty_ldisc_ops::ioctl and compat_ioctl After the previous patches, noone needs 'file' parameter in neither ioctl hook from tty_ldisc_ops. So remove 'file' from both of them. Cc: Marcel Holtmann Cc: Johan Hedberg Cc: Luiz Augusto von Dentz Cc: Wolfgang Grandegger Cc: Marc Kleine-Budde Cc: "David S. Miller" Cc: Jakub Kicinski Cc: Andreas Koensgen Cc: Paul Mackerras Acked-by: Krzysztof Kozlowski [NFC] Acked-by: Dmitry Torokhov Acked-by: Marc Kleine-Budde Signed-off-by: Jiri Slaby Link: https://lore.kernel.org/r/20211122094529.24171-1-jslaby@suse.cz Signed-off-by: Greg Kroah-Hartman --- drivers/tty/n_gsm.c | 4 ++-- drivers/tty/n_hdlc.c | 5 ++--- drivers/tty/n_tty.c | 4 ++-- drivers/tty/tty_io.c | 8 ++++---- 4 files changed, 10 insertions(+), 11 deletions(-) (limited to 'drivers/tty') diff --git a/drivers/tty/n_gsm.c b/drivers/tty/n_gsm.c index 68e6df27d2e3..ba27b274c967 100644 --- a/drivers/tty/n_gsm.c +++ b/drivers/tty/n_gsm.c @@ -2687,8 +2687,8 @@ static __poll_t gsmld_poll(struct tty_struct *tty, struct file *file, return mask; } -static int gsmld_ioctl(struct tty_struct *tty, struct file *file, - unsigned int cmd, unsigned long arg) +static int gsmld_ioctl(struct tty_struct *tty, unsigned int cmd, + unsigned long arg) { struct gsm_config c; struct gsm_mux *gsm = tty->disc_data; diff --git a/drivers/tty/n_hdlc.c b/drivers/tty/n_hdlc.c index 7e0884ecc74f..a66915032e7e 100644 --- a/drivers/tty/n_hdlc.c +++ b/drivers/tty/n_hdlc.c @@ -572,14 +572,13 @@ static ssize_t n_hdlc_tty_write(struct tty_struct *tty, struct file *file, /** * n_hdlc_tty_ioctl - process IOCTL system call for the tty device. * @tty: pointer to tty instance data - * @file: pointer to open file object for device * @cmd: IOCTL command code * @arg: argument for IOCTL call (cmd dependent) * * Returns command dependent result. */ -static int n_hdlc_tty_ioctl(struct tty_struct *tty, struct file *file, - unsigned int cmd, unsigned long arg) +static int n_hdlc_tty_ioctl(struct tty_struct *tty, unsigned int cmd, + unsigned long arg) { struct n_hdlc *n_hdlc = tty->disc_data; int error = 0; diff --git a/drivers/tty/n_tty.c b/drivers/tty/n_tty.c index 5be6d02dc690..5b0f50373fc6 100644 --- a/drivers/tty/n_tty.c +++ b/drivers/tty/n_tty.c @@ -2400,8 +2400,8 @@ static unsigned long inq_canon(struct n_tty_data *ldata) return nr; } -static int n_tty_ioctl(struct tty_struct *tty, struct file *file, - unsigned int cmd, unsigned long arg) +static int n_tty_ioctl(struct tty_struct *tty, unsigned int cmd, + unsigned long arg) { struct n_tty_data *ldata = tty->disc_data; int retval; diff --git a/drivers/tty/tty_io.c b/drivers/tty/tty_io.c index 99cad1560876..3c2349b2089c 100644 --- a/drivers/tty/tty_io.c +++ b/drivers/tty/tty_io.c @@ -2811,7 +2811,7 @@ long tty_ioctl(struct file *file, unsigned int cmd, unsigned long arg) return hung_up_tty_ioctl(file, cmd, arg); retval = -EINVAL; if (ld->ops->ioctl) { - retval = ld->ops->ioctl(tty, file, cmd, arg); + retval = ld->ops->ioctl(tty, cmd, arg); if (retval == -ENOIOCTLCMD) retval = -ENOTTY; } @@ -2990,10 +2990,10 @@ static long tty_compat_ioctl(struct file *file, unsigned int cmd, if (!ld) return hung_up_tty_compat_ioctl(file, cmd, arg); if (ld->ops->compat_ioctl) - retval = ld->ops->compat_ioctl(tty, file, cmd, arg); + retval = ld->ops->compat_ioctl(tty, cmd, arg); if (retval == -ENOIOCTLCMD && ld->ops->ioctl) - retval = ld->ops->ioctl(tty, file, - (unsigned long)compat_ptr(cmd), arg); + retval = ld->ops->ioctl(tty, (unsigned long)compat_ptr(cmd), + arg); tty_ldisc_deref(ld); return retval; -- cgit From c67643b46c28fc8bb7d81c65bc7eef18c3fbe972 Mon Sep 17 00:00:00 2001 From: Fugang Duan Date: Thu, 25 Nov 2021 09:43:06 +0800 Subject: tty: serial: imx: clear the RTSD status before enable the RTSD irq MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Clear RTSD status before enabling the irq event for RTSD in imx_uart_enable_wakeup function. Since RTSD can be set as the wakeup source, this can avoid any risk of false triggering of a wake-up interrupts. Acked-by: Uwe Kleine-König Signed-off-by: Fugang Duan Signed-off-by: Sherry Sun Link: https://lore.kernel.org/r/20211125014306.4432-1-sherry.sun@nxp.com Signed-off-by: Greg Kroah-Hartman --- drivers/tty/serial/imx.c | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) (limited to 'drivers/tty') diff --git a/drivers/tty/serial/imx.c b/drivers/tty/serial/imx.c index 90f82e6c54e4..fb75e3e0d828 100644 --- a/drivers/tty/serial/imx.c +++ b/drivers/tty/serial/imx.c @@ -2482,10 +2482,12 @@ static void imx_uart_enable_wakeup(struct imx_port *sport, bool on) if (sport->have_rtscts) { u32 ucr1 = imx_uart_readl(sport, UCR1); - if (on) + if (on) { + imx_uart_writel(sport, USR1_RTSD, USR1); ucr1 |= UCR1_RTSDEN; - else + } else { ucr1 &= ~UCR1_RTSDEN; + } imx_uart_writel(sport, ucr1, UCR1); } } -- cgit From 028e083832b06fdeeb290e1e57dc1f6702c4c215 Mon Sep 17 00:00:00 2001 From: Fugang Duan Date: Thu, 25 Nov 2021 10:03:49 +0800 Subject: tty: serial: imx: disable UCR4_OREN in .stop_rx() instead of .shutdown() The UCR4_OREN should be disabled before disabling the uart receiver in .stop_rx() instead of in the .shutdown(). Otherwise, if we have the overrun error during the receiver disable process, the overrun interrupt will keep trigging until we disable the OREN interrupt in the .shutdown(), because the ORE status can only be cleared when read the rx FIFO or reset the controller. Although the called time between the receiver disable and OREN disable in .shutdown() is very short, there is still the risk of endless interrupt during this short period of time. So here change to disable OREN before the receiver been disabled in .stop_rx(). Signed-off-by: Fugang Duan Signed-off-by: Sherry Sun Link: https://lore.kernel.org/r/20211125020349.4980-1-sherry.sun@nxp.com Signed-off-by: Greg Kroah-Hartman --- drivers/tty/serial/imx.c | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) (limited to 'drivers/tty') diff --git a/drivers/tty/serial/imx.c b/drivers/tty/serial/imx.c index fb75e3e0d828..df8a0c8b8b29 100644 --- a/drivers/tty/serial/imx.c +++ b/drivers/tty/serial/imx.c @@ -486,18 +486,21 @@ static void imx_uart_stop_tx(struct uart_port *port) static void imx_uart_stop_rx(struct uart_port *port) { struct imx_port *sport = (struct imx_port *)port; - u32 ucr1, ucr2; + u32 ucr1, ucr2, ucr4; ucr1 = imx_uart_readl(sport, UCR1); ucr2 = imx_uart_readl(sport, UCR2); + ucr4 = imx_uart_readl(sport, UCR4); if (sport->dma_is_enabled) { ucr1 &= ~(UCR1_RXDMAEN | UCR1_ATDMAEN); } else { ucr1 &= ~UCR1_RRDYEN; ucr2 &= ~UCR2_ATEN; + ucr4 &= ~UCR4_OREN; } imx_uart_writel(sport, ucr1, UCR1); + imx_uart_writel(sport, ucr4, UCR4); ucr2 &= ~UCR2_RXEN; imx_uart_writel(sport, ucr2, UCR2); @@ -1544,7 +1547,7 @@ static void imx_uart_shutdown(struct uart_port *port) imx_uart_writel(sport, ucr1, UCR1); ucr4 = imx_uart_readl(sport, UCR4); - ucr4 &= ~(UCR4_OREN | UCR4_TCEN); + ucr4 &= ~UCR4_TCEN; imx_uart_writel(sport, ucr4, UCR4); spin_unlock_irqrestore(&sport->port.lock, flags); -- cgit From 1e67bd2b8cb90b66e89562598e9c2046246832d3 Mon Sep 17 00:00:00 2001 From: Tudor Ambarus Date: Thu, 25 Nov 2021 11:00:17 +0200 Subject: tty: serial: atmel: Check return code of dmaengine_submit() The tx_submit() method of struct dma_async_tx_descriptor is entitled to do sanity checks and return errors if encountered. It's not the case for the DMA controller drivers that this client is using (at_h/xdmac), because they currently don't do sanity checks and always return a positive cookie at tx_submit() method. In case the controller drivers will implement sanity checks and return errors, print a message so that the client will be informed that something went wrong at tx_submit() level. Fixes: 08f738be88bb ("serial: at91: add tx dma support") Signed-off-by: Tudor Ambarus Acked-by: Richard Genoud Link: https://lore.kernel.org/r/20211125090028.786832-3-tudor.ambarus@microchip.com Signed-off-by: Greg Kroah-Hartman --- drivers/tty/serial/atmel_serial.c | 10 ++++++++++ 1 file changed, 10 insertions(+) (limited to 'drivers/tty') diff --git a/drivers/tty/serial/atmel_serial.c b/drivers/tty/serial/atmel_serial.c index 2c99a47a2535..376f7a9c2868 100644 --- a/drivers/tty/serial/atmel_serial.c +++ b/drivers/tty/serial/atmel_serial.c @@ -1004,6 +1004,11 @@ static void atmel_tx_dma(struct uart_port *port) desc->callback = atmel_complete_tx_dma; desc->callback_param = atmel_port; atmel_port->cookie_tx = dmaengine_submit(desc); + if (dma_submit_error(atmel_port->cookie_tx)) { + dev_err(port->dev, "dma_submit_error %d\n", + atmel_port->cookie_tx); + return; + } } if (uart_circ_chars_pending(xmit) < WAKEUP_CHARS) @@ -1258,6 +1263,11 @@ static int atmel_prepare_rx_dma(struct uart_port *port) desc->callback_param = port; atmel_port->desc_rx = desc; atmel_port->cookie_rx = dmaengine_submit(desc); + if (dma_submit_error(atmel_port->cookie_rx)) { + dev_err(port->dev, "dma_submit_error %d\n", + atmel_port->cookie_rx); + goto chan_err; + } return 0; -- cgit From 4f4b9b5895614eb2e2b5f4cab7858f44bd113e1b Mon Sep 17 00:00:00 2001 From: Tudor Ambarus Date: Thu, 25 Nov 2021 11:00:18 +0200 Subject: tty: serial: atmel: Call dma_async_issue_pending() The driver wrongly assummed that tx_submit() will start the transfer, which is not the case, now that the at_xdmac driver is fixed. tx_submit is supposed to push the current transaction descriptor to a pending queue, waiting for issue_pending to be called. issue_pending must start the transfer, not tx_submit. Fixes: 34df42f59a60 ("serial: at91: add rx dma support") Fixes: 08f738be88bb ("serial: at91: add tx dma support") Signed-off-by: Tudor Ambarus Link: https://lore.kernel.org/r/20211125090028.786832-4-tudor.ambarus@microchip.com Signed-off-by: Greg Kroah-Hartman --- drivers/tty/serial/atmel_serial.c | 4 ++++ 1 file changed, 4 insertions(+) (limited to 'drivers/tty') diff --git a/drivers/tty/serial/atmel_serial.c b/drivers/tty/serial/atmel_serial.c index 376f7a9c2868..269b4500e9e7 100644 --- a/drivers/tty/serial/atmel_serial.c +++ b/drivers/tty/serial/atmel_serial.c @@ -1009,6 +1009,8 @@ static void atmel_tx_dma(struct uart_port *port) atmel_port->cookie_tx); return; } + + dma_async_issue_pending(chan); } if (uart_circ_chars_pending(xmit) < WAKEUP_CHARS) @@ -1269,6 +1271,8 @@ static int atmel_prepare_rx_dma(struct uart_port *port) goto chan_err; } + dma_async_issue_pending(atmel_port->chan_rx); + return 0; chan_err: -- cgit From cb6f6f9877928f6c3373f0b2088f05cda56344c5 Mon Sep 17 00:00:00 2001 From: Jiri Slaby Date: Fri, 26 Nov 2021 09:15:59 +0100 Subject: tty: reformat kernel-doc in tty_port.c Kernel-doc is a bit strict about some formatting. So fix these: 1) When there is a tab in comments, it thinks the line is a continuation one. So the description of the functions end up as descriptions of the last parameter described. Remove the tabs. 2) Remove newlines before parameters description. This was not wrong per se, only inconsistent with the rest of the file. 3) Add periods to the end of sentences where appropriate. 4) Use recognized "Note" instead of "NB" (nota bene). 5) Add "()" to function names and "%" to constants, so that they are properly highlighted. By the above, this patch also unifies these docs with the other kernel-doc's in this file. Signed-off-by: Jiri Slaby Link: https://lore.kernel.org/r/20211126081611.11001-12-jslaby@suse.cz Signed-off-by: Greg Kroah-Hartman --- drivers/tty/tty_port.c | 161 +++++++++++++++++++++++++++---------------------- 1 file changed, 88 insertions(+), 73 deletions(-) (limited to 'drivers/tty') diff --git a/drivers/tty/tty_port.c b/drivers/tty/tty_port.c index 2f1061a9d926..ebb441ee92d5 100644 --- a/drivers/tty/tty_port.c +++ b/drivers/tty/tty_port.c @@ -82,9 +82,9 @@ EXPORT_SYMBOL(tty_port_init); * @index: index of the tty * * Provide the tty layer with a link from a tty (specified by @index) to a - * tty_port (@port). Use this only if neither tty_port_register_device nor - * tty_port_install is used in the driver. If used, this has to be called before - * tty_register_driver. + * tty_port (@port). Use this only if neither tty_port_register_device() nor + * tty_port_install() is used in the driver. If used, this has to be called + * before tty_register_driver(). */ void tty_port_link_device(struct tty_port *port, struct tty_driver *driver, unsigned index) @@ -102,9 +102,9 @@ EXPORT_SYMBOL_GPL(tty_port_link_device); * @index: index of the tty * @device: parent if exists, otherwise NULL * - * It is the same as tty_register_device except the provided @port is linked to - * a concrete tty specified by @index. Use this or tty_port_install (or both). - * Call tty_port_link_device as a last resort. + * It is the same as tty_register_device() except the provided @port is linked + * to a concrete tty specified by @index. Use this or tty_port_install() (or + * both). Call tty_port_link_device() as a last resort. */ struct device *tty_port_register_device(struct tty_port *port, struct tty_driver *driver, unsigned index, @@ -123,9 +123,9 @@ EXPORT_SYMBOL_GPL(tty_port_register_device); * @drvdata: Driver data to be set to device. * @attr_grp: Attribute group to be set on device. * - * It is the same as tty_register_device_attr except the provided @port is - * linked to a concrete tty specified by @index. Use this or tty_port_install - * (or both). Call tty_port_link_device as a last resort. + * It is the same as tty_register_device_attr() except the provided @port is + * linked to a concrete tty specified by @index. Use this or tty_port_install() + * (or both). Call tty_port_link_device() as a last resort. */ struct device *tty_port_register_device_attr(struct tty_port *port, struct tty_driver *driver, unsigned index, @@ -240,9 +240,9 @@ EXPORT_SYMBOL(tty_port_free_xmit_buf); * tty_port_destroy -- destroy inited port * @port: tty port to be destroyed * - * When a port was initialized using tty_port_init, one has to destroy the - * port by this function. Either indirectly by using tty_port refcounting - * (tty_port_put) or directly if refcounting is not used. + * When a port was initialized using tty_port_init(), one has to destroy the + * port by this function. Either indirectly by using &tty_port refcounting + * (tty_port_put()) or directly if refcounting is not used. */ void tty_port_destroy(struct tty_port *port) { @@ -275,11 +275,11 @@ void tty_port_put(struct tty_port *port) EXPORT_SYMBOL(tty_port_put); /** - * tty_port_tty_get - get a tty reference - * @port: tty port + * tty_port_tty_get - get a tty reference + * @port: tty port * - * Return a refcount protected tty instance or NULL if the port is not - * associated with a tty (eg due to close or hangup) + * Return a refcount protected tty instance or %NULL if the port is not + * associated with a tty (eg due to close or hangup). */ struct tty_struct *tty_port_tty_get(struct tty_port *port) { @@ -294,12 +294,12 @@ struct tty_struct *tty_port_tty_get(struct tty_port *port) EXPORT_SYMBOL(tty_port_tty_get); /** - * tty_port_tty_set - set the tty of a port - * @port: tty port - * @tty: the tty + * tty_port_tty_set - set the tty of a port + * @port: tty port + * @tty: the tty * - * Associate the port and tty pair. Manages any internal refcounts. - * Pass NULL to deassociate a port + * Associate the port and tty pair. Manages any internal refcounts. Pass %NULL + * to deassociate a port. */ void tty_port_tty_set(struct tty_port *port, struct tty_struct *tty) { @@ -335,13 +335,13 @@ out: } /** - * tty_port_hangup - hangup helper - * @port: tty port + * tty_port_hangup - hangup helper + * @port: tty port * - * Perform port level tty hangup flag and count changes. Drop the tty - * reference. + * Perform port level tty hangup flag and count changes. Drop the tty + * reference. * - * Caller holds tty lock. + * Caller holds tty lock. */ void tty_port_hangup(struct tty_port *port) { @@ -365,9 +365,8 @@ EXPORT_SYMBOL(tty_port_hangup); /** * tty_port_tty_hangup - helper to hang up a tty - * * @port: tty port - * @check_clocal: hang only ttys with CLOCAL unset? + * @check_clocal: hang only ttys with %CLOCAL unset? */ void tty_port_tty_hangup(struct tty_port *port, bool check_clocal) { @@ -381,7 +380,6 @@ EXPORT_SYMBOL_GPL(tty_port_tty_hangup); /** * tty_port_tty_wakeup - helper to wake up a tty - * * @port: tty port */ void tty_port_tty_wakeup(struct tty_port *port) @@ -391,12 +389,12 @@ void tty_port_tty_wakeup(struct tty_port *port) EXPORT_SYMBOL_GPL(tty_port_tty_wakeup); /** - * tty_port_carrier_raised - carrier raised check - * @port: tty port + * tty_port_carrier_raised - carrier raised check + * @port: tty port * - * Wrapper for the carrier detect logic. For the moment this is used - * to hide some internal details. This will eventually become entirely - * internal to the tty port. + * Wrapper for the carrier detect logic. For the moment this is used + * to hide some internal details. This will eventually become entirely + * internal to the tty port. */ int tty_port_carrier_raised(struct tty_port *port) { @@ -407,12 +405,12 @@ int tty_port_carrier_raised(struct tty_port *port) EXPORT_SYMBOL(tty_port_carrier_raised); /** - * tty_port_raise_dtr_rts - Raise DTR/RTS - * @port: tty port + * tty_port_raise_dtr_rts - Raise DTR/RTS + * @port: tty port * - * Wrapper for the DTR/RTS raise logic. For the moment this is used - * to hide some internal details. This will eventually become entirely - * internal to the tty port. + * Wrapper for the DTR/RTS raise logic. For the moment this is used to hide + * some internal details. This will eventually become entirely internal to the + * tty port. */ void tty_port_raise_dtr_rts(struct tty_port *port) { @@ -422,12 +420,12 @@ void tty_port_raise_dtr_rts(struct tty_port *port) EXPORT_SYMBOL(tty_port_raise_dtr_rts); /** - * tty_port_lower_dtr_rts - Lower DTR/RTS - * @port: tty port + * tty_port_lower_dtr_rts - Lower DTR/RTS + * @port: tty port * - * Wrapper for the DTR/RTS raise logic. For the moment this is used - * to hide some internal details. This will eventually become entirely - * internal to the tty port. + * Wrapper for the DTR/RTS raise logic. For the moment this is used to hide + * some internal details. This will eventually become entirely internal to the + * tty port. */ void tty_port_lower_dtr_rts(struct tty_port *port) { @@ -437,28 +435,29 @@ void tty_port_lower_dtr_rts(struct tty_port *port) EXPORT_SYMBOL(tty_port_lower_dtr_rts); /** - * tty_port_block_til_ready - Waiting logic for tty open - * @port: the tty port being opened - * @tty: the tty device being bound - * @filp: the file pointer of the opener or NULL + * tty_port_block_til_ready - Waiting logic for tty open + * @port: the tty port being opened + * @tty: the tty device being bound + * @filp: the file pointer of the opener or %NULL + * + * Implement the core POSIX/SuS tty behaviour when opening a tty device. + * Handles: * - * Implement the core POSIX/SuS tty behaviour when opening a tty device. - * Handles: - * - hangup (both before and during) - * - non blocking open - * - rts/dtr/dcd - * - signals - * - port flags and counts + * - hangup (both before and during) + * - non blocking open + * - rts/dtr/dcd + * - signals + * - port flags and counts * - * The passed tty_port must implement the carrier_raised method if it can - * do carrier detect and the dtr_rts method if it supports software - * management of these lines. Note that the dtr/rts raise is done each - * iteration as a hangup may have previously dropped them while we wait. + * The passed @port must implement the @port->ops->carrier_raised method if it + * can do carrier detect and the @port->ops->dtr_rts method if it supports + * software management of these lines. Note that the dtr/rts raise is done each + * iteration as a hangup may have previously dropped them while we wait. * - * Caller holds tty lock. + * Caller holds tty lock. * - * NB: May drop and reacquire tty lock when blocking, so tty and tty_port - * may have changed state (eg., may have been hung up). + * Note: May drop and reacquire tty lock when blocking, so @tty and @port may + * have changed state (eg., may have been hung up). */ int tty_port_block_til_ready(struct tty_port *port, struct tty_struct *tty, struct file *filp) @@ -628,10 +627,18 @@ void tty_port_close_end(struct tty_port *port, struct tty_struct *tty) } EXPORT_SYMBOL(tty_port_close_end); -/* - * tty_port_close +/** + * tty_port_close - generic tty->ops->close handler + * @port: tty_port of the device + * @tty: tty being closed + * @filp: passed file pointer + * + * It is a generic helper to be used in driver's @tty->ops->close. It wraps a + * sequence of tty_port_close_start(), tty_port_shutdown(), and + * tty_port_close_end(). The latter two are called only if this is the last + * close. See the respective functions for the details. * - * Caller holds tty lock + * Locking: Caller holds tty lock */ void tty_port_close(struct tty_port *port, struct tty_struct *tty, struct file *filp) @@ -652,9 +659,9 @@ EXPORT_SYMBOL(tty_port_close); * @driver: tty_driver for this device * @tty: tty to be installed * - * It is the same as tty_standard_install except the provided @port is linked - * to a concrete tty specified by @tty. Use this or tty_port_register_device - * (or both). Call tty_port_link_device as a last resort. + * It is the same as tty_standard_install() except the provided @port is linked + * to a concrete tty specified by @tty. Use this or tty_port_register_device() + * (or both). Call tty_port_link_device() as a last resort. */ int tty_port_install(struct tty_port *port, struct tty_driver *driver, struct tty_struct *tty) @@ -664,13 +671,21 @@ int tty_port_install(struct tty_port *port, struct tty_driver *driver, } EXPORT_SYMBOL_GPL(tty_port_install); -/* - * tty_port_open +/** + * tty_port_open - generic tty->ops->open handler + * @port: tty_port of the device + * @tty: tty to be opened + * @filp: passed file pointer * - * Caller holds tty lock. + * It is a generic helper to be used in driver's @tty->ops->open. It activates + * the devices using @port->ops->activate if not active already. And waits for + * the device to be ready using tty_port_block_til_ready() (e.g. raises + * DTR/CTS and waits for carrier). + * + * Locking: Caller holds tty lock. * - * NB: may drop and reacquire tty lock (in tty_port_block_til_ready()) so - * tty and tty_port may have changed state (eg., may be hung up now) + * Note: may drop and reacquire tty lock (in tty_port_block_til_ready()) so + * @tty and @port may have changed state (eg., may be hung up now). */ int tty_port_open(struct tty_port *port, struct tty_struct *tty, struct file *filp) -- cgit From 796a75a98762f14006d2f941163b589f7ebcdf87 Mon Sep 17 00:00:00 2001 From: Jiri Slaby Date: Fri, 26 Nov 2021 09:16:00 +0100 Subject: tty: reformat kernel-doc in tty_io.c Kernel-doc is a bit strict about some formatting. So fix these: 1) When there is a tab in comments, it thinks the line is a continuation one. So the description of the functions end up as descriptions of the last parameter described. Remove the tabs. 2) Remove newlines before parameters description and after the comments. This was not wrong per se, only inconsistent with the rest of the file. 3) Add periods to the end of sentences where appropriate. 4) Add "()" to function names and "%" to constants, so that they are properly highlighted. By the above, this patch also unifies these docs with the other kernel-doc's in this file. Signed-off-by: Jiri Slaby Link: https://lore.kernel.org/r/20211126081611.11001-13-jslaby@suse.cz Signed-off-by: Greg Kroah-Hartman --- drivers/tty/tty_io.c | 871 +++++++++++++++++++++++++-------------------------- 1 file changed, 419 insertions(+), 452 deletions(-) (limited to 'drivers/tty') diff --git a/drivers/tty/tty_io.c b/drivers/tty/tty_io.c index 3c2349b2089c..b23269eb0cba 100644 --- a/drivers/tty/tty_io.c +++ b/drivers/tty/tty_io.c @@ -158,14 +158,13 @@ static int tty_fasync(int fd, struct file *filp, int on); static void release_tty(struct tty_struct *tty, int idx); /** - * free_tty_struct - free a disused tty - * @tty: tty struct to free + * free_tty_struct - free a disused tty + * @tty: tty struct to free * - * Free the write buffers, tty queue and tty memory itself. + * Free the write buffers, tty queue and tty memory itself. * - * Locking: none. Must be called after tty is definitely unused + * Locking: none. Must be called after tty is definitely unused */ - static void free_tty_struct(struct tty_struct *tty) { tty_ldisc_deinit(tty); @@ -206,8 +205,9 @@ void tty_add_file(struct tty_struct *tty, struct file *file) spin_unlock(&tty->files_lock); } -/* +/** * tty_free_file - free file->private_data + * @file: to free private_data of * * This shall be used only for fail path handling when tty_add_file was not * called yet. @@ -233,15 +233,14 @@ static void tty_del_file(struct file *file) } /** - * tty_name - return tty naming - * @tty: tty structure + * tty_name - return tty naming + * @tty: tty structure * - * Convert a tty structure into a name. The name reflects the kernel - * naming policy and if udev is in use may not reflect user space + * Convert a tty structure into a name. The name reflects the kernel naming + * policy and if udev is in use may not reflect user space * - * Locking: none + * Locking: none */ - const char *tty_name(const struct tty_struct *tty) { if (!tty) /* Hmm. NULL pointer. That's fun. */ @@ -303,16 +302,15 @@ static int check_tty_count(struct tty_struct *tty, const char *routine) } /** - * get_tty_driver - find device of a tty - * @device: device identifier - * @index: returns the index of the tty + * get_tty_driver - find device of a tty + * @device: device identifier + * @index: returns the index of the tty * - * This routine returns a tty driver structure, given a device number - * and also passes back the index number. + * This routine returns a tty driver structure, given a device number and also + * passes back the index number. * - * Locking: caller must hold tty_mutex + * Locking: caller must hold tty_mutex */ - static struct tty_driver *get_tty_driver(dev_t device, int *index) { struct tty_driver *p; @@ -329,17 +327,17 @@ static struct tty_driver *get_tty_driver(dev_t device, int *index) } /** - * tty_dev_name_to_number - return dev_t for device name - * @name: user space name of device under /dev - * @number: pointer to dev_t that this function will populate + * tty_dev_name_to_number - return dev_t for device name + * @name: user space name of device under /dev + * @number: pointer to dev_t that this function will populate * - * This function converts device names like ttyS0 or ttyUSB1 into dev_t - * like (4, 64) or (188, 1). If no corresponding driver is registered then - * the function returns -ENODEV. + * This function converts device names like ttyS0 or ttyUSB1 into dev_t like + * (4, 64) or (188, 1). If no corresponding driver is registered then the + * function returns -%ENODEV. * - * Locking: this acquires tty_mutex to protect the tty_drivers list from - * being modified while we are traversing it, and makes sure to - * release it before exiting. + * Locking: this acquires tty_mutex to protect the tty_drivers list from + * being modified while we are traversing it, and makes sure to + * release it before exiting. */ int tty_dev_name_to_number(const char *name, dev_t *number) { @@ -381,13 +379,12 @@ EXPORT_SYMBOL_GPL(tty_dev_name_to_number); #ifdef CONFIG_CONSOLE_POLL /** - * tty_find_polling_driver - find device of a polled tty - * @name: name string to match - * @line: pointer to resulting tty line nr + * tty_find_polling_driver - find device of a polled tty + * @name: name string to match + * @line: pointer to resulting tty line nr * - * This routine returns a tty driver structure, given a name - * and the condition that the tty driver is capable of polled - * operation. + * This routine returns a tty driver structure, given a name and the condition + * that the tty driver is capable of polled operation. */ struct tty_driver *tty_find_polling_driver(char *name, int *line) { @@ -515,14 +512,13 @@ static DEFINE_SPINLOCK(redirect_lock); static struct file *redirect; /** - * tty_wakeup - request more data - * @tty: terminal + * tty_wakeup - request more data + * @tty: terminal * - * Internal and external helper for wakeups of tty. This function - * informs the line discipline if present that the driver is ready - * to receive more output data. + * Internal and external helper for wakeups of tty. This function informs the + * line discipline if present that the driver is ready to receive more output + * data. */ - void tty_wakeup(struct tty_struct *tty) { struct tty_ldisc *ld; @@ -540,11 +536,11 @@ void tty_wakeup(struct tty_struct *tty) EXPORT_SYMBOL_GPL(tty_wakeup); /** - * tty_release_redirect - Release a redirect on a pty if present - * @tty: tty device + * tty_release_redirect - Release a redirect on a pty if present + * @tty: tty device * - * This is available to the pty code so if the master closes, if the - * slave is a redirect it can release the redirect. + * This is available to the pty code so if the master closes, if the slave is a + * redirect it can release the redirect. */ static struct file *tty_release_redirect(struct tty_struct *tty) { @@ -561,27 +557,29 @@ static struct file *tty_release_redirect(struct tty_struct *tty) } /** - * __tty_hangup - actual handler for hangup events - * @tty: tty device - * @exit_session: if non-zero, signal all foreground group processes - * - * This can be called by a "kworker" kernel thread. That is process - * synchronous but doesn't hold any locks, so we need to make sure we - * have the appropriate locks for what we're doing. - * - * The hangup event clears any pending redirections onto the hung up - * device. It ensures future writes will error and it does the needed - * line discipline hangup and signal delivery. The tty object itself - * remains intact. - * - * Locking: - * BTM - * redirect lock for undoing redirection - * file list lock for manipulating list of ttys - * tty_ldiscs_lock from called functions - * termios_rwsem resetting termios data - * tasklist_lock to walk task list for hangup event - * ->siglock to protect ->signal/->sighand + * __tty_hangup - actual handler for hangup events + * @tty: tty device + * @exit_session: if non-zero, signal all foreground group processes + * + * This can be called by a "kworker" kernel thread. That is process synchronous + * but doesn't hold any locks, so we need to make sure we have the appropriate + * locks for what we're doing. + * + * The hangup event clears any pending redirections onto the hung up device. It + * ensures future writes will error and it does the needed line discipline + * hangup and signal delivery. The tty object itself remains intact. + * + * Locking: + * * BTM + * + * * redirect lock for undoing redirection + * * file list lock for manipulating list of ttys + * * tty_ldiscs_lock from called functions + * * termios_rwsem resetting termios data + * * tasklist_lock to walk task list for hangup event + * + * * ->siglock to protect ->signal/->sighand + * */ static void __tty_hangup(struct tty_struct *tty, int exit_session) { @@ -682,13 +680,12 @@ static void do_tty_hangup(struct work_struct *work) } /** - * tty_hangup - trigger a hangup event - * @tty: tty to hangup + * tty_hangup - trigger a hangup event + * @tty: tty to hangup * - * A carrier loss (virtual or otherwise) has occurred on this like - * schedule a hangup sequence to run after this event. + * A carrier loss (virtual or otherwise) has occurred on @tty. Schedule a + * hangup sequence to run after this event. */ - void tty_hangup(struct tty_struct *tty) { tty_debug_hangup(tty, "hangup\n"); @@ -697,14 +694,13 @@ void tty_hangup(struct tty_struct *tty) EXPORT_SYMBOL(tty_hangup); /** - * tty_vhangup - process vhangup - * @tty: tty to hangup + * tty_vhangup - process vhangup + * @tty: tty to hangup * - * The user has asked via system call for the terminal to be hung up. - * We do this synchronously so that when the syscall returns the process - * is complete. That guarantee is necessary for security reasons. + * The user has asked via system call for the terminal to be hung up. We do + * this synchronously so that when the syscall returns the process is complete. + * That guarantee is necessary for security reasons. */ - void tty_vhangup(struct tty_struct *tty) { tty_debug_hangup(tty, "vhangup\n"); @@ -714,11 +710,10 @@ EXPORT_SYMBOL(tty_vhangup); /** - * tty_vhangup_self - process vhangup for own ctty + * tty_vhangup_self - process vhangup for own ctty * - * Perform a vhangup on the current controlling tty + * Perform a vhangup on the current controlling tty */ - void tty_vhangup_self(void) { struct tty_struct *tty; @@ -731,16 +726,15 @@ void tty_vhangup_self(void) } /** - * tty_vhangup_session - hangup session leader exit - * @tty: tty to hangup + * tty_vhangup_session - hangup session leader exit + * @tty: tty to hangup * - * The session leader is exiting and hanging up its controlling terminal. - * Every process in the foreground process group is signalled SIGHUP. + * The session leader is exiting and hanging up its controlling terminal. + * Every process in the foreground process group is signalled %SIGHUP. * - * We do this synchronously so that when the syscall returns the process - * is complete. That guarantee is necessary for security reasons. + * We do this synchronously so that when the syscall returns the process is + * complete. That guarantee is necessary for security reasons. */ - void tty_vhangup_session(struct tty_struct *tty) { tty_debug_hangup(tty, "session hangup\n"); @@ -748,13 +742,11 @@ void tty_vhangup_session(struct tty_struct *tty) } /** - * tty_hung_up_p - was tty hung up - * @filp: file pointer of tty + * tty_hung_up_p - was tty hung up + * @filp: file pointer of tty * - * Return true if the tty has been subject to a vhangup or a carrier - * loss + * Return: true if the tty has been subject to a vhangup or a carrier loss */ - int tty_hung_up_p(struct file *filp) { return (filp && filp->f_op == &hung_up_tty_fops); @@ -771,20 +763,18 @@ void __stop_tty(struct tty_struct *tty) } /** - * stop_tty - propagate flow control - * @tty: tty to stop + * stop_tty - propagate flow control + * @tty: tty to stop * - * Perform flow control to the driver. May be called - * on an already stopped device and will not re-call the driver - * method. + * Perform flow control to the driver. May be called on an already stopped + * device and will not re-call the &tty_driver->stop() method. * - * This functionality is used by both the line disciplines for - * halting incoming flow and by the driver. It may therefore be - * called from any context, may be under the tty atomic_write_lock - * but not always. + * This functionality is used by both the line disciplines for halting incoming + * flow and by the driver. It may therefore be called from any context, may be + * under the tty %atomic_write_lock but not always. * - * Locking: - * flow.lock + * Locking: + * flow.lock */ void stop_tty(struct tty_struct *tty) { @@ -807,15 +797,15 @@ void __start_tty(struct tty_struct *tty) } /** - * start_tty - propagate flow control - * @tty: tty to start + * start_tty - propagate flow control + * @tty: tty to start * - * Start a tty that has been stopped if at all possible. If this - * tty was previous stopped and is now being started, the driver - * start method is invoked and the line discipline woken. + * Start a tty that has been stopped if at all possible. If @tty was previously + * stopped and is now being started, the &tty_driver->start() method is invoked + * and the line discipline woken. * - * Locking: - * flow.lock + * Locking: + * flow.lock */ void start_tty(struct tty_struct *tty) { @@ -908,18 +898,17 @@ static int iterate_tty_read(struct tty_ldisc *ld, struct tty_struct *tty, /** - * tty_read - read method for tty device files - * @iocb: kernel I/O control block - * @to: destination for the data read + * tty_read - read method for tty device files + * @iocb: kernel I/O control block + * @to: destination for the data read * - * Perform the read system call function on this terminal device. Checks - * for hung up devices before calling the line discipline method. + * Perform the read system call function on this terminal device. Checks + * for hung up devices before calling the line discipline method. * - * Locking: - * Locks the line discipline internally while needed. Multiple - * read calls may be outstanding in parallel. + * Locking: + * Locks the line discipline internally while needed. Multiple read calls + * may be outstanding in parallel. */ - static ssize_t tty_read(struct kiocb *iocb, struct iov_iter *to) { int i; @@ -1069,13 +1058,12 @@ out: * @tty: the destination tty_struct * @msg: the message to write * - * This is used for messages that need to be redirected to a specific tty. - * We don't put it into the syslog queue right now maybe in the future if - * really needed. + * This is used for messages that need to be redirected to a specific tty. We + * don't put it into the syslog queue right now maybe in the future if really + * needed. * * We must still hold the BTM and test the CLOSING flag for the moment. */ - void tty_write_message(struct tty_struct *tty, char *msg) { if (tty) { @@ -1113,18 +1101,18 @@ static ssize_t file_tty_write(struct file *file, struct kiocb *iocb, struct iov_ } /** - * tty_write - write method for tty device file - * @iocb: kernel I/O control block - * @from: iov_iter with data to write + * tty_write - write method for tty device file + * @iocb: kernel I/O control block + * @from: iov_iter with data to write * - * Write data to a tty device via the line discipline. + * Write data to a tty device via the line discipline. * - * Locking: - * Locks the line discipline as required - * Writes to the tty driver are serialized by the atomic_write_lock - * and are then processed in chunks to the device. The line - * discipline write method will not be invoked in parallel for - * each device. + * Locking: + * Locks the line discipline as required + * Writes to the tty driver are serialized by the atomic_write_lock + * and are then processed in chunks to the device. The line + * discipline write method will not be invoked in parallel for + * each device. */ static ssize_t tty_write(struct kiocb *iocb, struct iov_iter *from) { @@ -1154,14 +1142,15 @@ ssize_t redirected_tty_write(struct kiocb *iocb, struct iov_iter *iter) return tty_write(iocb, iter); } -/* - * tty_send_xchar - send priority character +/** + * tty_send_xchar - send priority character + * @tty: the tty to send to + * @ch: xchar to send * - * Send a high priority character to the tty even if stopped + * Send a high priority character to the tty even if stopped. * - * Locking: none for xchar method, write ordering for write method. + * Locking: none for xchar method, write ordering for write method. */ - int tty_send_xchar(struct tty_struct *tty, char ch) { bool was_stopped = tty->flow.stopped; @@ -1188,15 +1177,15 @@ int tty_send_xchar(struct tty_struct *tty, char ch) } /** - * pty_line_name - generate name for a pty - * @driver: the tty driver in use - * @index: the minor number - * @p: output buffer of at least 6 bytes + * pty_line_name - generate name for a pty + * @driver: the tty driver in use + * @index: the minor number + * @p: output buffer of at least 6 bytes * - * Generate a name from a driver reference and write it to the output - * buffer. + * Generate a name from a @driver reference and write it to the output buffer + * @p. * - * Locking: None + * Locking: None */ static void pty_line_name(struct tty_driver *driver, int index, char *p) { @@ -1209,15 +1198,15 @@ static void pty_line_name(struct tty_driver *driver, int index, char *p) } /** - * tty_line_name - generate name for a tty - * @driver: the tty driver in use - * @index: the minor number - * @p: output buffer of at least 7 bytes + * tty_line_name - generate name for a tty + * @driver: the tty driver in use + * @index: the minor number + * @p: output buffer of at least 7 bytes * - * Generate a name from a driver reference and write it to the output - * buffer. + * Generate a name from a @driver reference and write it to the output buffer + * @p. * - * Locking: None + * Locking: None */ static ssize_t tty_line_name(struct tty_driver *driver, int index, char *p) { @@ -1229,15 +1218,15 @@ static ssize_t tty_line_name(struct tty_driver *driver, int index, char *p) } /** - * tty_driver_lookup_tty() - find an existing tty, if any - * @driver: the driver for the tty - * @file: file object - * @idx: the minor number + * tty_driver_lookup_tty() - find an existing tty, if any + * @driver: the driver for the tty + * @file: file object + * @idx: the minor number * - * Return the tty, if found. If not found, return NULL or ERR_PTR() if the - * driver lookup() method returns an error. + * Return: the tty, if found. If not found, return %NULL or ERR_PTR() if the + * driver lookup() method returns an error. * - * Locking: tty_mutex must be held. If the tty is found, bump the tty kref. + * Locking: tty_mutex must be held. If the tty is found, bump the tty kref. */ static struct tty_struct *tty_driver_lookup_tty(struct tty_driver *driver, struct file *file, int idx) @@ -1258,13 +1247,12 @@ static struct tty_struct *tty_driver_lookup_tty(struct tty_driver *driver, } /** - * tty_init_termios - helper for termios setup - * @tty: the tty to set up + * tty_init_termios - helper for termios setup + * @tty: the tty to set up * - * Initialise the termios structure for this tty. This runs under - * the tty_mutex currently so we can be relaxed about ordering. + * Initialise the termios structure for this tty. This runs under the + * %tty_mutex currently so we can be relaxed about ordering. */ - void tty_init_termios(struct tty_struct *tty) { struct ktermios *tp; @@ -1298,16 +1286,15 @@ int tty_standard_install(struct tty_driver *driver, struct tty_struct *tty) EXPORT_SYMBOL_GPL(tty_standard_install); /** - * tty_driver_install_tty() - install a tty entry in the driver - * @driver: the driver for the tty - * @tty: the tty + * tty_driver_install_tty() - install a tty entry in the driver + * @driver: the driver for the tty + * @tty: the tty * - * Install a tty object into the driver tables. The tty->index field - * will be set by the time this is called. This method is responsible - * for ensuring any need additional structures are allocated and - * configured. + * Install a tty object into the driver tables. The @tty->index field will be + * set by the time this is called. This method is responsible for ensuring any + * need additional structures are allocated and configured. * - * Locking: tty_mutex for now + * Locking: tty_mutex for now */ static int tty_driver_install_tty(struct tty_driver *driver, struct tty_struct *tty) @@ -1317,14 +1304,14 @@ static int tty_driver_install_tty(struct tty_driver *driver, } /** - * tty_driver_remove_tty() - remove a tty from the driver tables - * @driver: the driver for the tty - * @tty: tty to remove + * tty_driver_remove_tty() - remove a tty from the driver tables + * @driver: the driver for the tty + * @tty: tty to remove * - * Remvoe a tty object from the driver tables. The tty->index field - * will be set by the time this is called. + * Remove a tty object from the driver tables. The tty->index field will be set + * by the time this is called. * - * Locking: tty_mutex for now + * Locking: tty_mutex for now */ static void tty_driver_remove_tty(struct tty_driver *driver, struct tty_struct *tty) { @@ -1335,13 +1322,13 @@ static void tty_driver_remove_tty(struct tty_driver *driver, struct tty_struct * } /** - * tty_reopen() - fast re-open of an open tty - * @tty: the tty to open + * tty_reopen() - fast re-open of an open tty + * @tty: the tty to open * - * Return 0 on success, -errno on error. - * Re-opens on master ptys are not allowed and return -EIO. + * Re-opens on master ptys are not allowed and return -%EIO. * - * Locking: Caller must hold tty_lock + * Locking: Caller must hold tty_lock + * Return: 0 on success, -errno on error. */ static int tty_reopen(struct tty_struct *tty) { @@ -1379,30 +1366,28 @@ static int tty_reopen(struct tty_struct *tty) } /** - * tty_init_dev - initialise a tty device - * @driver: tty driver we are opening a device on - * @idx: device index + * tty_init_dev - initialise a tty device + * @driver: tty driver we are opening a device on + * @idx: device index * - * Prepare a tty device. This may not be a "new" clean device but - * could also be an active device. The pty drivers require special - * handling because of this. + * Prepare a tty device. This may not be a "new" clean device but could also be + * an active device. The pty drivers require special handling because of this. * - * Locking: - * The function is called under the tty_mutex, which - * protects us from the tty struct or driver itself going away. + * Locking: + * The function is called under the tty_mutex, which protects us from the + * tty struct or driver itself going away. * - * On exit the tty device has the line discipline attached and - * a reference count of 1. If a pair was created for pty/tty use - * and the other was a pty master then it too has a reference count of 1. + * On exit the tty device has the line discipline attached and a reference + * count of 1. If a pair was created for pty/tty use and the other was a pty + * master then it too has a reference count of 1. * - * WSH 06/09/97: Rewritten to remove races and properly clean up after a - * failed open. The new code protects the open with a mutex, so it's - * really quite straightforward. The mutex locking can probably be - * relaxed for the (most common) case of reopening a tty. + * WSH 06/09/97: Rewritten to remove races and properly clean up after a failed + * open. The new code protects the open with a mutex, so it's really quite + * straightforward. The mutex locking can probably be relaxed for the (most + * common) case of reopening a tty. * - * Return: returned tty structure + * Return: new tty structure */ - struct tty_struct *tty_init_dev(struct tty_driver *driver, int idx) { struct tty_struct *tty; @@ -1503,10 +1488,10 @@ void tty_save_termios(struct tty_struct *tty) EXPORT_SYMBOL_GPL(tty_save_termios); /** - * tty_flush_works - flush all works of a tty/pty pair - * @tty: tty device to flush works for (or either end of a pty pair) + * tty_flush_works - flush all works of a tty/pty pair + * @tty: tty device to flush works for (or either end of a pty pair) * - * Sync flush all works belonging to @tty (and the 'other' tty). + * Sync flush all works belonging to @tty (and the 'other' tty). */ static void tty_flush_works(struct tty_struct *tty) { @@ -1519,19 +1504,19 @@ static void tty_flush_works(struct tty_struct *tty) } /** - * release_one_tty - release tty structure memory - * @work: work of tty we are obliterating + * release_one_tty - release tty structure memory + * @work: work of tty we are obliterating * - * Releases memory associated with a tty structure, and clears out the - * driver table slots. This function is called when a device is no longer - * in use. It also gets called when setup of a device fails. + * Releases memory associated with a tty structure, and clears out the + * driver table slots. This function is called when a device is no longer + * in use. It also gets called when setup of a device fails. * - * Locking: - * takes the file list lock internally when working on the list - * of ttys that the driver keeps. + * Locking: + * takes the file list lock internally when working on the list of ttys + * that the driver keeps. * - * This method gets called from a work queue so that the driver private - * cleanup ops can sleep (needed for USB at least) + * This method gets called from a work queue so that the driver private + * cleanup ops can sleep (needed for USB at least) */ static void release_one_tty(struct work_struct *work) { @@ -1568,13 +1553,12 @@ static void queue_release_one_tty(struct kref *kref) } /** - * tty_kref_put - release a tty kref - * @tty: tty device + * tty_kref_put - release a tty kref + * @tty: tty device * - * Release a reference to a tty device and if need be let the kref - * layer destruct the object for us + * Release a reference to the @tty device and if need be let the kref layer + * destruct the object for us. */ - void tty_kref_put(struct tty_struct *tty) { if (tty) @@ -1583,18 +1567,17 @@ void tty_kref_put(struct tty_struct *tty) EXPORT_SYMBOL(tty_kref_put); /** - * release_tty - release tty structure memory - * @tty: tty device release - * @idx: index of the tty device release - * - * Release both @tty and a possible linked partner (think pty pair), - * and decrement the refcount of the backing module. + * release_tty - release tty structure memory + * @tty: tty device release + * @idx: index of the tty device release * - * Locking: - * tty_mutex - * takes the file list lock internally when working on the list - * of ttys that the driver keeps. + * Release both @tty and a possible linked partner (think pty pair), + * and decrement the refcount of the backing module. * + * Locking: + * tty_mutex + * takes the file list lock internally when working on the list of ttys + * that the driver keeps. */ static void release_tty(struct tty_struct *tty, int idx) { @@ -1619,12 +1602,12 @@ static void release_tty(struct tty_struct *tty, int idx) } /** - * tty_release_checks - check a tty before real release - * @tty: tty to check - * @idx: index of the tty + * tty_release_checks - check a tty before real release + * @tty: tty to check + * @idx: index of the tty * - * Performs some paranoid checking before true release of the @tty. - * This is a no-op unless TTY_PARANOIA_CHECK is defined. + * Performs some paranoid checking before true release of the @tty. This is a + * no-op unless %TTY_PARANOIA_CHECK is defined. */ static int tty_release_checks(struct tty_struct *tty, int idx) { @@ -1661,12 +1644,12 @@ static int tty_release_checks(struct tty_struct *tty, int idx) } /** - * tty_kclose - closes tty opened by tty_kopen - * @tty: tty device + * tty_kclose - closes tty opened by tty_kopen + * @tty: tty device * - * Performs the final steps to release and free a tty device. It is the - * same as tty_release_struct except that it also resets TTY_PORT_KOPENED - * flag on tty->port. + * Performs the final steps to release and free a tty device. It is the same as + * tty_release_struct() except that it also resets %TTY_PORT_KOPENED flag on + * @tty->port. */ void tty_kclose(struct tty_struct *tty) { @@ -1691,12 +1674,12 @@ void tty_kclose(struct tty_struct *tty) EXPORT_SYMBOL_GPL(tty_kclose); /** - * tty_release_struct - release a tty struct - * @tty: tty device - * @idx: index of the tty + * tty_release_struct - release a tty struct + * @tty: tty device + * @idx: index of the tty * - * Performs the final steps to release and free a tty device. It is - * roughly the reverse of tty_init_dev. + * Performs the final steps to release and free a tty device. It is roughly the + * reverse of tty_init_dev(). */ void tty_release_struct(struct tty_struct *tty, int idx) { @@ -1720,24 +1703,23 @@ void tty_release_struct(struct tty_struct *tty, int idx) EXPORT_SYMBOL_GPL(tty_release_struct); /** - * tty_release - vfs callback for close - * @inode: inode of tty - * @filp: file pointer for handle to tty + * tty_release - vfs callback for close + * @inode: inode of tty + * @filp: file pointer for handle to tty * - * Called the last time each file handle is closed that references - * this tty. There may however be several such references. + * Called the last time each file handle is closed that references this tty. + * There may however be several such references. * - * Locking: - * Takes bkl. See tty_release_dev + * Locking: + * Takes BKL. See tty_release_dev(). * - * Even releasing the tty structures is a tricky business.. We have - * to be very careful that the structures are all released at the - * same time, as interrupts might otherwise get the wrong pointers. + * Even releasing the tty structures is a tricky business. We have to be very + * careful that the structures are all released at the same time, as interrupts + * might otherwise get the wrong pointers. * * WSH 09/09/97: rewritten to avoid some nasty race conditions that could * lead to double frees or releasing memory still in use. */ - int tty_release(struct inode *inode, struct file *filp) { struct tty_struct *tty = file_tty(filp); @@ -1880,15 +1862,15 @@ int tty_release(struct inode *inode, struct file *filp) } /** - * tty_open_current_tty - get locked tty of current task - * @device: device number - * @filp: file pointer to tty - * @return: locked tty of the current task iff @device is /dev/tty + * tty_open_current_tty - get locked tty of current task + * @device: device number + * @filp: file pointer to tty + * @return: locked tty of the current task iff @device is /dev/tty * - * Performs a re-open of the current task's controlling tty. + * Performs a re-open of the current task's controlling tty. * - * We cannot return driver and index like for the other nodes because - * devpts will not work then. It expects inodes to be from devpts FS. + * We cannot return driver and index like for the other nodes because devpts + * will not work then. It expects inodes to be from devpts FS. */ static struct tty_struct *tty_open_current_tty(dev_t device, struct file *filp) { @@ -1916,16 +1898,17 @@ static struct tty_struct *tty_open_current_tty(dev_t device, struct file *filp) } /** - * tty_lookup_driver - lookup a tty driver for a given device file - * @device: device number - * @filp: file pointer to tty - * @index: index for the device in the @return driver - * @return: driver for this inode (with increased refcount) + * tty_lookup_driver - lookup a tty driver for a given device file + * @device: device number + * @filp: file pointer to tty + * @index: index for the device in the @return driver * - * If @return is not erroneous, the caller is responsible to decrement the - * refcount by tty_driver_kref_put. + * If returned value is not erroneous, the caller is responsible to decrement + * the refcount by tty_driver_kref_put(). * - * Locking: tty_mutex protects get_tty_driver + * Locking: %tty_mutex protects get_tty_driver() + * + * Return: driver for this inode (with increased refcount) */ static struct tty_driver *tty_lookup_driver(dev_t device, struct file *filp, int *index) @@ -2001,19 +1984,18 @@ out: } /** - * tty_kopen_exclusive - open a tty device for kernel - * @device: dev_t of device to open + * tty_kopen_exclusive - open a tty device for kernel + * @device: dev_t of device to open * - * Opens tty exclusively for kernel. Performs the driver lookup, - * makes sure it's not already opened and performs the first-time - * tty initialization. + * Opens tty exclusively for kernel. Performs the driver lookup, makes sure + * it's not already opened and performs the first-time tty initialization. * - * Returns the locked initialized &tty_struct + * Claims the global %tty_mutex to serialize: + * * concurrent first-time tty initialization + * * concurrent tty driver removal w/ lookup + * * concurrent tty removal from driver table * - * Claims the global tty_mutex to serialize: - * - concurrent first-time tty initialization - * - concurrent tty driver removal w/ lookup - * - concurrent tty removal from driver table + * Return: the locked initialized &tty_struct */ struct tty_struct *tty_kopen_exclusive(dev_t device) { @@ -2022,13 +2004,13 @@ struct tty_struct *tty_kopen_exclusive(dev_t device) EXPORT_SYMBOL_GPL(tty_kopen_exclusive); /** - * tty_kopen_shared - open a tty device for shared in-kernel use - * @device: dev_t of device to open + * tty_kopen_shared - open a tty device for shared in-kernel use + * @device: dev_t of device to open * - * Opens an already existing tty for in-kernel use. Compared to - * tty_kopen_exclusive() above it doesn't ensure to be the only user. + * Opens an already existing tty for in-kernel use. Compared to + * tty_kopen_exclusive() above it doesn't ensure to be the only user. * - * Locking is identical to tty_kopen() above. + * Locking: identical to tty_kopen() above. */ struct tty_struct *tty_kopen_shared(dev_t device) { @@ -2037,19 +2019,20 @@ struct tty_struct *tty_kopen_shared(dev_t device) EXPORT_SYMBOL_GPL(tty_kopen_shared); /** - * tty_open_by_driver - open a tty device - * @device: dev_t of device to open - * @filp: file pointer to tty + * tty_open_by_driver - open a tty device + * @device: dev_t of device to open + * @filp: file pointer to tty + * + * Performs the driver lookup, checks for a reopen, or otherwise performs the + * first-time tty initialization. * - * Performs the driver lookup, checks for a reopen, or otherwise - * performs the first-time tty initialization. * - * Returns the locked initialized or re-opened &tty_struct + * Claims the global tty_mutex to serialize: + * * concurrent first-time tty initialization + * * concurrent tty driver removal w/ lookup + * * concurrent tty removal from driver table * - * Claims the global tty_mutex to serialize: - * - concurrent first-time tty initialization - * - concurrent tty driver removal w/ lookup - * - concurrent tty removal from driver table + * Return: the locked initialized or re-opened &tty_struct */ static struct tty_struct *tty_open_by_driver(dev_t device, struct file *filp) @@ -2104,29 +2087,28 @@ out: } /** - * tty_open - open a tty device - * @inode: inode of device file - * @filp: file pointer to tty + * tty_open - open a tty device + * @inode: inode of device file + * @filp: file pointer to tty * - * tty_open and tty_release keep up the tty count that contains the - * number of opens done on a tty. We cannot use the inode-count, as - * different inodes might point to the same tty. + * tty_open() and tty_release() keep up the tty count that contains the number + * of opens done on a tty. We cannot use the inode-count, as different inodes + * might point to the same tty. * - * Open-counting is needed for pty masters, as well as for keeping - * track of serial lines: DTR is dropped when the last close happens. - * (This is not done solely through tty->count, now. - Ted 1/27/92) + * Open-counting is needed for pty masters, as well as for keeping track of + * serial lines: DTR is dropped when the last close happens. + * (This is not done solely through tty->count, now. - Ted 1/27/92) * - * The termios state of a pty is reset on first open so that - * settings don't persist across reuse. + * The termios state of a pty is reset on the first open so that settings don't + * persist across reuse. * - * Locking: tty_mutex protects tty, tty_lookup_driver and tty_init_dev. - * tty->count should protect the rest. - * ->siglock protects ->signal/->sighand + * Locking: + * * %tty_mutex protects tty, tty_lookup_driver() and tty_init_dev(). + * * @tty->count should protect the rest. + * * ->siglock protects ->signal/->sighand * - * Note: the tty_unlock/lock cases without a ref are only safe due to - * tty_mutex + * Note: the tty_unlock/lock cases without a ref are only safe due to %tty_mutex */ - static int tty_open(struct inode *inode, struct file *filp) { struct tty_struct *tty; @@ -2198,19 +2180,17 @@ retry_open: } - /** - * tty_poll - check tty status - * @filp: file being polled - * @wait: poll wait structures to update + * tty_poll - check tty status + * @filp: file being polled + * @wait: poll wait structures to update * - * Call the line discipline polling method to obtain the poll - * status of the device. + * Call the line discipline polling method to obtain the poll status of the + * device. * - * Locking: locks called line discipline but ldisc poll method - * may be re-entered freely by other callers. + * Locking: locks called line discipline but ldisc poll method may be + * re-entered freely by other callers. */ - static __poll_t tty_poll(struct file *filp, poll_table *wait) { struct tty_struct *tty = file_tty(filp); @@ -2278,20 +2258,18 @@ static int tty_fasync(int fd, struct file *filp, int on) } /** - * tiocsti - fake input character - * @tty: tty to fake input into - * @p: pointer to character + * tiocsti - fake input character + * @tty: tty to fake input into + * @p: pointer to character * - * Fake input to a tty device. Does the necessary locking and - * input management. + * Fake input to a tty device. Does the necessary locking and input management. * - * FIXME: does not honour flow control ?? + * FIXME: does not honour flow control ?? * - * Locking: - * Called functions take tty_ldiscs_lock - * current->signal->tty check is safe without locks + * Locking: + * * Called functions take tty_ldiscs_lock + * * current->signal->tty check is safe without locks */ - static int tiocsti(struct tty_struct *tty, char __user *p) { char ch, mbz = 0; @@ -2314,16 +2292,15 @@ static int tiocsti(struct tty_struct *tty, char __user *p) } /** - * tiocgwinsz - implement window query ioctl - * @tty: tty - * @arg: user buffer for result + * tiocgwinsz - implement window query ioctl + * @tty: tty + * @arg: user buffer for result * - * Copies the kernel idea of the window size into the user buffer. + * Copies the kernel idea of the window size into the user buffer. * - * Locking: tty->winsize_mutex is taken to ensure the winsize data - * is consistent. + * Locking: @tty->winsize_mutex is taken to ensure the winsize data is + * consistent. */ - static int tiocgwinsz(struct tty_struct *tty, struct winsize __user *arg) { int err; @@ -2336,14 +2313,13 @@ static int tiocgwinsz(struct tty_struct *tty, struct winsize __user *arg) } /** - * tty_do_resize - resize event - * @tty: tty being resized - * @ws: new dimensions + * tty_do_resize - resize event + * @tty: tty being resized + * @ws: new dimensions * - * Update the termios variables and send the necessary signals to - * peform a terminal resize correctly + * Update the termios variables and send the necessary signals to peform a + * terminal resize correctly. */ - int tty_do_resize(struct tty_struct *tty, struct winsize *ws) { struct pid *pgrp; @@ -2367,20 +2343,19 @@ done: EXPORT_SYMBOL(tty_do_resize); /** - * tiocswinsz - implement window size set ioctl - * @tty: tty side of tty - * @arg: user buffer for result + * tiocswinsz - implement window size set ioctl + * @tty: tty side of tty + * @arg: user buffer for result * - * Copies the user idea of the window size to the kernel. Traditionally - * this is just advisory information but for the Linux console it - * actually has driver level meaning and triggers a VC resize. + * Copies the user idea of the window size to the kernel. Traditionally this is + * just advisory information but for the Linux console it actually has driver + * level meaning and triggers a VC resize. * - * Locking: - * Driver dependent. The default do_resize method takes the - * tty termios mutex and ctrl.lock. The console takes its own lock - * then calls into the default method. + * Locking: + * Driver dependent. The default do_resize method takes the tty termios + * mutex and ctrl.lock. The console takes its own lock then calls into the + * default method. */ - static int tiocswinsz(struct tty_struct *tty, struct winsize __user *arg) { struct winsize tmp_ws; @@ -2395,14 +2370,13 @@ static int tiocswinsz(struct tty_struct *tty, struct winsize __user *arg) } /** - * tioccons - allow admin to move logical console - * @file: the file to become console + * tioccons - allow admin to move logical console + * @file: the file to become console * - * Allow the administrator to move the redirected console device + * Allow the administrator to move the redirected console device. * - * Locking: uses redirect_lock to guard the redirect information + * Locking: uses redirect_lock to guard the redirect information */ - static int tioccons(struct file *file) { if (!capable(CAP_SYS_ADMIN)) @@ -2435,15 +2409,14 @@ static int tioccons(struct file *file) } /** - * tiocsetd - set line discipline - * @tty: tty device - * @p: pointer to user data + * tiocsetd - set line discipline + * @tty: tty device + * @p: pointer to user data * - * Set the line discipline according to user request. + * Set the line discipline according to user request. * - * Locking: see tty_set_ldisc, this function is just a helper + * Locking: see tty_set_ldisc(), this function is just a helper */ - static int tiocsetd(struct tty_struct *tty, int __user *p) { int disc; @@ -2458,16 +2431,15 @@ static int tiocsetd(struct tty_struct *tty, int __user *p) } /** - * tiocgetd - get line discipline - * @tty: tty device - * @p: pointer to user data + * tiocgetd - get line discipline + * @tty: tty device + * @p: pointer to user data * - * Retrieves the line discipline id directly from the ldisc. + * Retrieves the line discipline id directly from the ldisc. * - * Locking: waits for ldisc reference (in case the line discipline - * is changing or the tty is being hungup) + * Locking: waits for ldisc reference (in case the line discipline is changing + * or the @tty is being hungup) */ - static int tiocgetd(struct tty_struct *tty, int __user *p) { struct tty_ldisc *ld; @@ -2482,18 +2454,16 @@ static int tiocgetd(struct tty_struct *tty, int __user *p) } /** - * send_break - performed time break - * @tty: device to break on - * @duration: timeout in mS + * send_break - performed time break + * @tty: device to break on + * @duration: timeout in mS * - * Perform a timed break on hardware that lacks its own driver level - * timed break functionality. - * - * Locking: - * atomic_write_lock serializes + * Perform a timed break on hardware that lacks its own driver level timed + * break functionality. * + * Locking: + * @tty->atomic_write_lock serializes */ - static int send_break(struct tty_struct *tty, unsigned int duration) { int retval; @@ -2522,16 +2492,15 @@ out: } /** - * tty_tiocmget - get modem status - * @tty: tty device - * @p: pointer to result + * tty_tiocmget - get modem status + * @tty: tty device + * @p: pointer to result * - * Obtain the modem status bits from the tty driver if the feature - * is supported. Return -ENOTTY if it is not available. + * Obtain the modem status bits from the tty driver if the feature is + * supported. Return -%ENOTTY if it is not available. * - * Locking: none (up to the driver) + * Locking: none (up to the driver) */ - static int tty_tiocmget(struct tty_struct *tty, int __user *p) { int retval = -ENOTTY; @@ -2546,17 +2515,16 @@ static int tty_tiocmget(struct tty_struct *tty, int __user *p) } /** - * tty_tiocmset - set modem status - * @tty: tty device - * @cmd: command - clear bits, set bits or set all - * @p: pointer to desired bits + * tty_tiocmset - set modem status + * @tty: tty device + * @cmd: command - clear bits, set bits or set all + * @p: pointer to desired bits * - * Set the modem status bits from the tty driver if the feature - * is supported. Return -ENOTTY if it is not available. + * Set the modem status bits from the tty driver if the feature + * is supported. Return -%ENOTTY if it is not available. * - * Locking: none (up to the driver) + * Locking: none (up to the driver) */ - static int tty_tiocmset(struct tty_struct *tty, unsigned int cmd, unsigned __user *p) { @@ -2588,13 +2556,13 @@ static int tty_tiocmset(struct tty_struct *tty, unsigned int cmd, } /** - * tty_get_icount - get tty statistics - * @tty: tty device - * @icount: output parameter + * tty_get_icount - get tty statistics + * @tty: tty device + * @icount: output parameter * - * Gets a copy of the tty's icount statistics. + * Gets a copy of the @tty's icount statistics. * - * Locking: none (up to the driver) + * Locking: none (up to the driver) */ int tty_get_icount(struct tty_struct *tty, struct serial_icounter_struct *icount) @@ -3102,14 +3070,15 @@ static struct device *tty_get_device(struct tty_struct *tty) } -/* - * alloc_tty_struct +/** + * alloc_tty_struct - allocate a new tty + * @driver: driver which will handle the returned tty + * @idx: minor of the tty * - * This subroutine allocates and initializes a tty structure. + * This subroutine allocates and initializes a tty structure. * - * Locking: none - tty in question is not exposed at this point + * Locking: none - @tty in question is not exposed at this point */ - struct tty_struct *alloc_tty_struct(struct tty_driver *driver, int idx) { struct tty_struct *tty; @@ -3151,17 +3120,18 @@ struct tty_struct *alloc_tty_struct(struct tty_driver *driver, int idx) } /** - * tty_put_char - write one character to a tty - * @tty: tty - * @ch: character + * tty_put_char - write one character to a tty + * @tty: tty + * @ch: character to write + * + * Write one byte to the @tty using the provided @tty->ops->put_char() method + * if present. * - * Write one byte to the tty using the provided put_char method - * if present. Returns the number of characters successfully output. + * Note: the specific put_char operation in the driver layer may go + * away soon. Don't call it directly, use this method * - * Note: the specific put_char operation in the driver layer may go - * away soon. Don't call it directly, use this method + * Return: the number of characters successfully output. */ - int tty_put_char(struct tty_struct *tty, unsigned char ch) { if (tty->ops->put_char) @@ -3190,24 +3160,23 @@ static int tty_cdev_add(struct tty_driver *driver, dev_t dev, } /** - * tty_register_device - register a tty device - * @driver: the tty driver that describes the tty device - * @index: the index in the tty driver for this tty device - * @device: a struct device that is associated with this tty device. - * This field is optional, if there is no known struct device - * for this tty device it can be set to NULL safely. + * tty_register_device - register a tty device + * @driver: the tty driver that describes the tty device + * @index: the index in the tty driver for this tty device + * @device: a struct device that is associated with this tty device. + * This field is optional, if there is no known struct device + * for this tty device it can be set to NULL safely. * - * Returns a pointer to the struct device for this tty device - * (or ERR_PTR(-EFOO) on error). + * This call is required to be made to register an individual tty device + * if the tty driver's flags have the %TTY_DRIVER_DYNAMIC_DEV bit set. If + * that bit is not set, this function should not be called by a tty + * driver. * - * This call is required to be made to register an individual tty device - * if the tty driver's flags have the TTY_DRIVER_DYNAMIC_DEV bit set. If - * that bit is not set, this function should not be called by a tty - * driver. + * Locking: ?? * - * Locking: ?? + * Return: A pointer to the struct device for this tty device (or + * ERR_PTR(-EFOO) on error). */ - struct device *tty_register_device(struct tty_driver *driver, unsigned index, struct device *device) { @@ -3222,24 +3191,23 @@ static void tty_device_create_release(struct device *dev) } /** - * tty_register_device_attr - register a tty device - * @driver: the tty driver that describes the tty device - * @index: the index in the tty driver for this tty device - * @device: a struct device that is associated with this tty device. - * This field is optional, if there is no known struct device - * for this tty device it can be set to NULL safely. - * @drvdata: Driver data to be set to device. - * @attr_grp: Attribute group to be set on device. + * tty_register_device_attr - register a tty device + * @driver: the tty driver that describes the tty device + * @index: the index in the tty driver for this tty device + * @device: a struct device that is associated with this tty device. + * This field is optional, if there is no known struct device + * for this tty device it can be set to %NULL safely. + * @drvdata: Driver data to be set to device. + * @attr_grp: Attribute group to be set on device. * - * Returns a pointer to the struct device for this tty device - * (or ERR_PTR(-EFOO) on error). + * This call is required to be made to register an individual tty device if the + * tty driver's flags have the %TTY_DRIVER_DYNAMIC_DEV bit set. If that bit is + * not set, this function should not be called by a tty driver. * - * This call is required to be made to register an individual tty device - * if the tty driver's flags have the TTY_DRIVER_DYNAMIC_DEV bit set. If - * that bit is not set, this function should not be called by a tty - * driver. + * Locking: ?? * - * Locking: ?? + * Return: A pointer to the struct device for this tty device (or + * ERR_PTR(-EFOO) on error). */ struct device *tty_register_device_attr(struct tty_driver *driver, unsigned index, struct device *device, @@ -3312,16 +3280,15 @@ err_put: EXPORT_SYMBOL_GPL(tty_register_device_attr); /** - * tty_unregister_device - unregister a tty device - * @driver: the tty driver that describes the tty device - * @index: the index in the tty driver for this tty device + * tty_unregister_device - unregister a tty device + * @driver: the tty driver that describes the tty device + * @index: the index in the tty driver for this tty device * - * If a tty device is registered with a call to tty_register_device() then - * this function must be called when the tty device is gone. + * If a tty device is registered with a call to tty_register_device() then + * this function must be called when the tty device is gone. * - * Locking: ?? + * Locking: ?? */ - void tty_unregister_device(struct tty_driver *driver, unsigned index) { device_destroy(tty_class, @@ -3337,10 +3304,10 @@ EXPORT_SYMBOL(tty_unregister_device); * __tty_alloc_driver -- allocate tty driver * @lines: count of lines this driver can handle at most * @owner: module which is responsible for this driver - * @flags: some of TTY_DRIVER_* flags, will be set in driver->flags + * @flags: some of %TTY_DRIVER_ flags, will be set in driver->flags * * This should not be called directly, some of the provided macros should be - * used instead. Use IS_ERR and friends on @retval. + * used instead. Use IS_ERR() and friends on @retval. */ struct tty_driver *__tty_alloc_driver(unsigned int lines, struct module *owner, unsigned long flags) -- cgit From cbb68f91995001c79a9b89dcf6a25d22c7b92872 Mon Sep 17 00:00:00 2001 From: Jiri Slaby Date: Fri, 26 Nov 2021 09:16:01 +0100 Subject: tty: reformat kernel-doc in tty_ldisc.c Kernel-doc is a bit strict about some formatting. So fix these: 1) When there is a tab in comments, it thinks the line is a continuation one. So the description of the functions end up as descriptions of the last parameter described. Remove the tabs. 2) Remove newlines before parameters description and after the comments. This was not wrong per se, only inconsistent with the rest of the file. 3) Add periods to the end of sentences where appropriate. 4) Add "()" to function names and "%" to constants, so that they are properly highlighted. Signed-off-by: Jiri Slaby Link: https://lore.kernel.org/r/20211126081611.11001-14-jslaby@suse.cz Signed-off-by: Greg Kroah-Hartman --- drivers/tty/tty_ldisc.c | 292 ++++++++++++++++++++++-------------------------- 1 file changed, 132 insertions(+), 160 deletions(-) (limited to 'drivers/tty') diff --git a/drivers/tty/tty_ldisc.c b/drivers/tty/tty_ldisc.c index 3e4e0b20b4bb..776d8a62f77c 100644 --- a/drivers/tty/tty_ldisc.c +++ b/drivers/tty/tty_ldisc.c @@ -47,17 +47,14 @@ static DEFINE_RAW_SPINLOCK(tty_ldiscs_lock); static struct tty_ldisc_ops *tty_ldiscs[NR_LDISCS]; /** - * tty_register_ldisc - install a line discipline - * @new_ldisc: pointer to the ldisc object + * tty_register_ldisc - install a line discipline + * @new_ldisc: pointer to the ldisc object * - * Installs a new line discipline into the kernel. The discipline - * is set up as unreferenced and then made available to the kernel - * from this point onwards. + * Installs a new line discipline into the kernel. The discipline is set up as + * unreferenced and then made available to the kernel from this point onwards. * - * Locking: - * takes tty_ldiscs_lock to guard against ldisc races + * Locking: takes %tty_ldiscs_lock to guard against ldisc races */ - int tty_register_ldisc(struct tty_ldisc_ops *new_ldisc) { unsigned long flags; @@ -75,14 +72,13 @@ int tty_register_ldisc(struct tty_ldisc_ops *new_ldisc) EXPORT_SYMBOL(tty_register_ldisc); /** - * tty_unregister_ldisc - unload a line discipline - * @ldisc: ldisc number + * tty_unregister_ldisc - unload a line discipline + * @ldisc: ldisc number * - * Remove a line discipline from the kernel providing it is not - * currently in use. + * Remove a line discipline from the kernel providing it is not currently in + * use. * - * Locking: - * takes tty_ldiscs_lock to guard against ldisc races + * Locking: takes %tty_ldiscs_lock to guard against ldisc races */ void tty_unregister_ldisc(struct tty_ldisc_ops *ldisc) @@ -122,27 +118,25 @@ static void put_ldops(struct tty_ldisc_ops *ldops) } static int tty_ldisc_autoload = IS_BUILTIN(CONFIG_LDISC_AUTOLOAD); + /** - * tty_ldisc_get - take a reference to an ldisc - * @tty: tty device - * @disc: ldisc number - * - * Takes a reference to a line discipline. Deals with refcounts and - * module locking counts. - * - * Returns: -EINVAL if the discipline index is not [N_TTY..NR_LDISCS] or - * if the discipline is not registered - * -EAGAIN if request_module() failed to load or register the - * discipline - * -ENOMEM if allocation failure - * - * Otherwise, returns a pointer to the discipline and bumps the - * ref count - * - * Locking: - * takes tty_ldiscs_lock to guard against ldisc races + * tty_ldisc_get - take a reference to an ldisc + * @tty: tty device + * @disc: ldisc number + * + * Takes a reference to a line discipline. Deals with refcounts and module + * locking counts. If the discipline is not available, its module loaded, if + * possible. + * + * Returns: + * * -%EINVAL if the discipline index is not [%N_TTY .. %NR_LDISCS] or if the + * discipline is not registered + * * -%EAGAIN if request_module() failed to load or register the discipline + * * -%ENOMEM if allocation failure + * * Otherwise, returns a pointer to the discipline and bumps the ref count + * + * Locking: takes %tty_ldiscs_lock to guard against ldisc races */ - static struct tty_ldisc *tty_ldisc_get(struct tty_struct *tty, int disc) { struct tty_ldisc *ld; @@ -176,10 +170,11 @@ static struct tty_ldisc *tty_ldisc_get(struct tty_struct *tty, int disc) return ld; } -/* - * tty_ldisc_put - release the ldisc +/** + * tty_ldisc_put - release the ldisc + * @ld: lisdsc to release * - * Complement of tty_ldisc_get(). + * Complement of tty_ldisc_get(). */ static void tty_ldisc_put(struct tty_ldisc *ld) { @@ -226,25 +221,22 @@ const struct seq_operations tty_ldiscs_seq_ops = { }; /** - * tty_ldisc_ref_wait - wait for the tty ldisc - * @tty: tty device + * tty_ldisc_ref_wait - wait for the tty ldisc + * @tty: tty device * - * Dereference the line discipline for the terminal and take a - * reference to it. If the line discipline is in flux then - * wait patiently until it changes. + * Dereference the line discipline for the terminal and take a reference to it. + * If the line discipline is in flux then wait patiently until it changes. * - * Returns: NULL if the tty has been hungup and not re-opened with - * a new file descriptor, otherwise valid ldisc reference + * Returns: %NULL if the tty has been hungup and not re-opened with a new file + * descriptor, otherwise valid ldisc reference * - * Note 1: Must not be called from an IRQ/timer context. The caller - * must also be careful not to hold other locks that will deadlock - * against a discipline change, such as an existing ldisc reference - * (which we check for) + * Note 1: Must not be called from an IRQ/timer context. The caller must also + * be careful not to hold other locks that will deadlock against a discipline + * change, such as an existing ldisc reference (which we check for). * - * Note 2: a file_operations routine (read/poll/write) should use this - * function to wait for any ldisc lifetime events to finish. + * Note 2: a file_operations routine (read/poll/write) should use this function + * to wait for any ldisc lifetime events to finish. */ - struct tty_ldisc *tty_ldisc_ref_wait(struct tty_struct *tty) { struct tty_ldisc *ld; @@ -258,14 +250,13 @@ struct tty_ldisc *tty_ldisc_ref_wait(struct tty_struct *tty) EXPORT_SYMBOL_GPL(tty_ldisc_ref_wait); /** - * tty_ldisc_ref - get the tty ldisc - * @tty: tty device + * tty_ldisc_ref - get the tty ldisc + * @tty: tty device * - * Dereference the line discipline for the terminal and take a - * reference to it. If the line discipline is in flux then - * return NULL. Can be called from IRQ and timer functions. + * Dereference the line discipline for the terminal and take a reference to it. + * If the line discipline is in flux then return %NULL. Can be called from IRQ + * and timer functions. */ - struct tty_ldisc *tty_ldisc_ref(struct tty_struct *tty) { struct tty_ldisc *ld = NULL; @@ -280,13 +271,12 @@ struct tty_ldisc *tty_ldisc_ref(struct tty_struct *tty) EXPORT_SYMBOL_GPL(tty_ldisc_ref); /** - * tty_ldisc_deref - free a tty ldisc reference - * @ld: reference to free up + * tty_ldisc_deref - free a tty ldisc reference + * @ld: reference to free up * - * Undoes the effect of tty_ldisc_ref or tty_ldisc_ref_wait. May - * be called in IRQ context. + * Undoes the effect of tty_ldisc_ref() or tty_ldisc_ref_wait(). May be called + * in IRQ context. */ - void tty_ldisc_deref(struct tty_ldisc *ld) { ldsem_up_read(&ld->tty->ldisc_sem); @@ -386,13 +376,12 @@ static void tty_ldisc_unlock_pair(struct tty_struct *tty, } /** - * tty_ldisc_flush - flush line discipline queue - * @tty: tty + * tty_ldisc_flush - flush line discipline queue + * @tty: tty to flush ldisc for * - * Flush the line discipline queue (if any) and the tty flip buffers - * for this tty. + * Flush the line discipline queue (if any) and the tty flip buffers for this + * @tty. */ - void tty_ldisc_flush(struct tty_struct *tty) { struct tty_ldisc *ld = tty_ldisc_ref(tty); @@ -404,21 +393,18 @@ void tty_ldisc_flush(struct tty_struct *tty) EXPORT_SYMBOL_GPL(tty_ldisc_flush); /** - * tty_set_termios_ldisc - set ldisc field - * @tty: tty structure - * @disc: line discipline number + * tty_set_termios_ldisc - set ldisc field + * @tty: tty structure + * @disc: line discipline number * - * This is probably overkill for real world processors but - * they are not on hot paths so a little discipline won't do - * any harm. + * This is probably overkill for real world processors but they are not on hot + * paths so a little discipline won't do any harm. * - * The line discipline-related tty_struct fields are reset to - * prevent the ldisc driver from re-using stale information for - * the new ldisc instance. + * The line discipline-related tty_struct fields are reset to prevent the ldisc + * driver from re-using stale information for the new ldisc instance. * - * Locking: takes termios_rwsem + * Locking: takes termios_rwsem */ - static void tty_set_termios_ldisc(struct tty_struct *tty, int disc) { down_write(&tty->termios_rwsem); @@ -430,16 +416,14 @@ static void tty_set_termios_ldisc(struct tty_struct *tty, int disc) } /** - * tty_ldisc_open - open a line discipline - * @tty: tty we are opening the ldisc on - * @ld: discipline to open + * tty_ldisc_open - open a line discipline + * @tty: tty we are opening the ldisc on + * @ld: discipline to open * - * A helper opening method. Also a convenient debugging and check - * point. + * A helper opening method. Also a convenient debugging and check point. * - * Locking: always called with BTM already held. + * Locking: always called with BTM already held. */ - static int tty_ldisc_open(struct tty_struct *tty, struct tty_ldisc *ld) { WARN_ON(test_and_set_bit(TTY_LDISC_OPEN, &tty->flags)); @@ -457,14 +441,12 @@ static int tty_ldisc_open(struct tty_struct *tty, struct tty_ldisc *ld) } /** - * tty_ldisc_close - close a line discipline - * @tty: tty we are opening the ldisc on - * @ld: discipline to close + * tty_ldisc_close - close a line discipline + * @tty: tty we are opening the ldisc on + * @ld: discipline to close * - * A helper close method. Also a convenient debugging and check - * point. + * A helper close method. Also a convenient debugging and check point. */ - static void tty_ldisc_close(struct tty_struct *tty, struct tty_ldisc *ld) { lockdep_assert_held_write(&tty->ldisc_sem); @@ -476,14 +458,13 @@ static void tty_ldisc_close(struct tty_struct *tty, struct tty_ldisc *ld) } /** - * tty_ldisc_failto - helper for ldisc failback - * @tty: tty to open the ldisc on - * @ld: ldisc we are trying to fail back to + * tty_ldisc_failto - helper for ldisc failback + * @tty: tty to open the ldisc on + * @ld: ldisc we are trying to fail back to * - * Helper to try and recover a tty when switching back to the old - * ldisc fails and we need something attached. + * Helper to try and recover a tty when switching back to the old ldisc fails + * and we need something attached. */ - static int tty_ldisc_failto(struct tty_struct *tty, int ld) { struct tty_ldisc *disc = tty_ldisc_get(tty, ld); @@ -501,14 +482,13 @@ static int tty_ldisc_failto(struct tty_struct *tty, int ld) } /** - * tty_ldisc_restore - helper for tty ldisc change - * @tty: tty to recover - * @old: previous ldisc + * tty_ldisc_restore - helper for tty ldisc change + * @tty: tty to recover + * @old: previous ldisc * - * Restore the previous line discipline or N_TTY when a line discipline - * change fails due to an open error + * Restore the previous line discipline or %N_TTY when a line discipline change + * fails due to an open error */ - static void tty_ldisc_restore(struct tty_struct *tty, struct tty_ldisc *old) { /* There is an outstanding reference here so this is safe */ @@ -528,16 +508,15 @@ static void tty_ldisc_restore(struct tty_struct *tty, struct tty_ldisc *old) } /** - * tty_set_ldisc - set line discipline - * @tty: the terminal to set - * @disc: the line discipline number - * - * Set the discipline of a tty line. Must be called from a process - * context. The ldisc change logic has to protect itself against any - * overlapping ldisc change (including on the other end of pty pairs), - * the close of one side of a tty/pty pair, and eventually hangup. + * tty_set_ldisc - set line discipline + * @tty: the terminal to set + * @disc: the line discipline number + * + * Set the discipline of a tty line. Must be called from a process context. The + * ldisc change logic has to protect itself against any overlapping ldisc + * change (including on the other end of pty pairs), the close of one side of a + * tty/pty pair, and eventually hangup. */ - int tty_set_ldisc(struct tty_struct *tty, int disc) { int retval; @@ -613,10 +592,10 @@ err: EXPORT_SYMBOL_GPL(tty_set_ldisc); /** - * tty_ldisc_kill - teardown ldisc - * @tty: tty being released + * tty_ldisc_kill - teardown ldisc + * @tty: tty being released * - * Perform final close of the ldisc and reset tty->ldisc + * Perform final close of the ldisc and reset @tty->ldisc */ static void tty_ldisc_kill(struct tty_struct *tty) { @@ -633,12 +612,11 @@ static void tty_ldisc_kill(struct tty_struct *tty) } /** - * tty_reset_termios - reset terminal state - * @tty: tty to reset + * tty_reset_termios - reset terminal state + * @tty: tty to reset * - * Restore a terminal to the driver default state. + * Restore a terminal to the driver default state. */ - static void tty_reset_termios(struct tty_struct *tty) { down_write(&tty->termios_rwsem); @@ -650,19 +628,17 @@ static void tty_reset_termios(struct tty_struct *tty) /** - * tty_ldisc_reinit - reinitialise the tty ldisc - * @tty: tty to reinit - * @disc: line discipline to reinitialize + * tty_ldisc_reinit - reinitialise the tty ldisc + * @tty: tty to reinit + * @disc: line discipline to reinitialize * - * Completely reinitialize the line discipline state, by closing the - * current instance, if there is one, and opening a new instance. If - * an error occurs opening the new non-N_TTY instance, the instance - * is dropped and tty->ldisc reset to NULL. The caller can then retry - * with N_TTY instead. + * Completely reinitialize the line discipline state, by closing the current + * instance, if there is one, and opening a new instance. If an error occurs + * opening the new non-%N_TTY instance, the instance is dropped and @tty->ldisc + * reset to %NULL. The caller can then retry with %N_TTY instead. * - * Returns 0 if successful, otherwise error code < 0 + * Returns: 0 if successful, otherwise error code < 0 */ - int tty_ldisc_reinit(struct tty_struct *tty, int disc) { struct tty_ldisc *ld; @@ -692,21 +668,20 @@ int tty_ldisc_reinit(struct tty_struct *tty, int disc) } /** - * tty_ldisc_hangup - hangup ldisc reset - * @tty: tty being hung up - * @reinit: whether to re-initialise the tty + * tty_ldisc_hangup - hangup ldisc reset + * @tty: tty being hung up + * @reinit: whether to re-initialise the tty * - * Some tty devices reset their termios when they receive a hangup - * event. In that situation we must also switch back to N_TTY properly - * before we reset the termios data. + * Some tty devices reset their termios when they receive a hangup event. In + * that situation we must also switch back to %N_TTY properly before we reset + * the termios data. * - * Locking: We can take the ldisc mutex as the rest of the code is - * careful to allow for this. + * Locking: We can take the ldisc mutex as the rest of the code is careful to + * allow for this. * - * In the pty pair case this occurs in the close() path of the - * tty itself so we must be careful about locking rules. + * In the pty pair case this occurs in the close() path of the tty itself so we + * must be careful about locking rules. */ - void tty_ldisc_hangup(struct tty_struct *tty, bool reinit) { struct tty_ldisc *ld; @@ -752,15 +727,14 @@ void tty_ldisc_hangup(struct tty_struct *tty, bool reinit) } /** - * tty_ldisc_setup - open line discipline - * @tty: tty being shut down - * @o_tty: pair tty for pty/tty pairs + * tty_ldisc_setup - open line discipline + * @tty: tty being shut down + * @o_tty: pair tty for pty/tty pairs * - * Called during the initial open of a tty/pty pair in order to set up the - * line disciplines and bind them to the tty. This has no locking issues - * as the device isn't yet active. + * Called during the initial open of a tty/pty pair in order to set up the line + * disciplines and bind them to the @tty. This has no locking issues as the + * device isn't yet active. */ - int tty_ldisc_setup(struct tty_struct *tty, struct tty_struct *o_tty) { int retval = tty_ldisc_open(tty, tty->ldisc); @@ -783,13 +757,12 @@ int tty_ldisc_setup(struct tty_struct *tty, struct tty_struct *o_tty) } /** - * tty_ldisc_release - release line discipline - * @tty: tty being shut down (or one end of pty pair) + * tty_ldisc_release - release line discipline + * @tty: tty being shut down (or one end of pty pair) * - * Called during the final close of a tty or a pty pair in order to shut - * down the line discpline layer. On exit, each tty's ldisc is NULL. + * Called during the final close of a tty or a pty pair in order to shut down + * the line discpline layer. On exit, each tty's ldisc is %NULL. */ - void tty_ldisc_release(struct tty_struct *tty) { struct tty_struct *o_tty = tty->link; @@ -814,13 +787,12 @@ void tty_ldisc_release(struct tty_struct *tty) } /** - * tty_ldisc_init - ldisc setup for new tty - * @tty: tty being allocated + * tty_ldisc_init - ldisc setup for new tty + * @tty: tty being allocated * - * Set up the line discipline objects for a newly allocated tty. Note that - * the tty structure is not completely set up when this call is made. + * Set up the line discipline objects for a newly allocated tty. Note that the + * tty structure is not completely set up when this call is made. */ - int tty_ldisc_init(struct tty_struct *tty) { struct tty_ldisc *ld = tty_ldisc_get(tty, N_TTY); @@ -832,11 +804,11 @@ int tty_ldisc_init(struct tty_struct *tty) } /** - * tty_ldisc_deinit - ldisc cleanup for new tty - * @tty: tty that was allocated recently + * tty_ldisc_deinit - ldisc cleanup for new tty + * @tty: tty that was allocated recently * - * The tty structure must not becompletely set up (tty_ldisc_setup) when - * this call is made. + * The tty structure must not be completely set up (tty_ldisc_setup()) when + * this call is made. */ void tty_ldisc_deinit(struct tty_struct *tty) { -- cgit From bc17b7236b47f89681f48503660858532b918640 Mon Sep 17 00:00:00 2001 From: Jiri Slaby Date: Fri, 26 Nov 2021 09:16:02 +0100 Subject: tty: reformat kernel-doc in tty_buffer.c Kernel-doc is a bit strict about some formatting. So fix these: 1) When there is a tab in comments, it thinks the line is a continuation one. So the description of the functions end up as descriptions of the last parameter described. Remove the tabs. 2) Remove newlines before parameters description and after the comments. This was not wrong per se, only inconsistent with the rest of the file. 3) Add periods to the end of sentences where appropriate. 4) Add "()" to function names and "%" to constants, so that they are properly highlighted. Signed-off-by: Jiri Slaby Link: https://lore.kernel.org/r/20211126081611.11001-15-jslaby@suse.cz Signed-off-by: Greg Kroah-Hartman --- drivers/tty/tty_buffer.c | 251 +++++++++++++++++++++++------------------------ 1 file changed, 124 insertions(+), 127 deletions(-) (limited to 'drivers/tty') diff --git a/drivers/tty/tty_buffer.c b/drivers/tty/tty_buffer.c index 5b6875057ce2..646510476c30 100644 --- a/drivers/tty/tty_buffer.c +++ b/drivers/tty/tty_buffer.c @@ -39,20 +39,15 @@ #define TTY_BUFFER_PAGE (((PAGE_SIZE - sizeof(struct tty_buffer)) / 2) & ~0xFF) /** - * tty_buffer_lock_exclusive - gain exclusive access to buffer - * tty_buffer_unlock_exclusive - release exclusive access + * tty_buffer_lock_exclusive - gain exclusive access to buffer + * @port: tty port owning the flip buffer * - * @port: tty port owning the flip buffer + * Guarantees safe use of the &tty_ldisc_ops.receive_buf() method by excluding + * the buffer work and any pending flush from using the flip buffer. Data can + * continue to be added concurrently to the flip buffer from the driver side. * - * Guarantees safe use of the line discipline's receive_buf() method by - * excluding the buffer work and any pending flush from using the flip - * buffer. Data can continue to be added concurrently to the flip buffer - * from the driver side. - * - * On release, the buffer work is restarted if there is data in the - * flip buffer + * See also tty_buffer_unlock_exclusive(). */ - void tty_buffer_lock_exclusive(struct tty_port *port) { struct tty_bufhead *buf = &port->buf; @@ -62,6 +57,14 @@ void tty_buffer_lock_exclusive(struct tty_port *port) } EXPORT_SYMBOL_GPL(tty_buffer_lock_exclusive); +/** + * tty_buffer_unlock_exclusive - release exclusive access + * @port: tty port owning the flip buffer + * + * The buffer work is restarted if there is data in the flip buffer. + * + * See also tty_buffer_lock_exclusive(). + */ void tty_buffer_unlock_exclusive(struct tty_port *port) { struct tty_bufhead *buf = &port->buf; @@ -77,17 +80,16 @@ void tty_buffer_unlock_exclusive(struct tty_port *port) EXPORT_SYMBOL_GPL(tty_buffer_unlock_exclusive); /** - * tty_buffer_space_avail - return unused buffer space - * @port: tty port owning the flip buffer + * tty_buffer_space_avail - return unused buffer space + * @port: tty port owning the flip buffer * - * Returns the # of bytes which can be written by the driver without - * reaching the buffer limit. + * Returns: the # of bytes which can be written by the driver without reaching + * the buffer limit. * - * Note: this does not guarantee that memory is available to write - * the returned # of bytes (use tty_prepare_flip_string_xxx() to - * pre-allocate if memory guarantee is required). + * Note: this does not guarantee that memory is available to write the returned + * # of bytes (use tty_prepare_flip_string() to pre-allocate if memory + * guarantee is required). */ - unsigned int tty_buffer_space_avail(struct tty_port *port) { int space = port->buf.mem_limit - atomic_read(&port->buf.mem_used); @@ -107,13 +109,12 @@ static void tty_buffer_reset(struct tty_buffer *p, size_t size) } /** - * tty_buffer_free_all - free buffers used by a tty - * @port: tty port to free from + * tty_buffer_free_all - free buffers used by a tty + * @port: tty port to free from * - * Remove all the buffers pending on a tty whether queued with data - * or in the free ring. Must be called when the tty is no longer in use + * Remove all the buffers pending on a tty whether queued with data or in the + * free ring. Must be called when the tty is no longer in use. */ - void tty_buffer_free_all(struct tty_port *port) { struct tty_bufhead *buf = &port->buf; @@ -142,17 +143,17 @@ void tty_buffer_free_all(struct tty_port *port) } /** - * tty_buffer_alloc - allocate a tty buffer - * @port: tty port - * @size: desired size (characters) - * - * Allocate a new tty buffer to hold the desired number of characters. - * We round our buffers off in 256 character chunks to get better - * allocation behaviour. - * Return NULL if out of memory or the allocation would exceed the - * per device queue + * tty_buffer_alloc - allocate a tty buffer + * @port: tty port + * @size: desired size (characters) + * + * Allocate a new tty buffer to hold the desired number of characters. We + * round our buffers off in 256 character chunks to get better allocation + * behaviour. + * + * Returns: %NULL if out of memory or the allocation would exceed the per + * device queue. */ - static struct tty_buffer *tty_buffer_alloc(struct tty_port *port, size_t size) { struct llist_node *free; @@ -185,14 +186,13 @@ found: } /** - * tty_buffer_free - free a tty buffer - * @port: tty port owning the buffer - * @b: the buffer to free + * tty_buffer_free - free a tty buffer + * @port: tty port owning the buffer + * @b: the buffer to free * - * Free a tty buffer, or add it to the free list according to our - * internal strategy + * Free a tty buffer, or add it to the free list according to our internal + * strategy. */ - static void tty_buffer_free(struct tty_port *port, struct tty_buffer *b) { struct tty_bufhead *buf = &port->buf; @@ -207,17 +207,15 @@ static void tty_buffer_free(struct tty_port *port, struct tty_buffer *b) } /** - * tty_buffer_flush - flush full tty buffers - * @tty: tty to flush - * @ld: optional ldisc ptr (must be referenced) + * tty_buffer_flush - flush full tty buffers + * @tty: tty to flush + * @ld: optional ldisc ptr (must be referenced) * - * flush all the buffers containing receive data. If ld != NULL, - * flush the ldisc input buffer. + * Flush all the buffers containing receive data. If @ld != %NULL, flush the + * ldisc input buffer. * - * Locking: takes buffer lock to ensure single-threaded flip buffer - * 'consumer' + * Locking: takes buffer lock to ensure single-threaded flip buffer 'consumer'. */ - void tty_buffer_flush(struct tty_struct *tty, struct tty_ldisc *ld) { struct tty_port *port = tty->port; @@ -244,17 +242,18 @@ void tty_buffer_flush(struct tty_struct *tty, struct tty_ldisc *ld) } /** - * __tty_buffer_request_room - grow tty buffer if needed - * @port: tty port - * @size: size desired - * @flags: buffer flags if new buffer allocated (default = 0) + * __tty_buffer_request_room - grow tty buffer if needed + * @port: tty port + * @size: size desired + * @flags: buffer flags if new buffer allocated (default = 0) + * + * Make at least @size bytes of linear space available for the tty buffer. * - * Make at least size bytes of linear space available for the tty - * buffer. If we fail return the size we managed to find. + * Will change over to a new buffer if the current buffer is encoded as + * %TTY_NORMAL (so has no flags buffer) and the new buffer requires a flags + * buffer. * - * Will change over to a new buffer if the current buffer is encoded as - * TTY_NORMAL (so has no flags buffer) and the new buffer requires - * a flags buffer. + * Returns: the size we managed to find. */ static int __tty_buffer_request_room(struct tty_port *port, size_t size, int flags) @@ -300,16 +299,17 @@ int tty_buffer_request_room(struct tty_port *port, size_t size) EXPORT_SYMBOL_GPL(tty_buffer_request_room); /** - * tty_insert_flip_string_fixed_flag - Add characters to the tty buffer - * @port: tty port - * @chars: characters - * @flag: flag value for each character - * @size: size - * - * Queue a series of bytes to the tty buffering. All the characters - * passed are marked with the supplied flag. Returns the number added. + * tty_insert_flip_string_fixed_flag - add characters to the tty buffer + * @port: tty port + * @chars: characters + * @flag: flag value for each character + * @size: size + * + * Queue a series of bytes to the tty buffering. All the characters passed are + * marked with the supplied flag. + * + * Returns: the number added. */ - int tty_insert_flip_string_fixed_flag(struct tty_port *port, const unsigned char *chars, char flag, size_t size) { @@ -338,17 +338,17 @@ int tty_insert_flip_string_fixed_flag(struct tty_port *port, EXPORT_SYMBOL(tty_insert_flip_string_fixed_flag); /** - * tty_insert_flip_string_flags - Add characters to the tty buffer - * @port: tty port - * @chars: characters - * @flags: flag bytes - * @size: size - * - * Queue a series of bytes to the tty buffering. For each character - * the flags array indicates the status of the character. Returns the - * number added. + * tty_insert_flip_string_flags - add characters to the tty buffer + * @port: tty port + * @chars: characters + * @flags: flag bytes + * @size: size + * + * Queue a series of bytes to the tty buffering. For each character the flags + * array indicates the status of the character. + * + * Returns: the number added. */ - int tty_insert_flip_string_flags(struct tty_port *port, const unsigned char *chars, const char *flags, size_t size) { @@ -376,13 +376,13 @@ int tty_insert_flip_string_flags(struct tty_port *port, EXPORT_SYMBOL(tty_insert_flip_string_flags); /** - * __tty_insert_flip_char - Add one character to the tty buffer - * @port: tty port - * @ch: character - * @flag: flag byte + * __tty_insert_flip_char - add one character to the tty buffer + * @port: tty port + * @ch: character + * @flag: flag byte * - * Queue a single byte to the tty buffering, with an optional flag. - * This is the slow path of tty_insert_flip_char. + * Queue a single byte @ch to the tty buffering, with an optional flag. This is + * the slow path of tty_insert_flip_char(). */ int __tty_insert_flip_char(struct tty_port *port, unsigned char ch, char flag) { @@ -402,18 +402,19 @@ int __tty_insert_flip_char(struct tty_port *port, unsigned char ch, char flag) EXPORT_SYMBOL(__tty_insert_flip_char); /** - * tty_prepare_flip_string - make room for characters - * @port: tty port - * @chars: return pointer for character write area - * @size: desired size - * - * Prepare a block of space in the buffer for data. Returns the length - * available and buffer pointer to the space which is now allocated and - * accounted for as ready for normal characters. This is used for drivers - * that need their own block copy routines into the buffer. There is no - * guarantee the buffer is a DMA target! + * tty_prepare_flip_string - make room for characters + * @port: tty port + * @chars: return pointer for character write area + * @size: desired size + * + * Prepare a block of space in the buffer for data. + * + * This is used for drivers that need their own block copy routines into the + * buffer. There is no guarantee the buffer is a DMA target! + * + * Returns: the length available and buffer pointer (@chars) to the space which + * is now allocated and accounted for as ready for normal characters. */ - int tty_prepare_flip_string(struct tty_port *port, unsigned char **chars, size_t size) { @@ -432,16 +433,16 @@ int tty_prepare_flip_string(struct tty_port *port, unsigned char **chars, EXPORT_SYMBOL_GPL(tty_prepare_flip_string); /** - * tty_ldisc_receive_buf - forward data to line discipline - * @ld: line discipline to process input - * @p: char buffer - * @f: TTY_* flags buffer - * @count: number of bytes to process + * tty_ldisc_receive_buf - forward data to line discipline + * @ld: line discipline to process input + * @p: char buffer + * @f: %TTY_NORMAL, %TTY_BREAK, etc. flags buffer + * @count: number of bytes to process * - * Callers other than flush_to_ldisc() need to exclude the kworker - * from concurrent use of the line discipline, see paste_selection(). + * Callers other than flush_to_ldisc() need to exclude the kworker from + * concurrent use of the line discipline, see paste_selection(). * - * Returns the number of bytes processed + * Returns: the number of bytes processed. */ int tty_ldisc_receive_buf(struct tty_ldisc *ld, const unsigned char *p, const char *f, int count) @@ -474,18 +475,16 @@ receive_buf(struct tty_port *port, struct tty_buffer *head, int count) } /** - * flush_to_ldisc - * @work: tty structure passed from work queue. + * flush_to_ldisc - flush data from buffer to ldisc + * @work: tty structure passed from work queue. * - * This routine is called out of the software interrupt to flush data - * from the buffer chain to the line discipline. + * This routine is called out of the software interrupt to flush data from the + * buffer chain to the line discipline. * - * The receive_buf method is single threaded for each tty instance. + * The receive_buf() method is single threaded for each tty instance. * - * Locking: takes buffer lock to ensure single-threaded flip buffer - * 'consumer' + * Locking: takes buffer lock to ensure single-threaded flip buffer 'consumer'. */ - static void flush_to_ldisc(struct work_struct *work) { struct tty_port *port = container_of(work, struct tty_port, buf.work); @@ -533,16 +532,15 @@ static void flush_to_ldisc(struct work_struct *work) } /** - * tty_flip_buffer_push - terminal - * @port: tty port to push + * tty_flip_buffer_push - push terminal buffers + * @port: tty port to push * - * Queue a push of the terminal flip buffers to the line discipline. - * Can be called from IRQ/atomic context. + * Queue a push of the terminal flip buffers to the line discipline. Can be + * called from IRQ/atomic context. * - * In the event of the queue being busy for flipping the work will be - * held off and retried later. + * In the event of the queue being busy for flipping the work will be held off + * and retried later. */ - void tty_flip_buffer_push(struct tty_port *port) { struct tty_bufhead *buf = &port->buf; @@ -557,13 +555,12 @@ void tty_flip_buffer_push(struct tty_port *port) EXPORT_SYMBOL(tty_flip_buffer_push); /** - * tty_buffer_init - prepare a tty buffer structure - * @port: tty port to initialise + * tty_buffer_init - prepare a tty buffer structure + * @port: tty port to initialise * - * Set up the initial state of the buffer management for a tty device. - * Must be called before the other tty buffer functions are used. + * Set up the initial state of the buffer management for a tty device. Must be + * called before the other tty buffer functions are used. */ - void tty_buffer_init(struct tty_port *port) { struct tty_bufhead *buf = &port->buf; @@ -580,14 +577,14 @@ void tty_buffer_init(struct tty_port *port) } /** - * tty_buffer_set_limit - change the tty buffer memory limit - * @port: tty port to change - * @limit: memory limit to set + * tty_buffer_set_limit - change the tty buffer memory limit + * @port: tty port to change + * @limit: memory limit to set + * + * Change the tty buffer memory limit. * - * Change the tty buffer memory limit. - * Must be called before the other tty buffer functions are used. + * Must be called before the other tty buffer functions are used. */ - int tty_buffer_set_limit(struct tty_port *port, int limit) { if (limit < MIN_TTYB_SIZE) -- cgit From c66453ce8af8bac78a72ba4e21fd9a86720127d7 Mon Sep 17 00:00:00 2001 From: Jiri Slaby Date: Fri, 26 Nov 2021 09:16:03 +0100 Subject: tty: fix kernel-doc in n_tty.c * process_echoes doc was a misnomer * isig and n_tty_receive_char docs were misplaced * n_tty_read parameters were incorrect (from pre-cookie times) So fix all the warnings at once: 624: warning: expecting prototype for process_echoes(). Prototype was for __process_echoes() instead 1110: warning: expecting prototype for isig(). Prototype was for __isig() instead 1264: warning: expecting prototype for n_tty_receive_char(). Prototype was for n_tty_receive_char_special() instead 2067: warning: Excess function parameter 'buf' description in 'n_tty_read' 624: warning: expecting prototype for process_echoes(). Prototype was for __process_echoes() instead 1110: warning: expecting prototype for isig(). Prototype was for __isig() instead 1264: warning: expecting prototype for n_tty_receive_char(). Prototype was for n_tty_receive_char_special() instead 2067: warning: Function parameter or member 'kbuf' not described in 'n_tty_read' 2067: warning: Function parameter or member 'cookie' not described in 'n_tty_read' 2067: warning: Function parameter or member 'offset' not described in 'n_tty_read' 2067: warning: Excess function parameter 'buf' description in 'n_tty_read' Signed-off-by: Jiri Slaby Link: https://lore.kernel.org/r/20211126081611.11001-16-jslaby@suse.cz Signed-off-by: Greg Kroah-Hartman --- drivers/tty/n_tty.c | 53 +++++++++++++++++++++++++++-------------------------- 1 file changed, 27 insertions(+), 26 deletions(-) (limited to 'drivers/tty') diff --git a/drivers/tty/n_tty.c b/drivers/tty/n_tty.c index 5b0f50373fc6..feef156803c2 100644 --- a/drivers/tty/n_tty.c +++ b/drivers/tty/n_tty.c @@ -596,7 +596,7 @@ break_out: } /** - * process_echoes - write pending echo characters + * __process_echoes - write pending echo characters * @tty: terminal device * * Write previously buffered echo (and other ldisc-generated) @@ -619,7 +619,6 @@ break_out: * * Locking: callers must hold output_lock */ - static size_t __process_echoes(struct tty_struct *tty) { struct n_tty_data *ldata = tty->disc_data; @@ -1091,6 +1090,16 @@ static void eraser(unsigned char c, struct tty_struct *tty) finish_erasing(ldata); } + +static void __isig(int sig, struct tty_struct *tty) +{ + struct pid *tty_pgrp = tty_get_pgrp(tty); + if (tty_pgrp) { + kill_pgrp(tty_pgrp, sig, 1); + put_pid(tty_pgrp); + } +} + /** * isig - handle the ISIG optio * @sig: signal @@ -1105,16 +1114,6 @@ static void eraser(unsigned char c, struct tty_struct *tty) * * Locking: ctrl.lock */ - -static void __isig(int sig, struct tty_struct *tty) -{ - struct pid *tty_pgrp = tty_get_pgrp(tty); - if (tty_pgrp) { - kill_pgrp(tty_pgrp, sig, 1); - put_pid(tty_pgrp); - } -} - static void isig(int sig, struct tty_struct *tty) { struct n_tty_data *ldata = tty->disc_data; @@ -1247,19 +1246,6 @@ n_tty_receive_signal_char(struct tty_struct *tty, int signal, unsigned char c) process_echoes(tty); } -/** - * n_tty_receive_char - perform processing - * @tty: terminal device - * @c: character - * - * Process an individual character of input received from the driver. - * This is serialized with respect to itself by the rules for the - * driver above. - * - * n_tty_receive_buf()/producer path: - * caller holds non-exclusive termios_rwsem - * publishes canon_head if canonical mode is active - */ static void n_tty_receive_char_special(struct tty_struct *tty, unsigned char c) { struct n_tty_data *ldata = tty->disc_data; @@ -1394,6 +1380,19 @@ handle_newline: put_tty_queue(c, ldata); } +/** + * n_tty_receive_char - perform processing + * @tty: terminal device + * @c: character + * + * Process an individual character of input received from the driver. + * This is serialized with respect to itself by the rules for the + * driver above. + * + * n_tty_receive_buf()/producer path: + * caller holds non-exclusive termios_rwsem + * publishes canon_head if canonical mode is active + */ static void n_tty_receive_char(struct tty_struct *tty, unsigned char c) { struct n_tty_data *ldata = tty->disc_data; @@ -2046,8 +2045,10 @@ static int job_control(struct tty_struct *tty, struct file *file) * n_tty_read - read function for tty * @tty: tty device * @file: file object - * @buf: userspace buffer pointer + * @kbuf: kernelspace buffer pointer * @nr: size of I/O + * @cookie: if non-%NULL, this is a continuation read + * @offset: where to continue reading from (unused in n_tty) * * Perform reads for the line discipline. We are guaranteed that the * line discipline will not be closed under us but we may get multiple -- cgit From 98629663bff8c2831f9cfd2b4e67537b24a48daa Mon Sep 17 00:00:00 2001 From: Jiri Slaby Date: Fri, 26 Nov 2021 09:16:04 +0100 Subject: tty: reformat kernel-doc in n_tty.c Kernel-doc is a bit strict about some formatting. So fix these: 1) When there is a tab in comments, it thinks the line is a continuation one. So the description of the functions end up as descriptions of the last parameter described. Remove the tabs. 2) Remove newlines before parameters description and after the comments. This was not wrong per se, only inconsistent with the rest of the file. 3) Add periods to the end of sentences where appropriate. 4) Add "()" to function names and "%" to constants, so that they are properly highlighted. Signed-off-by: Jiri Slaby Link: https://lore.kernel.org/r/20211126081611.11001-17-jslaby@suse.cz Signed-off-by: Greg Kroah-Hartman --- drivers/tty/n_tty.c | 671 +++++++++++++++++++++++++--------------------------- 1 file changed, 316 insertions(+), 355 deletions(-) (limited to 'drivers/tty') diff --git a/drivers/tty/n_tty.c b/drivers/tty/n_tty.c index feef156803c2..a38fd65e39ab 100644 --- a/drivers/tty/n_tty.c +++ b/drivers/tty/n_tty.c @@ -186,17 +186,16 @@ static void tty_copy(struct tty_struct *tty, void *to, size_t tail, size_t n) } /** - * n_tty_kick_worker - start input worker (if required) - * @tty: terminal + * n_tty_kick_worker - start input worker (if required) + * @tty: terminal * - * Re-schedules the flip buffer work if it may have stopped + * Re-schedules the flip buffer work if it may have stopped. * - * Caller holds exclusive termios_rwsem - * or - * n_tty_read()/consumer path: - * holds non-exclusive termios_rwsem + * Locking: + * * Caller holds exclusive %termios_rwsem, or + * * n_tty_read()/consumer path: + * holds non-exclusive %termios_rwsem */ - static void n_tty_kick_worker(struct tty_struct *tty) { struct n_tty_data *ldata = tty->disc_data; @@ -230,14 +229,12 @@ static ssize_t chars_in_buffer(struct tty_struct *tty) } /** - * n_tty_write_wakeup - asynchronous I/O notifier - * @tty: tty device + * n_tty_write_wakeup - asynchronous I/O notifier + * @tty: tty device * - * Required for the ptys, serial driver etc. since processes - * that attach themselves to the master and rely on ASYNC - * IO must be woken up + * Required for the ptys, serial driver etc. since processes that attach + * themselves to the master and rely on ASYNC IO must be woken up. */ - static void n_tty_write_wakeup(struct tty_struct *tty) { clear_bit(TTY_DO_WRITE_WAKEUP, &tty->flags); @@ -300,16 +297,16 @@ static void n_tty_check_unthrottle(struct tty_struct *tty) } /** - * put_tty_queue - add character to tty - * @c: character - * @ldata: n_tty data + * put_tty_queue - add character to tty + * @c: character + * @ldata: n_tty data * - * Add a character to the tty read_buf queue. + * Add a character to the tty read_buf queue. * - * n_tty_receive_buf()/producer path: - * caller holds non-exclusive termios_rwsem + * Locking: + * * n_tty_receive_buf()/producer path: + * caller holds non-exclusive %termios_rwsem */ - static inline void put_tty_queue(unsigned char c, struct n_tty_data *ldata) { *read_buf_addr(ldata, ldata->read_head) = c; @@ -317,16 +314,16 @@ static inline void put_tty_queue(unsigned char c, struct n_tty_data *ldata) } /** - * reset_buffer_flags - reset buffer state - * @ldata: line disc data to reset + * reset_buffer_flags - reset buffer state + * @ldata: line disc data to reset * - * Reset the read buffer counters and clear the flags. - * Called from n_tty_open() and n_tty_flush_buffer(). + * Reset the read buffer counters and clear the flags. Called from + * n_tty_open() and n_tty_flush_buffer(). * - * Locking: caller holds exclusive termios_rwsem - * (or locking is not required) + * Locking: + * * caller holds exclusive %termios_rwsem, or + * * (locking is not required) */ - static void reset_buffer_flags(struct n_tty_data *ldata) { ldata->read_head = ldata->canon_head = ldata->read_tail = 0; @@ -351,19 +348,18 @@ static void n_tty_packet_mode_flush(struct tty_struct *tty) } /** - * n_tty_flush_buffer - clean input queue - * @tty: terminal device + * n_tty_flush_buffer - clean input queue + * @tty: terminal device * - * Flush the input buffer. Called when the tty layer wants the - * buffer flushed (eg at hangup) or when the N_TTY line discipline - * internally has to clean the pending queue (for example some signals). + * Flush the input buffer. Called when the tty layer wants the buffer flushed + * (eg at hangup) or when the %N_TTY line discipline internally has to clean + * the pending queue (for example some signals). * - * Holds termios_rwsem to exclude producer/consumer while - * buffer indices are reset. + * Holds %termios_rwsem to exclude producer/consumer while buffer indices are + * reset. * - * Locking: ctrl.lock, exclusive termios_rwsem + * Locking: %ctrl.lock, exclusive %termios_rwsem */ - static void n_tty_flush_buffer(struct tty_struct *tty) { down_write(&tty->termios_rwsem); @@ -376,55 +372,50 @@ static void n_tty_flush_buffer(struct tty_struct *tty) } /** - * is_utf8_continuation - utf8 multibyte check - * @c: byte to check + * is_utf8_continuation - utf8 multibyte check + * @c: byte to check * - * Returns true if the utf8 character 'c' is a multibyte continuation - * character. We use this to correctly compute the on screen size - * of the character when printing + * Returns: true if the utf8 character @c is a multibyte continuation + * character. We use this to correctly compute the on-screen size of the + * character when printing. */ - static inline int is_utf8_continuation(unsigned char c) { return (c & 0xc0) == 0x80; } /** - * is_continuation - multibyte check - * @c: byte to check - * @tty: terminal device + * is_continuation - multibyte check + * @c: byte to check + * @tty: terminal device * - * Returns true if the utf8 character 'c' is a multibyte continuation - * character and the terminal is in unicode mode. + * Returns: true if the utf8 character @c is a multibyte continuation character + * and the terminal is in unicode mode. */ - static inline int is_continuation(unsigned char c, struct tty_struct *tty) { return I_IUTF8(tty) && is_utf8_continuation(c); } /** - * do_output_char - output one character - * @c: character (or partial unicode symbol) - * @tty: terminal device - * @space: space available in tty driver write buffer + * do_output_char - output one character + * @c: character (or partial unicode symbol) + * @tty: terminal device + * @space: space available in tty driver write buffer * - * This is a helper function that handles one output character - * (including special characters like TAB, CR, LF, etc.), - * doing OPOST processing and putting the results in the - * tty driver's write buffer. + * This is a helper function that handles one output character (including + * special characters like TAB, CR, LF, etc.), doing OPOST processing and + * putting the results in the tty driver's write buffer. * - * Note that Linux currently ignores TABDLY, CRDLY, VTDLY, FFDLY - * and NLDLY. They simply aren't relevant in the world today. - * If you ever need them, add them here. + * Note that Linux currently ignores TABDLY, CRDLY, VTDLY, FFDLY and NLDLY. + * They simply aren't relevant in the world today. If you ever need them, add + * them here. * - * Returns the number of bytes of buffer space used or -1 if - * no space left. + * Returns: the number of bytes of buffer space used or -1 if no space left. * - * Locking: should be called under the output_lock to protect - * the column state and space left in the buffer + * Locking: should be called under the %output_lock to protect the column state + * and space left in the buffer. */ - static int do_output_char(unsigned char c, struct tty_struct *tty, int space) { struct n_tty_data *ldata = tty->disc_data; @@ -487,19 +478,18 @@ static int do_output_char(unsigned char c, struct tty_struct *tty, int space) } /** - * process_output - output post processor - * @c: character (or partial unicode symbol) - * @tty: terminal device + * process_output - output post processor + * @c: character (or partial unicode symbol) + * @tty: terminal device + * + * Output one character with OPOST processing. * - * Output one character with OPOST processing. - * Returns -1 when the output device is full and the character - * must be retried. + * Returns: -1 when the output device is full and the character must be + * retried. * - * Locking: output_lock to protect column state and space left - * (also, this is called from n_tty_write under the - * tty layer write lock) + * Locking: %output_lock to protect column state and space left (also, this is + *called from n_tty_write() under the tty layer write lock). */ - static int process_output(unsigned char c, struct tty_struct *tty) { struct n_tty_data *ldata = tty->disc_data; @@ -518,24 +508,23 @@ static int process_output(unsigned char c, struct tty_struct *tty) } /** - * process_output_block - block post processor - * @tty: terminal device - * @buf: character buffer - * @nr: number of bytes to output - * - * Output a block of characters with OPOST processing. - * Returns the number of characters output. - * - * This path is used to speed up block console writes, among other - * things when processing blocks of output data. It handles only - * the simple cases normally found and helps to generate blocks of - * symbols for the console driver and thus improve performance. - * - * Locking: output_lock to protect column state and space left - * (also, this is called from n_tty_write under the - * tty layer write lock) + * process_output_block - block post processor + * @tty: terminal device + * @buf: character buffer + * @nr: number of bytes to output + * + * Output a block of characters with OPOST processing. + * + * This path is used to speed up block console writes, among other things when + * processing blocks of output data. It handles only the simple cases normally + * found and helps to generate blocks of symbols for the console driver and + * thus improve performance. + * + * Returns: the number of characters output. + * + * Locking: %output_lock to protect column state and space left (also, this is + * called from n_tty_write() under the tty layer write lock). */ - static ssize_t process_output_block(struct tty_struct *tty, const unsigned char *buf, unsigned int nr) { @@ -596,28 +585,26 @@ break_out: } /** - * __process_echoes - write pending echo characters - * @tty: terminal device + * __process_echoes - write pending echo characters + * @tty: terminal device * - * Write previously buffered echo (and other ldisc-generated) - * characters to the tty. + * Write previously buffered echo (and other ldisc-generated) characters to the + * tty. * - * Characters generated by the ldisc (including echoes) need to - * be buffered because the driver's write buffer can fill during - * heavy program output. Echoing straight to the driver will - * often fail under these conditions, causing lost characters and - * resulting mismatches of ldisc state information. + * Characters generated by the ldisc (including echoes) need to be buffered + * because the driver's write buffer can fill during heavy program output. + * Echoing straight to the driver will often fail under these conditions, + * causing lost characters and resulting mismatches of ldisc state information. * - * Since the ldisc state must represent the characters actually sent - * to the driver at the time of the write, operations like certain - * changes in column state are also saved in the buffer and executed - * here. + * Since the ldisc state must represent the characters actually sent to the + * driver at the time of the write, operations like certain changes in column + * state are also saved in the buffer and executed here. * - * A circular fifo buffer is used so that the most recent characters - * are prioritized. Also, when control characters are echoed with a - * prefixed "^", the pair is treated atomically and thus not separated. + * A circular fifo buffer is used so that the most recent characters are + * prioritized. Also, when control characters are echoed with a prefixed "^", + * the pair is treated atomically and thus not separated. * - * Locking: callers must hold output_lock + * Locking: callers must hold %output_lock. */ static size_t __process_echoes(struct tty_struct *tty) { @@ -827,13 +814,12 @@ static void flush_echoes(struct tty_struct *tty) } /** - * add_echo_byte - add a byte to the echo buffer - * @c: unicode byte to echo - * @ldata: n_tty data + * add_echo_byte - add a byte to the echo buffer + * @c: unicode byte to echo + * @ldata: n_tty data * - * Add a character or operation byte to the echo buffer. + * Add a character or operation byte to the echo buffer. */ - static inline void add_echo_byte(unsigned char c, struct n_tty_data *ldata) { *echo_buf_addr(ldata, ldata->echo_head) = c; @@ -842,12 +828,11 @@ static inline void add_echo_byte(unsigned char c, struct n_tty_data *ldata) } /** - * echo_move_back_col - add operation to move back a column - * @ldata: n_tty data + * echo_move_back_col - add operation to move back a column + * @ldata: n_tty data * - * Add an operation to the echo buffer to move back one column. + * Add an operation to the echo buffer to move back one column. */ - static void echo_move_back_col(struct n_tty_data *ldata) { add_echo_byte(ECHO_OP_START, ldata); @@ -855,13 +840,12 @@ static void echo_move_back_col(struct n_tty_data *ldata) } /** - * echo_set_canon_col - add operation to set the canon column - * @ldata: n_tty data + * echo_set_canon_col - add operation to set the canon column + * @ldata: n_tty data * - * Add an operation to the echo buffer to set the canon column - * to the current column. + * Add an operation to the echo buffer to set the canon column to the current + * column. */ - static void echo_set_canon_col(struct n_tty_data *ldata) { add_echo_byte(ECHO_OP_START, ldata); @@ -869,20 +853,18 @@ static void echo_set_canon_col(struct n_tty_data *ldata) } /** - * echo_erase_tab - add operation to erase a tab - * @num_chars: number of character columns already used - * @after_tab: true if num_chars starts after a previous tab - * @ldata: n_tty data - * - * Add an operation to the echo buffer to erase a tab. - * - * Called by the eraser function, which knows how many character - * columns have been used since either a previous tab or the start - * of input. This information will be used later, along with - * canon column (if applicable), to go back the correct number - * of columns. + * echo_erase_tab - add operation to erase a tab + * @num_chars: number of character columns already used + * @after_tab: true if num_chars starts after a previous tab + * @ldata: n_tty data + * + * Add an operation to the echo buffer to erase a tab. + * + * Called by the eraser function, which knows how many character columns have + * been used since either a previous tab or the start of input. This + * information will be used later, along with canon column (if applicable), to + * go back the correct number of columns. */ - static void echo_erase_tab(unsigned int num_chars, int after_tab, struct n_tty_data *ldata) { @@ -900,16 +882,15 @@ static void echo_erase_tab(unsigned int num_chars, int after_tab, } /** - * echo_char_raw - echo a character raw - * @c: unicode byte to echo - * @ldata: line disc data + * echo_char_raw - echo a character raw + * @c: unicode byte to echo + * @ldata: line disc data * - * Echo user input back onto the screen. This must be called only when - * L_ECHO(tty) is true. Called from the driver receive_buf path. + * Echo user input back onto the screen. This must be called only when + * L_ECHO(tty) is true. Called from the &tty_driver.receive_buf() path. * - * This variant does not treat control characters specially. + * This variant does not treat control characters specially. */ - static void echo_char_raw(unsigned char c, struct n_tty_data *ldata) { if (c == ECHO_OP_START) { @@ -921,17 +902,16 @@ static void echo_char_raw(unsigned char c, struct n_tty_data *ldata) } /** - * echo_char - echo a character - * @c: unicode byte to echo - * @tty: terminal device + * echo_char - echo a character + * @c: unicode byte to echo + * @tty: terminal device * - * Echo user input back onto the screen. This must be called only when - * L_ECHO(tty) is true. Called from the driver receive_buf path. + * Echo user input back onto the screen. This must be called only when + * L_ECHO(tty) is true. Called from the &tty_driver.receive_buf() path. * - * This variant tags control characters to be echoed as "^X" - * (where X is the letter representing the control char). + * This variant tags control characters to be echoed as "^X" (where X is the + * letter representing the control char). */ - static void echo_char(unsigned char c, struct tty_struct *tty) { struct n_tty_data *ldata = tty->disc_data; @@ -947,10 +927,9 @@ static void echo_char(unsigned char c, struct tty_struct *tty) } /** - * finish_erasing - complete erase - * @ldata: n_tty data + * finish_erasing - complete erase + * @ldata: n_tty data */ - static inline void finish_erasing(struct n_tty_data *ldata) { if (ldata->erasing) { @@ -960,18 +939,17 @@ static inline void finish_erasing(struct n_tty_data *ldata) } /** - * eraser - handle erase function - * @c: character input - * @tty: terminal device + * eraser - handle erase function + * @c: character input + * @tty: terminal device * - * Perform erase and necessary output when an erase character is - * present in the stream from the driver layer. Handles the complexities - * of UTF-8 multibyte symbols. + * Perform erase and necessary output when an erase character is present in the + * stream from the driver layer. Handles the complexities of UTF-8 multibyte + * symbols. * - * n_tty_receive_buf()/producer path: - * caller holds non-exclusive termios_rwsem + * Locking: n_tty_receive_buf()/producer path: + * caller holds non-exclusive %termios_rwsem */ - static void eraser(unsigned char c, struct tty_struct *tty) { struct n_tty_data *ldata = tty->disc_data; @@ -1101,18 +1079,18 @@ static void __isig(int sig, struct tty_struct *tty) } /** - * isig - handle the ISIG optio - * @sig: signal - * @tty: terminal + * isig - handle the ISIG optio + * @sig: signal + * @tty: terminal * - * Called when a signal is being sent due to terminal input. - * Called from the driver receive_buf path so serialized. + * Called when a signal is being sent due to terminal input. Called from the + * &tty_driver.receive_buf() path, so serialized. * - * Performs input and output flush if !NOFLSH. In this context, the echo - * buffer is 'output'. The signal is processed first to alert any current - * readers or writers to discontinue and exit their i/o loops. + * Performs input and output flush if !NOFLSH. In this context, the echo + * buffer is 'output'. The signal is processed first to alert any current + * readers or writers to discontinue and exit their i/o loops. * - * Locking: ctrl.lock + * Locking: %ctrl.lock */ static void isig(int sig, struct tty_struct *tty) { @@ -1150,18 +1128,17 @@ static void isig(int sig, struct tty_struct *tty) } /** - * n_tty_receive_break - handle break - * @tty: terminal + * n_tty_receive_break - handle break + * @tty: terminal * - * An RS232 break event has been hit in the incoming bitstream. This - * can cause a variety of events depending upon the termios settings. + * An RS232 break event has been hit in the incoming bitstream. This can cause + * a variety of events depending upon the termios settings. * - * n_tty_receive_buf()/producer path: - * caller holds non-exclusive termios_rwsem + * Locking: n_tty_receive_buf()/producer path: + * caller holds non-exclusive termios_rwsem * - * Note: may get exclusive termios_rwsem if flushing input buffer + * Note: may get exclusive %termios_rwsem if flushing input buffer */ - static void n_tty_receive_break(struct tty_struct *tty) { struct n_tty_data *ldata = tty->disc_data; @@ -1180,18 +1157,15 @@ static void n_tty_receive_break(struct tty_struct *tty) } /** - * n_tty_receive_overrun - handle overrun reporting - * @tty: terminal + * n_tty_receive_overrun - handle overrun reporting + * @tty: terminal * - * Data arrived faster than we could process it. While the tty - * driver has flagged this the bits that were missed are gone - * forever. + * Data arrived faster than we could process it. While the tty driver has + * flagged this the bits that were missed are gone forever. * - * Called from the receive_buf path so single threaded. Does not - * need locking as num_overrun and overrun_time are function - * private. + * Called from the receive_buf path so single threaded. Does not need locking + * as num_overrun and overrun_time are function private. */ - static void n_tty_receive_overrun(struct tty_struct *tty) { struct n_tty_data *ldata = tty->disc_data; @@ -1206,15 +1180,15 @@ static void n_tty_receive_overrun(struct tty_struct *tty) } /** - * n_tty_receive_parity_error - error notifier - * @tty: terminal device - * @c: character + * n_tty_receive_parity_error - error notifier + * @tty: terminal device + * @c: character * - * Process a parity error and queue the right data to indicate - * the error case if necessary. + * Process a parity error and queue the right data to indicate the error case + * if necessary. * - * n_tty_receive_buf()/producer path: - * caller holds non-exclusive termios_rwsem + * Locking: n_tty_receive_buf()/producer path: + * caller holds non-exclusive %termios_rwsem */ static void n_tty_receive_parity_error(struct tty_struct *tty, unsigned char c) { @@ -1381,17 +1355,16 @@ handle_newline: } /** - * n_tty_receive_char - perform processing - * @tty: terminal device - * @c: character + * n_tty_receive_char - perform processing + * @tty: terminal device + * @c: character * - * Process an individual character of input received from the driver. - * This is serialized with respect to itself by the rules for the - * driver above. + * Process an individual character of input received from the driver. This is + * serialized with respect to itself by the rules for the driver above. * - * n_tty_receive_buf()/producer path: - * caller holds non-exclusive termios_rwsem - * publishes canon_head if canonical mode is active + * Locking: n_tty_receive_buf()/producer path: + * caller holds non-exclusive %termios_rwsem + * publishes canon_head if canonical mode is active */ static void n_tty_receive_char(struct tty_struct *tty, unsigned char c) { @@ -1593,38 +1566,37 @@ static void __receive_buf(struct tty_struct *tty, const unsigned char *cp, } /** - * n_tty_receive_buf_common - process input - * @tty: device to receive input - * @cp: input chars - * @fp: flags for each char (if NULL, all chars are TTY_NORMAL) - * @count: number of input chars in @cp - * @flow: enable flow control - * - * Called by the terminal driver when a block of characters has - * been received. This function must be called from soft contexts - * not from interrupt context. The driver is responsible for making - * calls one at a time and in order (or using flush_to_ldisc) - * - * Returns the # of input chars from @cp which were processed. - * - * In canonical mode, the maximum line length is 4096 chars (including - * the line termination char); lines longer than 4096 chars are - * truncated. After 4095 chars, input data is still processed but - * not stored. Overflow processing ensures the tty can always - * receive more input until at least one line can be read. - * - * In non-canonical mode, the read buffer will only accept 4095 chars; - * this provides the necessary space for a newline char if the input - * mode is switched to canonical. - * - * Note it is possible for the read buffer to _contain_ 4096 chars - * in non-canonical mode: the read buffer could already contain the - * maximum canon line of 4096 chars when the mode is switched to - * non-canonical. - * - * n_tty_receive_buf()/producer path: - * claims non-exclusive termios_rwsem - * publishes commit_head or canon_head + * n_tty_receive_buf_common - process input + * @tty: device to receive input + * @cp: input chars + * @fp: flags for each char (if %NULL, all chars are %TTY_NORMAL) + * @count: number of input chars in @cp + * @flow: enable flow control + * + * Called by the terminal driver when a block of characters has been received. + * This function must be called from soft contexts not from interrupt context. + * The driver is responsible for making calls one at a time and in order (or + * using flush_to_ldisc()). + * + * Returns: the # of input chars from @cp which were processed. + * + * In canonical mode, the maximum line length is 4096 chars (including the line + * termination char); lines longer than 4096 chars are truncated. After 4095 + * chars, input data is still processed but not stored. Overflow processing + * ensures the tty can always receive more input until at least one line can be + * read. + * + * In non-canonical mode, the read buffer will only accept 4095 chars; this + * provides the necessary space for a newline char if the input mode is + * switched to canonical. + * + * Note it is possible for the read buffer to _contain_ 4096 chars in + * non-canonical mode: the read buffer could already contain the maximum canon + * line of 4096 chars when the mode is switched to non-canonical. + * + * Locking: n_tty_receive_buf()/producer path: + * claims non-exclusive %termios_rwsem + * publishes commit_head or canon_head */ static int n_tty_receive_buf_common(struct tty_struct *tty, const unsigned char *cp, @@ -1709,19 +1681,17 @@ static int n_tty_receive_buf2(struct tty_struct *tty, const unsigned char *cp, } /** - * n_tty_set_termios - termios data changed - * @tty: terminal - * @old: previous data + * n_tty_set_termios - termios data changed + * @tty: terminal + * @old: previous data * - * Called by the tty layer when the user changes termios flags so - * that the line discipline can plan ahead. This function cannot sleep - * and is protected from re-entry by the tty layer. The user is - * guaranteed that this function will not be re-entered or in progress - * when the ldisc is closed. + * Called by the tty layer when the user changes termios flags so that the line + * discipline can plan ahead. This function cannot sleep and is protected from + * re-entry by the tty layer. The user is guaranteed that this function will + * not be re-entered or in progress when the ldisc is closed. * - * Locking: Caller holds tty->termios_rwsem + * Locking: Caller holds @tty->termios_rwsem */ - static void n_tty_set_termios(struct tty_struct *tty, struct ktermios *old) { struct n_tty_data *ldata = tty->disc_data; @@ -1807,15 +1777,13 @@ static void n_tty_set_termios(struct tty_struct *tty, struct ktermios *old) } /** - * n_tty_close - close the ldisc for this tty - * @tty: device + * n_tty_close - close the ldisc for this tty + * @tty: device * - * Called from the terminal layer when this line discipline is - * being shut down, either because of a close or becsuse of a - * discipline change. The function will not be called while other - * ldisc methods are in progress. + * Called from the terminal layer when this line discipline is being shut down, + * either because of a close or becsuse of a discipline change. The function + * will not be called while other ldisc methods are in progress. */ - static void n_tty_close(struct tty_struct *tty) { struct n_tty_data *ldata = tty->disc_data; @@ -1830,15 +1798,13 @@ static void n_tty_close(struct tty_struct *tty) } /** - * n_tty_open - open an ldisc - * @tty: terminal to open + * n_tty_open - open an ldisc + * @tty: terminal to open * - * Called when this line discipline is being attached to the - * terminal device. Can sleep. Called serialized so that no - * other events will occur in parallel. No further open will occur - * until a close. + * Called when this line discipline is being attached to the terminal device. + * Can sleep. Called serialized so that no other events will occur in parallel. + * No further open will occur until a close. */ - static int n_tty_open(struct tty_struct *tty) { struct n_tty_data *ldata; @@ -1873,24 +1839,23 @@ static inline int input_available_p(struct tty_struct *tty, int poll) } /** - * copy_from_read_buf - copy read data directly - * @tty: terminal device - * @kbp: data - * @nr: size of data - * - * Helper function to speed up n_tty_read. It is only called when - * ICANON is off; it copies characters straight from the tty queue. + * copy_from_read_buf - copy read data directly + * @tty: terminal device + * @kbp: data + * @nr: size of data * - * Called under the ldata->atomic_read_lock sem + * Helper function to speed up n_tty_read(). It is only called when %ICANON is + * off; it copies characters straight from the tty queue. * - * Returns true if it successfully copied data, but there is still - * more data to be had. + * Returns: true if it successfully copied data, but there is still more data + * to be had. * - * n_tty_read()/consumer path: - * caller holds non-exclusive termios_rwsem + * Locking: + * * called under the @ldata->atomic_read_lock sem + * * n_tty_read()/consumer path: + * caller holds non-exclusive %termios_rwsem; * read_tail published */ - static bool copy_from_read_buf(struct tty_struct *tty, unsigned char **kbp, size_t *nr) @@ -1925,28 +1890,27 @@ static bool copy_from_read_buf(struct tty_struct *tty, } /** - * canon_copy_from_read_buf - copy read data in canonical mode - * @tty: terminal device - * @kbp: data - * @nr: size of data - * - * Helper function for n_tty_read. It is only called when ICANON is on; - * it copies one line of input up to and including the line-delimiting - * character into the result buffer. - * - * NB: When termios is changed from non-canonical to canonical mode and - * the read buffer contains data, n_tty_set_termios() simulates an EOF - * push (as if C-d were input) _without_ the DISABLED_CHAR in the buffer. - * This causes data already processed as input to be immediately available - * as input although a newline has not been received. - * - * Called under the atomic_read_lock mutex - * - * n_tty_read()/consumer path: - * caller holds non-exclusive termios_rwsem - * read_tail published + * canon_copy_from_read_buf - copy read data in canonical mode + * @tty: terminal device + * @kbp: data + * @nr: size of data + * + * Helper function for n_tty_read(). It is only called when %ICANON is on; it + * copies one line of input up to and including the line-delimiting character + * into the result buffer. + * + * Note: When termios is changed from non-canonical to canonical mode and the + * read buffer contains data, n_tty_set_termios() simulates an EOF push (as if + * C-d were input) _without_ the %DISABLED_CHAR in the buffer. This causes data + * already processed as input to be immediately available as input although a + * newline has not been received. + * + * Locking: + * * called under the %atomic_read_lock mutex + * * n_tty_read()/consumer path: + * caller holds non-exclusive %termios_rwsem; + * read_tail published */ - static bool canon_copy_from_read_buf(struct tty_struct *tty, unsigned char **kbp, size_t *nr) @@ -2014,19 +1978,19 @@ static bool canon_copy_from_read_buf(struct tty_struct *tty, } /** - * job_control - check job control - * @tty: tty - * @file: file handle - * - * Perform job control management checks on this file/tty descriptor - * and if appropriate send any needed signals and return a negative - * error code if action should be taken. - * - * Locking: redirected write test is safe - * current->signal->tty check is safe - * ctrl.lock to safely reference tty->ctrl.pgrp + * job_control - check job control + * @tty: tty + * @file: file handle + * + * Perform job control management checks on this @file/@tty descriptor and if + * appropriate send any needed signals and return a negative error code if + * action should be taken. + * + * Locking: + * * redirected write test is safe + * * current->signal->tty check is safe + * * ctrl.lock to safely reference @tty->ctrl.pgrp */ - static int job_control(struct tty_struct *tty, struct file *file) { /* Job control check -- must be done at start and after @@ -2042,26 +2006,25 @@ static int job_control(struct tty_struct *tty, struct file *file) /** - * n_tty_read - read function for tty - * @tty: tty device - * @file: file object - * @kbuf: kernelspace buffer pointer - * @nr: size of I/O - * @cookie: if non-%NULL, this is a continuation read - * @offset: where to continue reading from (unused in n_tty) - * - * Perform reads for the line discipline. We are guaranteed that the - * line discipline will not be closed under us but we may get multiple - * parallel readers and must handle this ourselves. We may also get - * a hangup. Always called in user context, may sleep. - * - * This code must be sure never to sleep through a hangup. - * - * n_tty_read()/consumer path: - * claims non-exclusive termios_rwsem - * publishes read_tail + * n_tty_read - read function for tty + * @tty: tty device + * @file: file object + * @kbuf: kernelspace buffer pointer + * @nr: size of I/O + * @cookie: if non-%NULL, this is a continuation read + * @offset: where to continue reading from (unused in n_tty) + * + * Perform reads for the line discipline. We are guaranteed that the line + * discipline will not be closed under us but we may get multiple parallel + * readers and must handle this ourselves. We may also get a hangup. Always + * called in user context, may sleep. + * + * This code must be sure never to sleep through a hangup. + * + * Locking: n_tty_read()/consumer path: + * claims non-exclusive termios_rwsem; + * publishes read_tail */ - static ssize_t n_tty_read(struct tty_struct *tty, struct file *file, unsigned char *kbuf, size_t nr, void **cookie, unsigned long offset) @@ -2233,25 +2196,23 @@ more_to_be_read: } /** - * n_tty_write - write function for tty - * @tty: tty device - * @file: file object - * @buf: userspace buffer pointer - * @nr: size of I/O - * - * Write function of the terminal device. This is serialized with - * respect to other write callers but not to termios changes, reads - * and other such events. Since the receive code will echo characters, - * thus calling driver write methods, the output_lock is used in - * the output processing functions called here as well as in the - * echo processing function to protect the column state and space - * left in the buffer. - * - * This code must be sure never to sleep through a hangup. - * - * Locking: output_lock to protect column state and space left - * (note that the process_output*() functions take this - * lock themselves) + * n_tty_write - write function for tty + * @tty: tty device + * @file: file object + * @buf: userspace buffer pointer + * @nr: size of I/O + * + * Write function of the terminal device. This is serialized with respect to + * other write callers but not to termios changes, reads and other such events. + * Since the receive code will echo characters, thus calling driver write + * methods, the %output_lock is used in the output processing functions called + * here as well as in the echo processing function to protect the column state + * and space left in the buffer. + * + * This code must be sure never to sleep through a hangup. + * + * Locking: output_lock to protect column state and space left + * (note that the process_output*() functions take this lock themselves) */ static ssize_t n_tty_write(struct tty_struct *tty, struct file *file, @@ -2342,19 +2303,19 @@ break_out: } /** - * n_tty_poll - poll method for N_TTY - * @tty: terminal device - * @file: file accessing it - * @wait: poll table + * n_tty_poll - poll method for N_TTY + * @tty: terminal device + * @file: file accessing it + * @wait: poll table * - * Called when the line discipline is asked to poll() for data or - * for special events. This code is not serialized with respect to - * other events save open/close. + * Called when the line discipline is asked to poll() for data or for special + * events. This code is not serialized with respect to other events save + * open/close. * - * This code must be sure never to sleep through a hangup. - * Called without the kernel lock held - fine + * This code must be sure never to sleep through a hangup. + * + * Locking: called without the kernel lock held -- fine. */ - static __poll_t n_tty_poll(struct tty_struct *tty, struct file *file, poll_table *wait) { -- cgit From 385812835431c9055362f453da6d59e7dfcde430 Mon Sep 17 00:00:00 2001 From: Jiri Slaby Date: Fri, 26 Nov 2021 09:16:05 +0100 Subject: tty: add kernel-doc for more tty_driver functions The only documented function for tty_driver structure allocation/registration was __tty_alloc_driver(). Fix highlighting in that comment. And add kernel-doc headers to all tty_driver_kref_put(), tty_register_driver(), and tty_unregister_driver() -- i.e. the main ones. More to follow later. Signed-off-by: Jiri Slaby Link: https://lore.kernel.org/r/20211126081611.11001-18-jslaby@suse.cz Signed-off-by: Greg Kroah-Hartman --- drivers/tty/tty_io.c | 16 ++++++++++++++-- 1 file changed, 14 insertions(+), 2 deletions(-) (limited to 'drivers/tty') diff --git a/drivers/tty/tty_io.c b/drivers/tty/tty_io.c index b23269eb0cba..26b325e44c53 100644 --- a/drivers/tty/tty_io.c +++ b/drivers/tty/tty_io.c @@ -3394,13 +3394,22 @@ static void destruct_tty_driver(struct kref *kref) kfree(driver); } +/** + * tty_driver_kref_put -- drop a reference to a tty driver + * @driver: driver of which to drop the reference + * + * The final put will destroy and free up the driver. + */ void tty_driver_kref_put(struct tty_driver *driver) { kref_put(&driver->kref, destruct_tty_driver); } EXPORT_SYMBOL(tty_driver_kref_put); -/* +/** + * tty_register_driver -- register a tty driver + * @driver: driver to register + * * Called by a tty driver to register itself. */ int tty_register_driver(struct tty_driver *driver) @@ -3462,7 +3471,10 @@ err: } EXPORT_SYMBOL(tty_register_driver); -/* +/** + * tty_unregister_driver -- unregister a tty driver + * @driver: driver to unregister + * * Called by a tty driver to unregister itself. */ void tty_unregister_driver(struct tty_driver *driver) -- cgit From 3be491d74a95b15cd1a725bcb10208dca346ec7a Mon Sep 17 00:00:00 2001 From: Jiri Slaby Date: Fri, 26 Nov 2021 09:16:06 +0100 Subject: tty: add kernel-doc for more tty_port functions From the main tty_port functions, only tty_port_destroy() was documented. Document more of them, so that we can reference them in Documentation/ later in this series. Signed-off-by: Jiri Slaby Link: https://lore.kernel.org/r/20211126081611.11001-19-jslaby@suse.cz Signed-off-by: Greg Kroah-Hartman --- drivers/tty/tty_port.c | 54 ++++++++++++++++++++++++++++++++++++++++++++++++-- 1 file changed, 52 insertions(+), 2 deletions(-) (limited to 'drivers/tty') diff --git a/drivers/tty/tty_port.c b/drivers/tty/tty_port.c index ebb441ee92d5..7709ce655f44 100644 --- a/drivers/tty/tty_port.c +++ b/drivers/tty/tty_port.c @@ -59,6 +59,15 @@ const struct tty_port_client_operations tty_port_default_client_ops = { }; EXPORT_SYMBOL_GPL(tty_port_default_client_ops); +/** + * tty_port_init -- initialize tty_port + * @port: tty_port to initialize + * + * Initializes the state of struct tty_port. When a port was initialized using + * this function, one has to destroy the port by tty_port_destroy(). Either + * indirectly by using &tty_port refcounting (tty_port_put()) or directly if + * refcounting is not used. + */ void tty_port_init(struct tty_port *port) { memset(port, 0, sizeof(*port)); @@ -267,6 +276,13 @@ static void tty_port_destructor(struct kref *kref) kfree(port); } +/** + * tty_port_put -- drop a reference to tty_port + * @port: port to drop a reference of (can be NULL) + * + * The final put will destroy and free up the @port using + * @port->ops->destruct() hook, or using kfree() if not provided. + */ void tty_port_put(struct tty_port *port) { if (port) @@ -312,6 +328,16 @@ void tty_port_tty_set(struct tty_port *port, struct tty_struct *tty) } EXPORT_SYMBOL(tty_port_tty_set); +/** + * tty_port_shutdown - internal helper to shutdown the device + * @port: tty port to be shut down + * @tty: the associated tty + * + * It is used by tty_port_hangup() and tty_port_close(). Its task is to + * shutdown the device if it was initialized (note consoles remain + * functioning). It lowers DTR/RTS (if @tty has HUPCL set) and invokes + * @port->ops->shutdown(). + */ static void tty_port_shutdown(struct tty_port *port, struct tty_struct *tty) { mutex_lock(&port->mutex); @@ -559,7 +585,21 @@ static void tty_port_drain_delay(struct tty_port *port, struct tty_struct *tty) schedule_timeout_interruptible(timeout); } -/* Caller holds tty lock. */ +/** + * tty_port_close_start - helper for tty->ops->close, part 1/2 + * @port: tty_port of the device + * @tty: tty being closed + * @filp: passed file pointer + * + * Decrements and checks open count. Flushes the port if this is the last + * close. That means, dropping the data from the outpu buffer on the device and + * waiting for sending logic to finish. The rest of close handling is performed + * in tty_port_close_end(). + * + * Locking: Caller holds tty lock. + * + * Return: 1 if this is the last close, otherwise 0 + */ int tty_port_close_start(struct tty_port *port, struct tty_struct *tty, struct file *filp) { @@ -605,7 +645,17 @@ int tty_port_close_start(struct tty_port *port, } EXPORT_SYMBOL(tty_port_close_start); -/* Caller holds tty lock */ +/** + * tty_port_close_end - helper for tty->ops->close, part 2/2 + * @port: tty_port of the device + * @tty: tty being closed + * + * This is a continuation of the first part: tty_port_close_start(). This + * should be called after turning off the device. It flushes the data from the + * line discipline and delays the close by @port->close_delay. + * + * Locking: Caller holds tty lock. + */ void tty_port_close_end(struct tty_port *port, struct tty_struct *tty) { unsigned long flags; -- cgit From 31bc35d3346f24315c48ef8c92282c6c4f1bdd12 Mon Sep 17 00:00:00 2001 From: Jiri Slaby Date: Fri, 26 Nov 2021 09:16:10 +0100 Subject: tty: add kernel-doc for tty_standard_install It is the only missing exported function which is not documented. Fix it. Signed-off-by: Jiri Slaby Link: https://lore.kernel.org/r/20211126081611.11001-23-jslaby@suse.cz Signed-off-by: Greg Kroah-Hartman --- drivers/tty/tty_io.c | 8 ++++++++ 1 file changed, 8 insertions(+) (limited to 'drivers/tty') diff --git a/drivers/tty/tty_io.c b/drivers/tty/tty_io.c index 26b325e44c53..a4cfd254fda2 100644 --- a/drivers/tty/tty_io.c +++ b/drivers/tty/tty_io.c @@ -1275,6 +1275,14 @@ void tty_init_termios(struct tty_struct *tty) } EXPORT_SYMBOL_GPL(tty_init_termios); +/** + * tty_standard_install - usual tty->ops->install + * @driver: the driver for the tty + * @tty: the tty + * + * If the @driver overrides @tty->ops->install, it still can call this function + * to perform the standard install operations. + */ int tty_standard_install(struct tty_driver *driver, struct tty_struct *tty) { tty_init_termios(tty); -- cgit From ffccc78a5862100e1859f74fa8eea0b85b7591f1 Mon Sep 17 00:00:00 2001 From: Sherry Sun Date: Fri, 3 Dec 2021 11:04:41 +0800 Subject: tty: serial: fsl_lpuart: add timeout for wait_event_interruptible in .shutdown() Use wait_event_interruptible in lpuart_dma_shutdown isn't a reasonable behavior, since it may cause the system hang here if the condition !sport->dma_tx_in_progress never to be true in some corner case, such as when enable the flow control, the dma tx request may never be completed due to the peer's CTS setting when run .shutdown(). So here change to use wait_event_interruptible_timeout instead of wait_event_interruptible, the tx dma will be forcibly terminated if the tx dma request cannot be completed within 300ms. Considering the worst tx dma case is to have a 4K bytes tx buffer, which would require about 300ms to complete when the baudrate is 115200. Signed-off-by: Sherry Sun Link: https://lore.kernel.org/r/20211203030441.22873-1-sherry.sun@nxp.com Signed-off-by: Greg Kroah-Hartman --- drivers/tty/serial/fsl_lpuart.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'drivers/tty') diff --git a/drivers/tty/serial/fsl_lpuart.c b/drivers/tty/serial/fsl_lpuart.c index b1e7190ae483..eaa6161e505a 100644 --- a/drivers/tty/serial/fsl_lpuart.c +++ b/drivers/tty/serial/fsl_lpuart.c @@ -1793,8 +1793,8 @@ static void lpuart_dma_shutdown(struct lpuart_port *sport) } if (sport->lpuart_dma_tx_use) { - if (wait_event_interruptible(sport->dma_wait, - !sport->dma_tx_in_progress) != false) { + if (wait_event_interruptible_timeout(sport->dma_wait, + !sport->dma_tx_in_progress, msecs_to_jiffies(300)) <= 0) { sport->dma_tx_in_progress = false; dmaengine_terminate_all(sport->dma_tx_chan); } -- cgit From 3672fb65155530b5eea6225685c75329b6debec3 Mon Sep 17 00:00:00 2001 From: Lizhi Hou Date: Mon, 29 Nov 2021 12:23:02 -0800 Subject: tty: serial: uartlite: allow 64 bit address The base address of uartlite registers could be 64 bit address which is from device resource. When ulite_probe() calls ulite_assign(), this 64 bit address is casted to 32-bit. The fix is to replace "u32" type with "phys_addr_t" type for the base address in ulite_assign() argument list. Fixes: 8fa7b6100693 ("[POWERPC] Uartlite: Separate the bus binding from the driver proper") Signed-off-by: Lizhi Hou Link: https://lore.kernel.org/r/20211129202302.1319033-1-lizhi.hou@xilinx.com Signed-off-by: Greg Kroah-Hartman --- drivers/tty/serial/uartlite.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers/tty') diff --git a/drivers/tty/serial/uartlite.c b/drivers/tty/serial/uartlite.c index d3d9566e5dbd..e1fa52d31474 100644 --- a/drivers/tty/serial/uartlite.c +++ b/drivers/tty/serial/uartlite.c @@ -626,7 +626,7 @@ static struct uart_driver ulite_uart_driver = { * * Returns: 0 on success, <0 otherwise */ -static int ulite_assign(struct device *dev, int id, u32 base, int irq, +static int ulite_assign(struct device *dev, int id, phys_addr_t base, int irq, struct uartlite_data *pdata) { struct uart_port *port; -- cgit From d1180405c7b5c7a1c6bde79d5fc24fe931430737 Mon Sep 17 00:00:00 2001 From: Lino Sanfilippo Date: Mon, 29 Nov 2021 18:42:38 +0100 Subject: serial: amba-pl011: do not request memory region twice MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit With commit 3873e2d7f63a ("drivers: PL011: refactor pl011_probe()") the function devm_ioremap() called from pl011_setup_port() was replaced with devm_ioremap_resource(). Since this function not only remaps but also requests the ports io memory region it now collides with the .config_port() callback which requests the same region at uart port registration. Since devm_ioremap_resource() already claims the memory successfully, the request in .config_port() fails. Later at uart port deregistration the attempt to release the unclaimed memory also fails. The failure results in a “Trying to free nonexistent resource" warning. Fix these issues by removing the callbacks that implement the redundant memory allocation/release. Also make sure that changing the drivers io memory base address via TIOCSSERIAL is not allowed any more. Fixes: 3873e2d7f63a ("drivers: PL011: refactor pl011_probe()") Signed-off-by: Lino Sanfilippo Link: https://lore.kernel.org/r/20211129174238.8333-1-LinoSanfilippo@gmx.de Signed-off-by: Greg Kroah-Hartman --- drivers/tty/serial/amba-pl011.c | 27 +++------------------------ 1 file changed, 3 insertions(+), 24 deletions(-) (limited to 'drivers/tty') diff --git a/drivers/tty/serial/amba-pl011.c b/drivers/tty/serial/amba-pl011.c index c9534e229166..e2927a600910 100644 --- a/drivers/tty/serial/amba-pl011.c +++ b/drivers/tty/serial/amba-pl011.c @@ -2151,32 +2151,13 @@ static const char *pl011_type(struct uart_port *port) return uap->port.type == PORT_AMBA ? uap->type : NULL; } -/* - * Release the memory region(s) being used by 'port' - */ -static void pl011_release_port(struct uart_port *port) -{ - release_mem_region(port->mapbase, SZ_4K); -} - -/* - * Request the memory region(s) being used by 'port' - */ -static int pl011_request_port(struct uart_port *port) -{ - return request_mem_region(port->mapbase, SZ_4K, "uart-pl011") - != NULL ? 0 : -EBUSY; -} - /* * Configure/autoconfigure the port. */ static void pl011_config_port(struct uart_port *port, int flags) { - if (flags & UART_CONFIG_TYPE) { + if (flags & UART_CONFIG_TYPE) port->type = PORT_AMBA; - pl011_request_port(port); - } } /* @@ -2191,6 +2172,8 @@ static int pl011_verify_port(struct uart_port *port, struct serial_struct *ser) ret = -EINVAL; if (ser->baud_base < 9600) ret = -EINVAL; + if (port->mapbase != (unsigned long) ser->iomem_base) + ret = -EINVAL; return ret; } @@ -2243,8 +2226,6 @@ static const struct uart_ops amba_pl011_pops = { .flush_buffer = pl011_dma_flush_buffer, .set_termios = pl011_set_termios, .type = pl011_type, - .release_port = pl011_release_port, - .request_port = pl011_request_port, .config_port = pl011_config_port, .verify_port = pl011_verify_port, #ifdef CONFIG_CONSOLE_POLL @@ -2274,8 +2255,6 @@ static const struct uart_ops sbsa_uart_pops = { .shutdown = sbsa_uart_shutdown, .set_termios = sbsa_uart_set_termios, .type = pl011_type, - .release_port = pl011_release_port, - .request_port = pl011_request_port, .config_port = pl011_config_port, .verify_port = pl011_verify_port, #ifdef CONFIG_CONSOLE_POLL -- cgit From 13a5fad39a7b781c21d9528bcf52a5f5babafe99 Mon Sep 17 00:00:00 2001 From: Cai Huoqing Date: Thu, 2 Dec 2021 22:07:37 +0800 Subject: tty: mips_ejtag_fdc: Make use of the helper function kthread_run_on_cpu() Replace kthread_create/kthread_bind/wake_up_process() with kthread_run_on_cpu() to simplify the code. Signed-off-by: Cai Huoqing Link: https://lore.kernel.org/r/20211202140737.94832-1-cai.huoqing@linux.dev Signed-off-by: Greg Kroah-Hartman --- drivers/tty/mips_ejtag_fdc.c | 22 ++++++++++------------ 1 file changed, 10 insertions(+), 12 deletions(-) (limited to 'drivers/tty') diff --git a/drivers/tty/mips_ejtag_fdc.c b/drivers/tty/mips_ejtag_fdc.c index 02c10a968de1..31dceb5039b5 100644 --- a/drivers/tty/mips_ejtag_fdc.c +++ b/drivers/tty/mips_ejtag_fdc.c @@ -955,19 +955,18 @@ static int mips_ejtag_fdc_tty_probe(struct mips_cdmm_device *dev) mips_ejtag_fdc_con.tty_drv = driver; init_waitqueue_head(&priv->waitqueue); - priv->thread = kthread_create(mips_ejtag_fdc_put, priv, priv->fdc_name); - if (IS_ERR(priv->thread)) { - ret = PTR_ERR(priv->thread); - dev_err(priv->dev, "Couldn't create kthread (%d)\n", ret); - goto err_destroy_ports; - } /* * Bind the writer thread to the right CPU so it can't migrate. * The channels are per-CPU and we want all channel I/O to be on a * single predictable CPU. */ - kthread_bind(priv->thread, dev->cpu); - wake_up_process(priv->thread); + priv->thread = kthread_run_on_cpu(mips_ejtag_fdc_put, priv, + dev->cpu, "ttyFDC/%u"); + if (IS_ERR(priv->thread)) { + ret = PTR_ERR(priv->thread); + dev_err(priv->dev, "Couldn't create kthread (%d)\n", ret); + goto err_destroy_ports; + } /* Look for an FDC IRQ */ priv->irq = get_c0_fdc_int(); @@ -1095,15 +1094,14 @@ static int mips_ejtag_fdc_tty_cpu_up(struct mips_cdmm_device *dev) } /* Restart the kthread */ - priv->thread = kthread_create(mips_ejtag_fdc_put, priv, priv->fdc_name); + /* Bind it back to the right CPU and set it off */ + priv->thread = kthread_run_on_cpu(mips_ejtag_fdc_put, priv, + dev->cpu, "ttyFDC/%u"); if (IS_ERR(priv->thread)) { ret = PTR_ERR(priv->thread); dev_err(priv->dev, "Couldn't re-create kthread (%d)\n", ret); goto out; } - /* Bind it back to the right CPU and set it off */ - kthread_bind(priv->thread, dev->cpu); - wake_up_process(priv->thread); out: return ret; } -- cgit From 26baf4b66c57596d7827a8e4f60a2d2b0401fe6e Mon Sep 17 00:00:00 2001 From: Yoshihiro Shimoda Date: Thu, 9 Dec 2021 16:08:17 +0900 Subject: tty: serial: sh-sci: Add support for R-Car Gen4 Add serial support for R-Car Gen4 SoC. Reviewed-by: Geert Uytterhoeven Signed-off-by: Yoshihiro Shimoda Link: https://lore.kernel.org/r/20211209070817.1223888-3-yoshihiro.shimoda.uh@renesas.com Signed-off-by: Greg Kroah-Hartman --- drivers/tty/serial/sh-sci.c | 3 +++ 1 file changed, 3 insertions(+) (limited to 'drivers/tty') diff --git a/drivers/tty/serial/sh-sci.c b/drivers/tty/serial/sh-sci.c index 88005d2fc2a0..86731b816e3f 100644 --- a/drivers/tty/serial/sh-sci.c +++ b/drivers/tty/serial/sh-sci.c @@ -3181,6 +3181,9 @@ static const struct of_device_id of_sci_match[] = { }, { .compatible = "renesas,rcar-gen3-scif", .data = SCI_OF_DATA(PORT_SCIF, SCIx_SH4_SCIF_BRG_REGTYPE), + }, { + .compatible = "renesas,rcar-gen4-scif", + .data = SCI_OF_DATA(PORT_SCIF, SCIx_SH4_SCIF_BRG_REGTYPE), }, /* Generic types */ { -- cgit From f087f01ca2c5ea846fb798f09f4106b551c32147 Mon Sep 17 00:00:00 2001 From: Rob Herring Date: Wed, 15 Dec 2021 16:48:00 -0600 Subject: serial: lantiq: Use platform_get_irq() to get the interrupt Use the preferred platform_get_irq() call to retrieve the interrupts. These have the advantage of working with deferred probe and gets us one step closer to removing of_irq_to_resource_table(). Signed-off-by: Rob Herring Link: https://lore.kernel.org/r/20211215224800.1984391-1-robh@kernel.org Signed-off-by: Greg Kroah-Hartman --- drivers/tty/serial/lantiq.c | 28 +++++++++++++--------------- 1 file changed, 13 insertions(+), 15 deletions(-) (limited to 'drivers/tty') diff --git a/drivers/tty/serial/lantiq.c b/drivers/tty/serial/lantiq.c index 497b334bc845..bb059418cb82 100644 --- a/drivers/tty/serial/lantiq.c +++ b/drivers/tty/serial/lantiq.c @@ -16,8 +16,6 @@ #include #include #include -#include -#include #include #include #include @@ -728,19 +726,19 @@ static struct uart_driver lqasc_reg = { static int fetch_irq_lantiq(struct device *dev, struct ltq_uart_port *ltq_port) { struct uart_port *port = <q_port->port; - struct resource irqres[3]; - int ret; + struct platform_device *pdev = to_platform_device(dev); - ret = of_irq_to_resource_table(dev->of_node, irqres, 3); - if (ret != 3) { - dev_err(dev, - "failed to get IRQs for serial port\n"); - return -ENODEV; - } - ltq_port->tx_irq = irqres[0].start; - ltq_port->rx_irq = irqres[1].start; - ltq_port->err_irq = irqres[2].start; - port->irq = irqres[0].start; + ltq_port->tx_irq = platform_get_irq(pdev, 0); + if (ltq_port->tx_irq < 0) + return ltq_port->tx_irq; + ltq_port->rx_irq = platform_get_irq(pdev, 1); + if (ltq_port->rx_irq < 0) + return ltq_port->rx_irq; + ltq_port->err_irq = platform_get_irq(pdev, 2); + if (ltq_port->err_irq < 0) + return ltq_port->err_irq; + + port->irq = ltq_port->tx_irq; return 0; } @@ -793,7 +791,7 @@ static int fetch_irq_intel(struct device *dev, struct ltq_uart_port *ltq_port) struct uart_port *port = <q_port->port; int ret; - ret = of_irq_get(dev->of_node, 0); + ret = platform_get_irq(to_platform_device(dev), 0); if (ret < 0) { dev_err(dev, "failed to fetch IRQ for serial port\n"); return ret; -- cgit From 09c7bda4ddefb1e326378e2aaf1e7814f850d750 Mon Sep 17 00:00:00 2001 From: Geert Uytterhoeven Date: Thu, 16 Dec 2021 15:17:32 +0100 Subject: serial: sh-sci: Drop support for "sci_ick" clock Since commit 1b463bd51042927e ("ARM: dts: r8a7794: Rename the serial port clock to fck") in v4.6, all upstream DTS files call the SCIF functional clock "fck". Hence the time is ripe to drop backward-compatibility with old DTBs that use the old "sci_ick" name. Reviewed-by: Laurent Pinchart Reviewed-by: Wolfram Sang Signed-off-by: Geert Uytterhoeven Link: https://lore.kernel.org/r/b4103e44d6ac46b6c1c264e2aeac80b39941fe74.1639663832.git.geert+renesas@glider.be Signed-off-by: Greg Kroah-Hartman --- drivers/tty/serial/sh-sci.c | 11 ----------- 1 file changed, 11 deletions(-) (limited to 'drivers/tty') diff --git a/drivers/tty/serial/sh-sci.c b/drivers/tty/serial/sh-sci.c index 86731b816e3f..f63b5a6662d5 100644 --- a/drivers/tty/serial/sh-sci.c +++ b/drivers/tty/serial/sh-sci.c @@ -2784,17 +2784,6 @@ static int sci_init_clocks(struct sci_port *sci_port, struct device *dev) return -EPROBE_DEFER; if (IS_ERR(clk) && i == SCI_FCK) { - /* - * "fck" used to be called "sci_ick", and we need to - * maintain DT backward compatibility. - */ - clk = devm_clk_get(dev, "sci_ick"); - if (PTR_ERR(clk) == -EPROBE_DEFER) - return -EPROBE_DEFER; - - if (!IS_ERR(clk)) - goto found; - /* * Not all SH platforms declare a clock lookup entry * for SCI devices, in which case we need to get the -- cgit From 0d1bc829a755de826582c1c48ec40601d9b2fc29 Mon Sep 17 00:00:00 2001 From: Geert Uytterhoeven Date: Thu, 16 Dec 2021 15:17:33 +0100 Subject: serial: sh-sci: Use dev_err_probe() Use the dev_err_probe() helper to streamline error handling. Reviewed-by: Laurent Pinchart Reviewed-by: Wolfram Sang Signed-off-by: Geert Uytterhoeven Link: https://lore.kernel.org/r/5c4dd8df1f8d0d14786f26ee80b77f3eb8e06cd5.1639663832.git.geert+renesas@glider.be Signed-off-by: Greg Kroah-Hartman --- drivers/tty/serial/sh-sci.c | 11 ++++------- 1 file changed, 4 insertions(+), 7 deletions(-) (limited to 'drivers/tty') diff --git a/drivers/tty/serial/sh-sci.c b/drivers/tty/serial/sh-sci.c index f63b5a6662d5..9b4afbb3f67c 100644 --- a/drivers/tty/serial/sh-sci.c +++ b/drivers/tty/serial/sh-sci.c @@ -2790,15 +2790,12 @@ static int sci_init_clocks(struct sci_port *sci_port, struct device *dev) * global "peripheral_clk" clock. */ clk = devm_clk_get(dev, "peripheral_clk"); - if (!IS_ERR(clk)) - goto found; - - dev_err(dev, "failed to get %s (%ld)\n", clk_names[i], - PTR_ERR(clk)); - return PTR_ERR(clk); + if (IS_ERR(clk)) + return dev_err_probe(dev, PTR_ERR(clk), + "failed to get %s\n", + clk_names[i]); } -found: if (IS_ERR(clk)) dev_dbg(dev, "failed to get %s (%ld)\n", clk_names[i], PTR_ERR(clk)); -- cgit From 8a1dcae95c2ea4cb5d499833ad3c9a28f248ba7c Mon Sep 17 00:00:00 2001 From: Geert Uytterhoeven Date: Thu, 16 Dec 2021 15:17:34 +0100 Subject: serial: sh-sci: Use devm_clk_get_optional() The sh-sci driver supports up to four input clocks, of which only the first one is mandatory. Replace devm_clk_get() and custom error checking by devm_clk_get_optional(), to simplify the code and to catch all real errors. Reviewed-by: Wolfram Sang Reviewed-by: Laurent Pinchart Signed-off-by: Geert Uytterhoeven Link: https://lore.kernel.org/r/bce27288cb570952dd96b441e1af8768ad8b4870.1639663832.git.geert+renesas@glider.be Signed-off-by: Greg Kroah-Hartman --- drivers/tty/serial/sh-sci.c | 15 +++++++-------- 1 file changed, 7 insertions(+), 8 deletions(-) (limited to 'drivers/tty') diff --git a/drivers/tty/serial/sh-sci.c b/drivers/tty/serial/sh-sci.c index 9b4afbb3f67c..c9073ba3b8da 100644 --- a/drivers/tty/serial/sh-sci.c +++ b/drivers/tty/serial/sh-sci.c @@ -2779,11 +2779,11 @@ static int sci_init_clocks(struct sci_port *sci_port, struct device *dev) clk_names[SCI_SCK] = "hsck"; for (i = 0; i < SCI_NUM_CLKS; i++) { - clk = devm_clk_get(dev, clk_names[i]); - if (PTR_ERR(clk) == -EPROBE_DEFER) - return -EPROBE_DEFER; + clk = devm_clk_get_optional(dev, clk_names[i]); + if (IS_ERR(clk)) + return PTR_ERR(clk); - if (IS_ERR(clk) && i == SCI_FCK) { + if (!clk && i == SCI_FCK) { /* * Not all SH platforms declare a clock lookup entry * for SCI devices, in which case we need to get the @@ -2796,13 +2796,12 @@ static int sci_init_clocks(struct sci_port *sci_port, struct device *dev) clk_names[i]); } - if (IS_ERR(clk)) - dev_dbg(dev, "failed to get %s (%ld)\n", clk_names[i], - PTR_ERR(clk)); + if (!clk) + dev_dbg(dev, "failed to get %s\n", clk_names[i]); else dev_dbg(dev, "clk %s is %pC rate %lu\n", clk_names[i], clk, clk_get_rate(clk)); - sci_port->clks[i] = IS_ERR(clk) ? NULL : clk; + sci_port->clks[i] = clk; } return 0; } -- cgit From 5bb221b0ad655b47a1b7601223feb7dbd9ac232e Mon Sep 17 00:00:00 2001 From: Rob Herring Date: Wed, 15 Dec 2021 16:48:31 -0600 Subject: serial: atmel: Use platform_get_irq() to get the interrupt Accessing platform device resources directly has long been deprecated for DT as IRQ resources may not be available at device creation time. Drivers continuing to use static IRQ resources is blocking removing the static setup from the DT core code. Signed-off-by: Rob Herring Link: https://lore.kernel.org/r/20211215224832.1985402-1-robh@kernel.org Signed-off-by: Greg Kroah-Hartman --- drivers/tty/serial/atmel_serial.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers/tty') diff --git a/drivers/tty/serial/atmel_serial.c b/drivers/tty/serial/atmel_serial.c index 269b4500e9e7..c370eddc651b 100644 --- a/drivers/tty/serial/atmel_serial.c +++ b/drivers/tty/serial/atmel_serial.c @@ -2493,7 +2493,7 @@ static int atmel_init_port(struct atmel_uart_port *atmel_port, port->fifosize = 1; port->dev = &pdev->dev; port->mapbase = mpdev->resource[0].start; - port->irq = mpdev->resource[1].start; + port->irq = platform_get_irq(mpdev, 0); port->rs485_config = atmel_config_rs485; port->iso7816_config = atmel_config_iso7816; port->membase = NULL; -- cgit From 443df57b31d14a920f23eaa265f4cb0dc3f94823 Mon Sep 17 00:00:00 2001 From: Jesse Taube Date: Wed, 15 Dec 2021 17:05:36 -0500 Subject: tty: serial: fsl_lpuart: Add i.MXRT1050 support Add support for i.MXRT1050's uart. Cc: Giulio Benetti Signed-off-by: Jesse Taube Link: https://lore.kernel.org/r/20211215220538.4180616-8-Mr.Bossman075@gmail.com Signed-off-by: Greg Kroah-Hartman --- drivers/tty/serial/fsl_lpuart.c | 8 ++++++++ 1 file changed, 8 insertions(+) (limited to 'drivers/tty') diff --git a/drivers/tty/serial/fsl_lpuart.c b/drivers/tty/serial/fsl_lpuart.c index 3affe52a364d..ce3e26144689 100644 --- a/drivers/tty/serial/fsl_lpuart.c +++ b/drivers/tty/serial/fsl_lpuart.c @@ -247,6 +247,7 @@ enum lpuart_type { LS1028A_LPUART, IMX7ULP_LPUART, IMX8QXP_LPUART, + IMXRT1050_LPUART, }; struct lpuart_port { @@ -310,6 +311,11 @@ static struct lpuart_soc_data imx8qxp_data = { .iotype = UPIO_MEM32, .reg_off = IMX_REG_OFF, }; +static struct lpuart_soc_data imxrt1050_data = { + .devtype = IMXRT1050_LPUART, + .iotype = UPIO_MEM32, + .reg_off = IMX_REG_OFF, +}; static const struct of_device_id lpuart_dt_ids[] = { { .compatible = "fsl,vf610-lpuart", .data = &vf_data, }, @@ -317,6 +323,7 @@ static const struct of_device_id lpuart_dt_ids[] = { { .compatible = "fsl,ls1028a-lpuart", .data = &ls1028a_data, }, { .compatible = "fsl,imx7ulp-lpuart", .data = &imx7ulp_data, }, { .compatible = "fsl,imx8qxp-lpuart", .data = &imx8qxp_data, }, + { .compatible = "fsl,imxrt1050-lpuart", .data = &imxrt1050_data}, { /* sentinel */ } }; MODULE_DEVICE_TABLE(of, lpuart_dt_ids); @@ -2626,6 +2633,7 @@ OF_EARLYCON_DECLARE(lpuart32, "fsl,ls1021a-lpuart", lpuart32_early_console_setup OF_EARLYCON_DECLARE(lpuart32, "fsl,ls1028a-lpuart", ls1028a_early_console_setup); OF_EARLYCON_DECLARE(lpuart32, "fsl,imx7ulp-lpuart", lpuart32_imx_early_console_setup); OF_EARLYCON_DECLARE(lpuart32, "fsl,imx8qxp-lpuart", lpuart32_imx_early_console_setup); +OF_EARLYCON_DECLARE(lpuart32, "fsl,imxrt1050-lpuart", lpuart32_imx_early_console_setup); EARLYCON_DECLARE(lpuart, lpuart_early_console_setup); EARLYCON_DECLARE(lpuart32, lpuart32_early_console_setup); -- cgit From 4b95391c8ef0f270ed58234597aef58976abe01c Mon Sep 17 00:00:00 2001 From: Colin Ian King Date: Sun, 5 Dec 2021 23:28:22 +0000 Subject: serial: 8250_pci: remove redundant assignment to tmp after the mask operation The variable tmp is being masked with a bitmask and the value is being written to port base + 0x3c. However, the masked value is being written back to tmp and tmp is never used after this. The assignmentment is redundant, replace the &= operator with just &. Signed-off-by: Colin Ian King Reviewesd-by: Andy Shevchenko Link: https://lore.kernel.org/r/20211205232822.110099-1-colin.i.king@gmail.com Signed-off-by: Greg Kroah-Hartman --- drivers/tty/serial/8250/8250_pci.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers/tty') diff --git a/drivers/tty/serial/8250/8250_pci.c b/drivers/tty/serial/8250/8250_pci.c index 60f8fffdfd77..81aac3c25ead 100644 --- a/drivers/tty/serial/8250/8250_pci.c +++ b/drivers/tty/serial/8250/8250_pci.c @@ -1278,7 +1278,7 @@ static int pci_quatech_init(struct pci_dev *dev) outl(inl(base + 0x38) | 0x00002000, base + 0x38); tmp = inl(base + 0x3c); outl(tmp | 0x01000000, base + 0x3c); - outl(tmp &= ~0x01000000, base + 0x3c); + outl(tmp & ~0x01000000, base + 0x3c); } } return 0; -- cgit From 59f37b7370ef56e6faf25d0e18bc597a0af40bb8 Mon Sep 17 00:00:00 2001 From: Sam Protsenko Date: Sat, 4 Dec 2021 21:57:55 +0200 Subject: tty: serial: samsung: Remove USI initialization USI control is now extracted to the dedicated USI driver. Remove USI related code from serial driver to avoid conflicts and code duplication. Signed-off-by: Sam Protsenko Reviewed-by: Krzysztof Kozlowski Link: https://lore.kernel.org/r/20211204195757.8600-4-semen.protsenko@linaro.org Signed-off-by: Greg Kroah-Hartman --- drivers/tty/serial/samsung_tty.c | 36 ++++-------------------------------- 1 file changed, 4 insertions(+), 32 deletions(-) (limited to 'drivers/tty') diff --git a/drivers/tty/serial/samsung_tty.c b/drivers/tty/serial/samsung_tty.c index ca084c10d0bb..f986a9253dc8 100644 --- a/drivers/tty/serial/samsung_tty.c +++ b/drivers/tty/serial/samsung_tty.c @@ -65,7 +65,6 @@ enum s3c24xx_port_type { struct s3c24xx_uart_info { char *name; enum s3c24xx_port_type type; - bool has_usi; unsigned int port_type; unsigned int fifosize; unsigned long rx_fifomask; @@ -1357,28 +1356,6 @@ static int apple_s5l_serial_startup(struct uart_port *port) return ret; } -static void exynos_usi_init(struct uart_port *port) -{ - struct s3c24xx_uart_port *ourport = to_ourport(port); - struct s3c24xx_uart_info *info = ourport->info; - unsigned int val; - - if (!info->has_usi) - return; - - /* Clear the software reset of USI block (it's set at startup) */ - val = rd_regl(port, USI_CON); - val &= ~USI_CON_RESET_MASK; - wr_regl(port, USI_CON, val); - udelay(1); - - /* Continuously provide the clock to USI IP w/o gating (for Rx mode) */ - val = rd_regl(port, USI_OPTION); - val &= ~USI_OPTION_HWACG_MASK; - val |= USI_OPTION_HWACG_CLKREQ_ON; - wr_regl(port, USI_OPTION, val); -} - /* power power management control */ static void s3c24xx_serial_pm(struct uart_port *port, unsigned int level, @@ -1405,8 +1382,6 @@ static void s3c24xx_serial_pm(struct uart_port *port, unsigned int level, if (!IS_ERR(ourport->baudclk)) clk_prepare_enable(ourport->baudclk); - - exynos_usi_init(port); break; default: dev_err(port->dev, "s3c24xx_serial: unknown pm %d\n", level); @@ -2130,8 +2105,6 @@ static int s3c24xx_serial_init_port(struct s3c24xx_uart_port *ourport, if (ret) pr_warn("uart: failed to enable baudclk\n"); - exynos_usi_init(port); - /* Keep all interrupts masked and cleared */ switch (ourport->info->type) { case TYPE_S3C6400: @@ -2780,11 +2753,10 @@ static struct s3c24xx_serial_drv_data s5pv210_serial_drv_data = { #endif #if defined(CONFIG_ARCH_EXYNOS) -#define EXYNOS_COMMON_SERIAL_DRV_DATA(_has_usi) \ +#define EXYNOS_COMMON_SERIAL_DRV_DATA() \ .info = &(struct s3c24xx_uart_info) { \ .name = "Samsung Exynos UART", \ .type = TYPE_S3C6400, \ - .has_usi = _has_usi, \ .port_type = PORT_S3C6400, \ .has_divslot = 1, \ .rx_fifomask = S5PV210_UFSTAT_RXMASK, \ @@ -2805,17 +2777,17 @@ static struct s3c24xx_serial_drv_data s5pv210_serial_drv_data = { } \ static struct s3c24xx_serial_drv_data exynos4210_serial_drv_data = { - EXYNOS_COMMON_SERIAL_DRV_DATA(false), + EXYNOS_COMMON_SERIAL_DRV_DATA(), .fifosize = { 256, 64, 16, 16 }, }; static struct s3c24xx_serial_drv_data exynos5433_serial_drv_data = { - EXYNOS_COMMON_SERIAL_DRV_DATA(false), + EXYNOS_COMMON_SERIAL_DRV_DATA(), .fifosize = { 64, 256, 16, 256 }, }; static struct s3c24xx_serial_drv_data exynos850_serial_drv_data = { - EXYNOS_COMMON_SERIAL_DRV_DATA(true), + EXYNOS_COMMON_SERIAL_DRV_DATA(), .fifosize = { 256, 64, 64, 64 }, }; -- cgit From 0882b473b084df31288003b3bee974aabac9dcf9 Mon Sep 17 00:00:00 2001 From: Sam Protsenko Date: Sat, 4 Dec 2021 21:57:56 +0200 Subject: tty: serial: samsung: Enable console as module Enable serial driver to be built as a module. To do so, init the console support on driver/module load instead of using console_initcall(). Inspired by commit 87a0b9f98ac5 ("tty: serial: meson: enable console as module"). Signed-off-by: Sam Protsenko Reviewed-by: Krzysztof Kozlowski Link: https://lore.kernel.org/r/20211204195757.8600-5-semen.protsenko@linaro.org Signed-off-by: Greg Kroah-Hartman --- drivers/tty/serial/Kconfig | 2 +- drivers/tty/serial/samsung_tty.c | 36 ++++++++++++++++++++++++++++++++---- 2 files changed, 33 insertions(+), 5 deletions(-) (limited to 'drivers/tty') diff --git a/drivers/tty/serial/Kconfig b/drivers/tty/serial/Kconfig index fc543ac97c13..0e5ccb25bdb1 100644 --- a/drivers/tty/serial/Kconfig +++ b/drivers/tty/serial/Kconfig @@ -263,7 +263,7 @@ config SERIAL_SAMSUNG_UARTS config SERIAL_SAMSUNG_CONSOLE bool "Support for console on Samsung SoC serial port" - depends on SERIAL_SAMSUNG=y + depends on SERIAL_SAMSUNG select SERIAL_CORE_CONSOLE select SERIAL_EARLYCON help diff --git a/drivers/tty/serial/samsung_tty.c b/drivers/tty/serial/samsung_tty.c index f986a9253dc8..61ccb359620a 100644 --- a/drivers/tty/serial/samsung_tty.c +++ b/drivers/tty/serial/samsung_tty.c @@ -1715,15 +1715,21 @@ s3c24xx_serial_verify_port(struct uart_port *port, struct serial_struct *ser) static struct console s3c24xx_serial_console; -static int __init s3c24xx_serial_console_init(void) +static void __init s3c24xx_serial_register_console(void) { register_console(&s3c24xx_serial_console); - return 0; } -console_initcall(s3c24xx_serial_console_init); + +static void s3c24xx_serial_unregister_console(void) +{ + if (s3c24xx_serial_console.flags & CON_ENABLED) + unregister_console(&s3c24xx_serial_console); +} #define S3C24XX_SERIAL_CONSOLE &s3c24xx_serial_console #else +static inline void s3c24xx_serial_register_console(void) { } +static inline void s3c24xx_serial_unregister_console(void) { } #define S3C24XX_SERIAL_CONSOLE NULL #endif @@ -2898,7 +2904,29 @@ static struct platform_driver samsung_serial_driver = { }, }; -module_platform_driver(samsung_serial_driver); +static int __init samsung_serial_init(void) +{ + int ret; + + s3c24xx_serial_register_console(); + + ret = platform_driver_register(&samsung_serial_driver); + if (ret) { + s3c24xx_serial_unregister_console(); + return ret; + } + + return 0; +} + +static void __exit samsung_serial_exit(void) +{ + platform_driver_unregister(&samsung_serial_driver); + s3c24xx_serial_unregister_console(); +} + +module_init(samsung_serial_init); +module_exit(samsung_serial_exit); #ifdef CONFIG_SERIAL_SAMSUNG_CONSOLE /* -- cgit From 8cf8d3c4a634042f37ba34429e6a36412640ede4 Mon Sep 17 00:00:00 2001 From: Sam Protsenko Date: Sat, 4 Dec 2021 21:57:57 +0200 Subject: tty: serial: samsung: Fix console registration from module On modern Exynos SoCs (like Exynos850) the UART can be implemented as a part of USI IP-core. In such case, USI driver is used to initialize USI registers, and it also calls of_platform_populate() to instantiate all sub-nodes (e.g. serial node) of USI node. When serial driver is built-in, but USI driver is a module, and CONFIG_SERIAL_SAMSUNG_CONSOLE is enabled, next call chain will happen when loading USI module from user space: usi_init v usi_probe v of_platform_populate v s3c24xx_serial_probe v uart_add_one_port v uart_configure_port v register_console v try_enable_new_console v s3c24xx_serial_console_setup But because the serial driver is built-in, and s3c24xx_serial_console_setup() is marked with __init keyword, that symbol will discarded and long gone by that time already, causing failed paging request. That happens during the next config combination: EXYNOS_USI=m SERIAL_SAMSUNG=y SERIAL_SAMSUNG_CONSOLE=y That config should be completely possible, so rather than limiting SERIAL_SAMSUNG choice to "m" only when USI=m, remove __init keyword for all affected functions. Signed-off-by: Sam Protsenko Reviewed-by: Krzysztof Kozlowski Link: https://lore.kernel.org/r/20211204195757.8600-6-semen.protsenko@linaro.org Signed-off-by: Greg Kroah-Hartman --- drivers/tty/serial/samsung_tty.c | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) (limited to 'drivers/tty') diff --git a/drivers/tty/serial/samsung_tty.c b/drivers/tty/serial/samsung_tty.c index 61ccb359620a..d002a4e48ed9 100644 --- a/drivers/tty/serial/samsung_tty.c +++ b/drivers/tty/serial/samsung_tty.c @@ -2500,7 +2500,8 @@ s3c24xx_serial_console_write(struct console *co, const char *s, uart_console_write(cons_uart, s, count, s3c24xx_serial_console_putchar); } -static void __init +/* Shouldn't be __init, as it can be instantiated from other module */ +static void s3c24xx_serial_get_options(struct uart_port *port, int *baud, int *parity, int *bits) { @@ -2563,7 +2564,8 @@ s3c24xx_serial_get_options(struct uart_port *port, int *baud, } } -static int __init +/* Shouldn't be __init, as it can be instantiated from other module */ +static int s3c24xx_serial_console_setup(struct console *co, char *options) { struct uart_port *port; -- cgit From fcfd3c09f40786f8a296bfc93909612cc571c087 Mon Sep 17 00:00:00 2001 From: Andy Shevchenko Date: Mon, 22 Nov 2021 15:35:10 +0200 Subject: serial: 8250_pci: Split out Pericom driver Pericom along with Acces I/O support consumes a lot of LOCs in 8250_pci.c. For the sake of easier maintenance, split it to a separate driver. Signed-off-by: Andy Shevchenko Link: https://lore.kernel.org/r/20211122133512.8947-2-andriy.shevchenko@linux.intel.com Signed-off-by: Greg Kroah-Hartman --- drivers/tty/serial/8250/8250_pci.c | 405 +-------------------------------- drivers/tty/serial/8250/8250_pericom.c | 214 +++++++++++++++++ drivers/tty/serial/8250/Kconfig | 8 + drivers/tty/serial/8250/Makefile | 1 + 4 files changed, 228 insertions(+), 400 deletions(-) create mode 100644 drivers/tty/serial/8250/8250_pericom.c (limited to 'drivers/tty') diff --git a/drivers/tty/serial/8250/8250_pci.c b/drivers/tty/serial/8250/8250_pci.c index 81aac3c25ead..e8b5469e9dfa 100644 --- a/drivers/tty/serial/8250/8250_pci.c +++ b/drivers/tty/serial/8250/8250_pci.c @@ -1318,89 +1318,6 @@ static int pci_default_setup(struct serial_private *priv, return setup_port(priv, port, bar, offset, board->reg_shift); } -static void -pericom_do_set_divisor(struct uart_port *port, unsigned int baud, - unsigned int quot, unsigned int quot_frac) -{ - int scr; - int lcr; - - for (scr = 16; scr > 4; scr--) { - unsigned int maxrate = port->uartclk / scr; - unsigned int divisor = max(maxrate / baud, 1U); - int delta = maxrate / divisor - baud; - - if (baud > maxrate + baud / 50) - continue; - - if (delta > baud / 50) - divisor++; - - if (divisor > 0xffff) - continue; - - /* Update delta due to possible divisor change */ - delta = maxrate / divisor - baud; - if (abs(delta) < baud / 50) { - lcr = serial_port_in(port, UART_LCR); - serial_port_out(port, UART_LCR, lcr | 0x80); - serial_port_out(port, UART_DLL, divisor & 0xff); - serial_port_out(port, UART_DLM, divisor >> 8 & 0xff); - serial_port_out(port, 2, 16 - scr); - serial_port_out(port, UART_LCR, lcr); - return; - } - } -} -static int pci_pericom_setup(struct serial_private *priv, - const struct pciserial_board *board, - struct uart_8250_port *port, int idx) -{ - unsigned int bar, offset = board->first_offset, maxnr; - - bar = FL_GET_BASE(board->flags); - if (board->flags & FL_BASE_BARS) - bar += idx; - else - offset += idx * board->uart_offset; - - - maxnr = (pci_resource_len(priv->dev, bar) - board->first_offset) >> - (board->reg_shift + 3); - - if (board->flags & FL_REGION_SZ_CAP && idx >= maxnr) - return 1; - - port->port.set_divisor = pericom_do_set_divisor; - - return setup_port(priv, port, bar, offset, board->reg_shift); -} - -static int pci_pericom_setup_four_at_eight(struct serial_private *priv, - const struct pciserial_board *board, - struct uart_8250_port *port, int idx) -{ - unsigned int bar, offset = board->first_offset, maxnr; - - bar = FL_GET_BASE(board->flags); - if (board->flags & FL_BASE_BARS) - bar += idx; - else - offset += idx * board->uart_offset; - - if (idx==3) - offset = 0x38; - - maxnr = (pci_resource_len(priv->dev, bar) - board->first_offset) >> - (board->reg_shift + 3); - - if (board->flags & FL_REGION_SZ_CAP && idx >= maxnr) - return 1; - - port->port.set_divisor = pericom_do_set_divisor; - - return setup_port(priv, port, bar, offset, board->reg_shift); -} static int ce4100_serial_setup(struct serial_private *priv, @@ -1886,42 +1803,6 @@ pci_moxa_setup(struct serial_private *priv, #define PCIE_DEVICE_ID_WCH_CH384_8S 0x3853 #define PCIE_DEVICE_ID_WCH_CH382_2S 0x3253 -#define PCI_VENDOR_ID_ACCESIO 0x494f -#define PCI_DEVICE_ID_ACCESIO_PCIE_COM_2SDB 0x1051 -#define PCI_DEVICE_ID_ACCESIO_MPCIE_COM_2S 0x1053 -#define PCI_DEVICE_ID_ACCESIO_PCIE_COM_4SDB 0x105C -#define PCI_DEVICE_ID_ACCESIO_MPCIE_COM_4S 0x105E -#define PCI_DEVICE_ID_ACCESIO_PCIE_COM232_2DB 0x1091 -#define PCI_DEVICE_ID_ACCESIO_MPCIE_COM232_2 0x1093 -#define PCI_DEVICE_ID_ACCESIO_PCIE_COM232_4DB 0x1099 -#define PCI_DEVICE_ID_ACCESIO_MPCIE_COM232_4 0x109B -#define PCI_DEVICE_ID_ACCESIO_PCIE_COM_2SMDB 0x10D1 -#define PCI_DEVICE_ID_ACCESIO_MPCIE_COM_2SM 0x10D3 -#define PCI_DEVICE_ID_ACCESIO_PCIE_COM_4SMDB 0x10DA -#define PCI_DEVICE_ID_ACCESIO_MPCIE_COM_4SM 0x10DC -#define PCI_DEVICE_ID_ACCESIO_MPCIE_ICM485_1 0x1108 -#define PCI_DEVICE_ID_ACCESIO_MPCIE_ICM422_2 0x1110 -#define PCI_DEVICE_ID_ACCESIO_MPCIE_ICM485_2 0x1111 -#define PCI_DEVICE_ID_ACCESIO_MPCIE_ICM422_4 0x1118 -#define PCI_DEVICE_ID_ACCESIO_MPCIE_ICM485_4 0x1119 -#define PCI_DEVICE_ID_ACCESIO_PCIE_ICM_2S 0x1152 -#define PCI_DEVICE_ID_ACCESIO_PCIE_ICM_4S 0x115A -#define PCI_DEVICE_ID_ACCESIO_PCIE_ICM232_2 0x1190 -#define PCI_DEVICE_ID_ACCESIO_MPCIE_ICM232_2 0x1191 -#define PCI_DEVICE_ID_ACCESIO_PCIE_ICM232_4 0x1198 -#define PCI_DEVICE_ID_ACCESIO_MPCIE_ICM232_4 0x1199 -#define PCI_DEVICE_ID_ACCESIO_PCIE_ICM_2SM 0x11D0 -#define PCI_DEVICE_ID_ACCESIO_PCIE_COM422_4 0x105A -#define PCI_DEVICE_ID_ACCESIO_PCIE_COM485_4 0x105B -#define PCI_DEVICE_ID_ACCESIO_PCIE_COM422_8 0x106A -#define PCI_DEVICE_ID_ACCESIO_PCIE_COM485_8 0x106B -#define PCI_DEVICE_ID_ACCESIO_PCIE_COM232_4 0x1098 -#define PCI_DEVICE_ID_ACCESIO_PCIE_COM232_8 0x10A9 -#define PCI_DEVICE_ID_ACCESIO_PCIE_COM_4SM 0x10D9 -#define PCI_DEVICE_ID_ACCESIO_PCIE_COM_8SM 0x10E9 -#define PCI_DEVICE_ID_ACCESIO_PCIE_ICM_4SM 0x11D8 - - #define PCI_DEVICE_ID_MOXA_CP102E 0x1024 #define PCI_DEVICE_ID_MOXA_CP102EL 0x1025 #define PCI_DEVICE_ID_MOXA_CP104EL_A 0x1045 @@ -2198,16 +2079,6 @@ static struct pci_serial_quirk pci_serial_quirks[] = { .setup = pci_default_setup, .exit = pci_plx9050_exit, }, - /* - * Pericom (Only 7954 - It have a offset jump for port 4) - */ - { - .vendor = PCI_VENDOR_ID_PERICOM, - .device = PCI_DEVICE_ID_PERICOM_PI7C9X7954, - .subvendor = PCI_ANY_ID, - .subdevice = PCI_ANY_ID, - .setup = pci_pericom_setup_four_at_eight, - }, /* * PLX */ @@ -2238,125 +2109,7 @@ static struct pci_serial_quirk pci_serial_quirks[] = { .setup = pci_default_setup, .exit = pci_plx9050_exit, }, - { - .vendor = PCI_VENDOR_ID_ACCESIO, - .device = PCI_DEVICE_ID_ACCESIO_PCIE_COM_4SDB, - .subvendor = PCI_ANY_ID, - .subdevice = PCI_ANY_ID, - .setup = pci_pericom_setup_four_at_eight, - }, - { - .vendor = PCI_VENDOR_ID_ACCESIO, - .device = PCI_DEVICE_ID_ACCESIO_MPCIE_COM_4S, - .subvendor = PCI_ANY_ID, - .subdevice = PCI_ANY_ID, - .setup = pci_pericom_setup_four_at_eight, - }, - { - .vendor = PCI_VENDOR_ID_ACCESIO, - .device = PCI_DEVICE_ID_ACCESIO_PCIE_COM232_4DB, - .subvendor = PCI_ANY_ID, - .subdevice = PCI_ANY_ID, - .setup = pci_pericom_setup_four_at_eight, - }, - { - .vendor = PCI_VENDOR_ID_ACCESIO, - .device = PCI_DEVICE_ID_ACCESIO_MPCIE_COM232_4, - .subvendor = PCI_ANY_ID, - .subdevice = PCI_ANY_ID, - .setup = pci_pericom_setup_four_at_eight, - }, - { - .vendor = PCI_VENDOR_ID_ACCESIO, - .device = PCI_DEVICE_ID_ACCESIO_PCIE_COM_4SMDB, - .subvendor = PCI_ANY_ID, - .subdevice = PCI_ANY_ID, - .setup = pci_pericom_setup_four_at_eight, - }, - { - .vendor = PCI_VENDOR_ID_ACCESIO, - .device = PCI_DEVICE_ID_ACCESIO_MPCIE_COM_4SM, - .subvendor = PCI_ANY_ID, - .subdevice = PCI_ANY_ID, - .setup = pci_pericom_setup_four_at_eight, - }, - { - .vendor = PCI_VENDOR_ID_ACCESIO, - .device = PCI_DEVICE_ID_ACCESIO_MPCIE_ICM422_4, - .subvendor = PCI_ANY_ID, - .subdevice = PCI_ANY_ID, - .setup = pci_pericom_setup_four_at_eight, - }, - { - .vendor = PCI_VENDOR_ID_ACCESIO, - .device = PCI_DEVICE_ID_ACCESIO_MPCIE_ICM485_4, - .subvendor = PCI_ANY_ID, - .subdevice = PCI_ANY_ID, - .setup = pci_pericom_setup_four_at_eight, - }, - { - .vendor = PCI_VENDOR_ID_ACCESIO, - .device = PCI_DEVICE_ID_ACCESIO_PCIE_ICM232_4, - .subvendor = PCI_ANY_ID, - .subdevice = PCI_ANY_ID, - .setup = pci_pericom_setup_four_at_eight, - }, - { - .vendor = PCI_VENDOR_ID_ACCESIO, - .device = PCI_DEVICE_ID_ACCESIO_PCIE_ICM_4S, - .subvendor = PCI_ANY_ID, - .subdevice = PCI_ANY_ID, - .setup = pci_pericom_setup_four_at_eight, - }, - { - .vendor = PCI_VENDOR_ID_ACCESIO, - .device = PCI_DEVICE_ID_ACCESIO_MPCIE_ICM232_4, - .subvendor = PCI_ANY_ID, - .subdevice = PCI_ANY_ID, - .setup = pci_pericom_setup_four_at_eight, - }, - { - .vendor = PCI_VENDOR_ID_ACCESIO, - .device = PCI_DEVICE_ID_ACCESIO_PCIE_COM422_4, - .subvendor = PCI_ANY_ID, - .subdevice = PCI_ANY_ID, - .setup = pci_pericom_setup_four_at_eight, - }, - { - .vendor = PCI_VENDOR_ID_ACCESIO, - .device = PCI_DEVICE_ID_ACCESIO_PCIE_COM485_4, - .subvendor = PCI_ANY_ID, - .subdevice = PCI_ANY_ID, - .setup = pci_pericom_setup_four_at_eight, - }, - { - .vendor = PCI_VENDOR_ID_ACCESIO, - .device = PCI_DEVICE_ID_ACCESIO_PCIE_COM232_4, - .subvendor = PCI_ANY_ID, - .subdevice = PCI_ANY_ID, - .setup = pci_pericom_setup_four_at_eight, - }, - { - .vendor = PCI_VENDOR_ID_ACCESIO, - .device = PCI_DEVICE_ID_ACCESIO_PCIE_COM_4SM, - .subvendor = PCI_ANY_ID, - .subdevice = PCI_ANY_ID, - .setup = pci_pericom_setup_four_at_eight, - }, - { - .vendor = PCI_VENDOR_ID_ACCESIO, - .device = PCI_DEVICE_ID_ACCESIO_PCIE_ICM_4SM, - .subvendor = PCI_ANY_ID, - .subdevice = PCI_ANY_ID, - .setup = pci_pericom_setup_four_at_eight, - }, - { - .vendor = PCI_VENDOR_ID_ACCESIO, - .device = PCI_ANY_ID, - .subvendor = PCI_ANY_ID, - .subdevice = PCI_ANY_ID, - .setup = pci_pericom_setup, - }, /* + /* * SBS Technologies, Inc., PMC-OCTALPRO 232 */ { @@ -2948,10 +2701,6 @@ enum pci_board_num_t { pbn_wch382_2, pbn_wch384_4, pbn_wch384_8, - pbn_pericom_PI7C9X7951, - pbn_pericom_PI7C9X7952, - pbn_pericom_PI7C9X7954, - pbn_pericom_PI7C9X7958, pbn_sunix_pci_1s, pbn_sunix_pci_2s, pbn_sunix_pci_4s, @@ -3696,33 +3445,6 @@ static struct pciserial_board pci_boards[] = { .uart_offset = 8, .first_offset = 0x00, }, - /* - * Pericom PI7C9X795[1248] Uno/Dual/Quad/Octal UART - */ - [pbn_pericom_PI7C9X7951] = { - .flags = FL_BASE0, - .num_ports = 1, - .base_baud = 921600, - .uart_offset = 0x8, - }, - [pbn_pericom_PI7C9X7952] = { - .flags = FL_BASE0, - .num_ports = 2, - .base_baud = 921600, - .uart_offset = 0x8, - }, - [pbn_pericom_PI7C9X7954] = { - .flags = FL_BASE0, - .num_ports = 4, - .base_baud = 921600, - .uart_offset = 0x8, - }, - [pbn_pericom_PI7C9X7958] = { - .flags = FL_BASE0, - .num_ports = 8, - .base_baud = 921600, - .uart_offset = 0x8, - }, [pbn_sunix_pci_1s] = { .num_ports = 1, .base_baud = 921600, @@ -3834,6 +3556,10 @@ static const struct pci_device_id blacklist[] = { { PCI_VDEVICE(EXAR, PCI_ANY_ID), }, { PCI_VDEVICE(COMMTECH, PCI_ANY_ID), }, + /* Pericom devices */ + { PCI_VDEVICE(PERICOM, PCI_ANY_ID), }, + { PCI_VDEVICE(ACCESSIO, PCI_ANY_ID), }, + /* End of the black list */ { } }; @@ -5027,127 +4753,6 @@ static const struct pci_device_id serial_pci_tbl[] = { { PCI_VENDOR_ID_DCI, PCI_DEVICE_ID_DCI_PCCOM8, PCI_ANY_ID, PCI_ANY_ID, 0, 0, pbn_b3_8_115200 }, - /* - * Pericom PI7C9X795[1248] Uno/Dual/Quad/Octal UART - */ - { PCI_VENDOR_ID_PERICOM, PCI_DEVICE_ID_PERICOM_PI7C9X7951, - PCI_ANY_ID, PCI_ANY_ID, - 0, - 0, pbn_pericom_PI7C9X7951 }, - { PCI_VENDOR_ID_PERICOM, PCI_DEVICE_ID_PERICOM_PI7C9X7952, - PCI_ANY_ID, PCI_ANY_ID, - 0, - 0, pbn_pericom_PI7C9X7952 }, - { PCI_VENDOR_ID_PERICOM, PCI_DEVICE_ID_PERICOM_PI7C9X7954, - PCI_ANY_ID, PCI_ANY_ID, - 0, - 0, pbn_pericom_PI7C9X7954 }, - { PCI_VENDOR_ID_PERICOM, PCI_DEVICE_ID_PERICOM_PI7C9X7958, - PCI_ANY_ID, PCI_ANY_ID, - 0, - 0, pbn_pericom_PI7C9X7958 }, - /* - * ACCES I/O Products quad - */ - { PCI_VENDOR_ID_ACCESIO, PCI_DEVICE_ID_ACCESIO_PCIE_COM_2SDB, - PCI_ANY_ID, PCI_ANY_ID, 0, 0, - pbn_pericom_PI7C9X7952 }, - { PCI_VENDOR_ID_ACCESIO, PCI_DEVICE_ID_ACCESIO_MPCIE_COM_2S, - PCI_ANY_ID, PCI_ANY_ID, 0, 0, - pbn_pericom_PI7C9X7952 }, - { PCI_VENDOR_ID_ACCESIO, PCI_DEVICE_ID_ACCESIO_PCIE_COM_4SDB, - PCI_ANY_ID, PCI_ANY_ID, 0, 0, - pbn_pericom_PI7C9X7954 }, - { PCI_VENDOR_ID_ACCESIO, PCI_DEVICE_ID_ACCESIO_MPCIE_COM_4S, - PCI_ANY_ID, PCI_ANY_ID, 0, 0, - pbn_pericom_PI7C9X7954 }, - { PCI_VENDOR_ID_ACCESIO, PCI_DEVICE_ID_ACCESIO_PCIE_COM232_2DB, - PCI_ANY_ID, PCI_ANY_ID, 0, 0, - pbn_pericom_PI7C9X7952 }, - { PCI_VENDOR_ID_ACCESIO, PCI_DEVICE_ID_ACCESIO_MPCIE_COM232_2, - PCI_ANY_ID, PCI_ANY_ID, 0, 0, - pbn_pericom_PI7C9X7952 }, - { PCI_VENDOR_ID_ACCESIO, PCI_DEVICE_ID_ACCESIO_PCIE_COM232_4DB, - PCI_ANY_ID, PCI_ANY_ID, 0, 0, - pbn_pericom_PI7C9X7954 }, - { PCI_VENDOR_ID_ACCESIO, PCI_DEVICE_ID_ACCESIO_MPCIE_COM232_4, - PCI_ANY_ID, PCI_ANY_ID, 0, 0, - pbn_pericom_PI7C9X7954 }, - { PCI_VENDOR_ID_ACCESIO, PCI_DEVICE_ID_ACCESIO_PCIE_COM_2SMDB, - PCI_ANY_ID, PCI_ANY_ID, 0, 0, - pbn_pericom_PI7C9X7952 }, - { PCI_VENDOR_ID_ACCESIO, PCI_DEVICE_ID_ACCESIO_MPCIE_COM_2SM, - PCI_ANY_ID, PCI_ANY_ID, 0, 0, - pbn_pericom_PI7C9X7952 }, - { PCI_VENDOR_ID_ACCESIO, PCI_DEVICE_ID_ACCESIO_PCIE_COM_4SMDB, - PCI_ANY_ID, PCI_ANY_ID, 0, 0, - pbn_pericom_PI7C9X7954 }, - { PCI_VENDOR_ID_ACCESIO, PCI_DEVICE_ID_ACCESIO_MPCIE_COM_4SM, - PCI_ANY_ID, PCI_ANY_ID, 0, 0, - pbn_pericom_PI7C9X7954 }, - { PCI_VENDOR_ID_ACCESIO, PCI_DEVICE_ID_ACCESIO_MPCIE_ICM485_1, - PCI_ANY_ID, PCI_ANY_ID, 0, 0, - pbn_pericom_PI7C9X7951 }, - { PCI_VENDOR_ID_ACCESIO, PCI_DEVICE_ID_ACCESIO_MPCIE_ICM422_2, - PCI_ANY_ID, PCI_ANY_ID, 0, 0, - pbn_pericom_PI7C9X7952 }, - { PCI_VENDOR_ID_ACCESIO, PCI_DEVICE_ID_ACCESIO_MPCIE_ICM485_2, - PCI_ANY_ID, PCI_ANY_ID, 0, 0, - pbn_pericom_PI7C9X7952 }, - { PCI_VENDOR_ID_ACCESIO, PCI_DEVICE_ID_ACCESIO_MPCIE_ICM422_4, - PCI_ANY_ID, PCI_ANY_ID, 0, 0, - pbn_pericom_PI7C9X7954 }, - { PCI_VENDOR_ID_ACCESIO, PCI_DEVICE_ID_ACCESIO_MPCIE_ICM485_4, - PCI_ANY_ID, PCI_ANY_ID, 0, 0, - pbn_pericom_PI7C9X7954 }, - { PCI_VENDOR_ID_ACCESIO, PCI_DEVICE_ID_ACCESIO_PCIE_ICM_2S, - PCI_ANY_ID, PCI_ANY_ID, 0, 0, - pbn_pericom_PI7C9X7952 }, - { PCI_VENDOR_ID_ACCESIO, PCI_DEVICE_ID_ACCESIO_PCIE_ICM_4S, - PCI_ANY_ID, PCI_ANY_ID, 0, 0, - pbn_pericom_PI7C9X7954 }, - { PCI_VENDOR_ID_ACCESIO, PCI_DEVICE_ID_ACCESIO_PCIE_ICM232_2, - PCI_ANY_ID, PCI_ANY_ID, 0, 0, - pbn_pericom_PI7C9X7952 }, - { PCI_VENDOR_ID_ACCESIO, PCI_DEVICE_ID_ACCESIO_MPCIE_ICM232_2, - PCI_ANY_ID, PCI_ANY_ID, 0, 0, - pbn_pericom_PI7C9X7952 }, - { PCI_VENDOR_ID_ACCESIO, PCI_DEVICE_ID_ACCESIO_PCIE_ICM232_4, - PCI_ANY_ID, PCI_ANY_ID, 0, 0, - pbn_pericom_PI7C9X7954 }, - { PCI_VENDOR_ID_ACCESIO, PCI_DEVICE_ID_ACCESIO_MPCIE_ICM232_4, - PCI_ANY_ID, PCI_ANY_ID, 0, 0, - pbn_pericom_PI7C9X7954 }, - { PCI_VENDOR_ID_ACCESIO, PCI_DEVICE_ID_ACCESIO_PCIE_ICM_2SM, - PCI_ANY_ID, PCI_ANY_ID, 0, 0, - pbn_pericom_PI7C9X7952 }, - { PCI_VENDOR_ID_ACCESIO, PCI_DEVICE_ID_ACCESIO_PCIE_COM422_4, - PCI_ANY_ID, PCI_ANY_ID, 0, 0, - pbn_pericom_PI7C9X7954 }, - { PCI_VENDOR_ID_ACCESIO, PCI_DEVICE_ID_ACCESIO_PCIE_COM485_4, - PCI_ANY_ID, PCI_ANY_ID, 0, 0, - pbn_pericom_PI7C9X7954 }, - { PCI_VENDOR_ID_ACCESIO, PCI_DEVICE_ID_ACCESIO_PCIE_COM422_8, - PCI_ANY_ID, PCI_ANY_ID, 0, 0, - pbn_pericom_PI7C9X7958 }, - { PCI_VENDOR_ID_ACCESIO, PCI_DEVICE_ID_ACCESIO_PCIE_COM485_8, - PCI_ANY_ID, PCI_ANY_ID, 0, 0, - pbn_pericom_PI7C9X7958 }, - { PCI_VENDOR_ID_ACCESIO, PCI_DEVICE_ID_ACCESIO_PCIE_COM232_4, - PCI_ANY_ID, PCI_ANY_ID, 0, 0, - pbn_pericom_PI7C9X7954 }, - { PCI_VENDOR_ID_ACCESIO, PCI_DEVICE_ID_ACCESIO_PCIE_COM232_8, - PCI_ANY_ID, PCI_ANY_ID, 0, 0, - pbn_pericom_PI7C9X7958 }, - { PCI_VENDOR_ID_ACCESIO, PCI_DEVICE_ID_ACCESIO_PCIE_COM_4SM, - PCI_ANY_ID, PCI_ANY_ID, 0, 0, - pbn_pericom_PI7C9X7954 }, - { PCI_VENDOR_ID_ACCESIO, PCI_DEVICE_ID_ACCESIO_PCIE_COM_8SM, - PCI_ANY_ID, PCI_ANY_ID, 0, 0, - pbn_pericom_PI7C9X7958 }, - { PCI_VENDOR_ID_ACCESIO, PCI_DEVICE_ID_ACCESIO_PCIE_ICM_4SM, - PCI_ANY_ID, PCI_ANY_ID, 0, 0, - pbn_pericom_PI7C9X7954 }, /* * Topic TP560 Data/Fax/Voice 56k modem (reported by Evan Clarke) */ diff --git a/drivers/tty/serial/8250/8250_pericom.c b/drivers/tty/serial/8250/8250_pericom.c new file mode 100644 index 000000000000..df27f0daea7a --- /dev/null +++ b/drivers/tty/serial/8250/8250_pericom.c @@ -0,0 +1,214 @@ +// SPDX-License-Identifier: GPL-2.0 +/* Driver for Pericom UART */ + +#include +#include +#include +#include + +#include "8250.h" + +#define PCI_DEVICE_ID_ACCESSIO_PCIE_COM_2SDB 0x1051 +#define PCI_DEVICE_ID_ACCESSIO_MPCIE_COM_2S 0x1053 +#define PCI_DEVICE_ID_ACCESSIO_PCIE_COM422_4 0x105a +#define PCI_DEVICE_ID_ACCESSIO_PCIE_COM485_4 0x105b +#define PCI_DEVICE_ID_ACCESSIO_PCIE_COM_4SDB 0x105c +#define PCI_DEVICE_ID_ACCESSIO_MPCIE_COM_4S 0x105e +#define PCI_DEVICE_ID_ACCESSIO_PCIE_COM422_8 0x106a +#define PCI_DEVICE_ID_ACCESSIO_PCIE_COM485_8 0x106b +#define PCI_DEVICE_ID_ACCESSIO_PCIE_COM232_2DB 0x1091 +#define PCI_DEVICE_ID_ACCESSIO_MPCIE_COM232_2 0x1093 +#define PCI_DEVICE_ID_ACCESSIO_PCIE_COM232_4 0x1098 +#define PCI_DEVICE_ID_ACCESSIO_PCIE_COM232_4DB 0x1099 +#define PCI_DEVICE_ID_ACCESSIO_MPCIE_COM232_4 0x109b +#define PCI_DEVICE_ID_ACCESSIO_PCIE_COM232_8 0x10a9 +#define PCI_DEVICE_ID_ACCESSIO_PCIE_COM_2SMDB 0x10d1 +#define PCI_DEVICE_ID_ACCESSIO_MPCIE_COM_2SM 0x10d3 +#define PCI_DEVICE_ID_ACCESSIO_PCIE_COM_4SM 0x10d9 +#define PCI_DEVICE_ID_ACCESSIO_PCIE_COM_4SMDB 0x10da +#define PCI_DEVICE_ID_ACCESSIO_MPCIE_COM_4SM 0x10dc +#define PCI_DEVICE_ID_ACCESSIO_PCIE_COM_8SM 0x10e9 +#define PCI_DEVICE_ID_ACCESSIO_MPCIE_ICM485_1 0x1108 +#define PCI_DEVICE_ID_ACCESSIO_MPCIE_ICM422_2 0x1110 +#define PCI_DEVICE_ID_ACCESSIO_MPCIE_ICM485_2 0x1111 +#define PCI_DEVICE_ID_ACCESSIO_MPCIE_ICM422_4 0x1118 +#define PCI_DEVICE_ID_ACCESSIO_MPCIE_ICM485_4 0x1119 +#define PCI_DEVICE_ID_ACCESSIO_PCIE_ICM_2S 0x1152 +#define PCI_DEVICE_ID_ACCESSIO_PCIE_ICM_4S 0x115a +#define PCI_DEVICE_ID_ACCESSIO_PCIE_ICM232_2 0x1190 +#define PCI_DEVICE_ID_ACCESSIO_MPCIE_ICM232_2 0x1191 +#define PCI_DEVICE_ID_ACCESSIO_PCIE_ICM232_4 0x1198 +#define PCI_DEVICE_ID_ACCESSIO_MPCIE_ICM232_4 0x1199 +#define PCI_DEVICE_ID_ACCESSIO_PCIE_ICM_2SM 0x11d0 +#define PCI_DEVICE_ID_ACCESSIO_PCIE_ICM_4SM 0x11d8 + +struct pericom8250 { + void __iomem *virt; + unsigned int nr; + int line[]; +}; + +static void pericom_do_set_divisor(struct uart_port *port, unsigned int baud, + unsigned int quot, unsigned int quot_frac) +{ + int scr; + + for (scr = 16; scr > 4; scr--) { + unsigned int maxrate = port->uartclk / scr; + unsigned int divisor = max(maxrate / baud, 1U); + int delta = maxrate / divisor - baud; + + if (baud > maxrate + baud / 50) + continue; + + if (delta > baud / 50) + divisor++; + + if (divisor > 0xffff) + continue; + + /* Update delta due to possible divisor change */ + delta = maxrate / divisor - baud; + if (abs(delta) < baud / 50) { + int lcr = serial_port_in(port, UART_LCR); + + serial_port_out(port, UART_LCR, lcr | 0x80); + serial_port_out(port, UART_DLL, divisor & 0xff); + serial_port_out(port, UART_DLM, (divisor >> 8) & 0xff); + serial_port_out(port, 2, 16 - scr); + serial_port_out(port, UART_LCR, lcr); + return; + } + } +} + +static int pericom8250_probe(struct pci_dev *pdev, const struct pci_device_id *id) +{ + unsigned int nr, i, bar = 0, maxnr; + struct pericom8250 *pericom; + struct uart_8250_port uart; + int ret; + + ret = pcim_enable_device(pdev); + if (ret) + return ret; + + maxnr = pci_resource_len(pdev, bar) >> 3; + + if (pdev->vendor == PCI_VENDOR_ID_PERICOM) + nr = pdev->device & 0x0f; + else if (pdev->vendor == PCI_VENDOR_ID_ACCESSIO) + nr = BIT(((pdev->device & 0x38) >> 3) - 1); + else + nr = 1; + + pericom = devm_kzalloc(&pdev->dev, struct_size(pericom, line, nr), GFP_KERNEL); + if (!pericom) + return -ENOMEM; + + pericom->virt = pcim_iomap(pdev, bar, 0); + if (!pericom->virt) + return -ENOMEM; + + memset(&uart, 0, sizeof(uart)); + + uart.port.dev = &pdev->dev; + uart.port.irq = pdev->irq; + uart.port.private_data = pericom; + uart.port.iotype = UPIO_PORT; + uart.port.uartclk = 921600 * 16; + uart.port.flags = UPF_SKIP_TEST | UPF_BOOT_AUTOCONF | UPF_SHARE_IRQ; + uart.port.set_divisor = pericom_do_set_divisor; + for (i = 0; i < nr && i < maxnr; i++) { + unsigned int offset = (i == 3 && nr == 4) ? 0x38 : i * 0x8; + + uart.port.iobase = pci_resource_start(pdev, bar) + offset; + + dev_dbg(&pdev->dev, "Setup PCI port: port %lx, irq %d, type %d\n", + uart.port.iobase, uart.port.irq, uart.port.iotype); + + pericom->line[i] = serial8250_register_8250_port(&uart); + if (pericom->line[i] < 0) { + dev_err(&pdev->dev, + "Couldn't register serial port %lx, irq %d, type %d, error %d\n", + uart.port.iobase, uart.port.irq, + uart.port.iotype, pericom->line[i]); + break; + } + } + pericom->nr = i; + + pci_set_drvdata(pdev, pericom); + return 0; +} + +static void pericom8250_remove(struct pci_dev *pdev) +{ + struct pericom8250 *pericom = pci_get_drvdata(pdev); + unsigned int i; + + for (i = 0; i < pericom->nr; i++) + serial8250_unregister_port(pericom->line[i]); +} + +static const struct pci_device_id pericom8250_pci_ids[] = { + /* + * Pericom PI7C9X795[1248] Uno/Dual/Quad/Octal UART + * (Only 7954 has an offset jump for port 4) + */ + { PCI_VDEVICE(PERICOM, PCI_DEVICE_ID_PERICOM_PI7C9X7951) }, + { PCI_VDEVICE(PERICOM, PCI_DEVICE_ID_PERICOM_PI7C9X7952) }, + { PCI_VDEVICE(PERICOM, PCI_DEVICE_ID_PERICOM_PI7C9X7954) }, + { PCI_VDEVICE(PERICOM, PCI_DEVICE_ID_PERICOM_PI7C9X7958) }, + + /* + * ACCES I/O Products quad + * (Only 7954 has an offset jump for port 4) + */ + { PCI_VDEVICE(ACCESSIO, PCI_DEVICE_ID_ACCESSIO_PCIE_COM_2SDB) }, + { PCI_VDEVICE(ACCESSIO, PCI_DEVICE_ID_ACCESSIO_MPCIE_COM_2S) }, + { PCI_VDEVICE(ACCESSIO, PCI_DEVICE_ID_ACCESSIO_PCIE_COM422_4) }, + { PCI_VDEVICE(ACCESSIO, PCI_DEVICE_ID_ACCESSIO_PCIE_COM485_4) }, + { PCI_VDEVICE(ACCESSIO, PCI_DEVICE_ID_ACCESSIO_PCIE_COM_4SDB) }, + { PCI_VDEVICE(ACCESSIO, PCI_DEVICE_ID_ACCESSIO_MPCIE_COM_4S) }, + { PCI_VDEVICE(ACCESSIO, PCI_DEVICE_ID_ACCESSIO_PCIE_COM422_8) }, + { PCI_VDEVICE(ACCESSIO, PCI_DEVICE_ID_ACCESSIO_PCIE_COM485_8) }, + { PCI_VDEVICE(ACCESSIO, PCI_DEVICE_ID_ACCESSIO_PCIE_COM232_2DB) }, + { PCI_VDEVICE(ACCESSIO, PCI_DEVICE_ID_ACCESSIO_MPCIE_COM232_2) }, + { PCI_VDEVICE(ACCESSIO, PCI_DEVICE_ID_ACCESSIO_PCIE_COM232_4) }, + { PCI_VDEVICE(ACCESSIO, PCI_DEVICE_ID_ACCESSIO_PCIE_COM232_4DB) }, + { PCI_VDEVICE(ACCESSIO, PCI_DEVICE_ID_ACCESSIO_MPCIE_COM232_4) }, + { PCI_VDEVICE(ACCESSIO, PCI_DEVICE_ID_ACCESSIO_PCIE_COM232_8) }, + { PCI_VDEVICE(ACCESSIO, PCI_DEVICE_ID_ACCESSIO_PCIE_COM_2SMDB) }, + { PCI_VDEVICE(ACCESSIO, PCI_DEVICE_ID_ACCESSIO_MPCIE_COM_2SM) }, + { PCI_VDEVICE(ACCESSIO, PCI_DEVICE_ID_ACCESSIO_PCIE_COM_4SM) }, + { PCI_VDEVICE(ACCESSIO, PCI_DEVICE_ID_ACCESSIO_PCIE_COM_4SMDB) }, + { PCI_VDEVICE(ACCESSIO, PCI_DEVICE_ID_ACCESSIO_MPCIE_COM_4SM) }, + { PCI_VDEVICE(ACCESSIO, PCI_DEVICE_ID_ACCESSIO_PCIE_COM_8SM) }, + { PCI_VDEVICE(ACCESSIO, PCI_DEVICE_ID_ACCESSIO_MPCIE_ICM485_1) }, + { PCI_VDEVICE(ACCESSIO, PCI_DEVICE_ID_ACCESSIO_MPCIE_ICM422_2) }, + { PCI_VDEVICE(ACCESSIO, PCI_DEVICE_ID_ACCESSIO_MPCIE_ICM485_2) }, + { PCI_VDEVICE(ACCESSIO, PCI_DEVICE_ID_ACCESSIO_MPCIE_ICM422_4) }, + { PCI_VDEVICE(ACCESSIO, PCI_DEVICE_ID_ACCESSIO_MPCIE_ICM485_4) }, + { PCI_VDEVICE(ACCESSIO, PCI_DEVICE_ID_ACCESSIO_PCIE_ICM_2S) }, + { PCI_VDEVICE(ACCESSIO, PCI_DEVICE_ID_ACCESSIO_PCIE_ICM_4S) }, + { PCI_VDEVICE(ACCESSIO, PCI_DEVICE_ID_ACCESSIO_PCIE_ICM232_2) }, + { PCI_VDEVICE(ACCESSIO, PCI_DEVICE_ID_ACCESSIO_MPCIE_ICM232_2) }, + { PCI_VDEVICE(ACCESSIO, PCI_DEVICE_ID_ACCESSIO_PCIE_ICM232_4) }, + { PCI_VDEVICE(ACCESSIO, PCI_DEVICE_ID_ACCESSIO_MPCIE_ICM232_4) }, + { PCI_VDEVICE(ACCESSIO, PCI_DEVICE_ID_ACCESSIO_PCIE_ICM_2SM) }, + { PCI_VDEVICE(ACCESSIO, PCI_DEVICE_ID_ACCESSIO_PCIE_ICM_4SM) }, + { } +}; +MODULE_DEVICE_TABLE(pci, pericom8250_pci_ids); + +static struct pci_driver pericom8250_pci_driver = { + .name = "8250_pericom", + .id_table = pericom8250_pci_ids, + .probe = pericom8250_probe, + .remove = pericom8250_remove, +}; +module_pci_driver(pericom8250_pci_driver); + +MODULE_LICENSE("GPL v2"); +MODULE_DESCRIPTION("Pericom UART driver"); diff --git a/drivers/tty/serial/8250/Kconfig b/drivers/tty/serial/8250/Kconfig index 8cd11aa63ed5..9d415a38cc71 100644 --- a/drivers/tty/serial/8250/Kconfig +++ b/drivers/tty/serial/8250/Kconfig @@ -498,6 +498,14 @@ config SERIAL_8250_MID present on the UART found on Intel Medfield SOC and various other Intel platforms. +config SERIAL_8250_PERICOM + tristate "Support for Pericom and Acces I/O serial ports" + default SERIAL_8250 + depends on SERIAL_8250 && PCI + help + Selecting this option will enable handling of the extra features + present on the Pericom and Acces I/O UARTs. + config SERIAL_8250_PXA tristate "PXA serial port support" depends on SERIAL_8250 diff --git a/drivers/tty/serial/8250/Makefile b/drivers/tty/serial/8250/Makefile index b9bcd73c8997..4e4913e0e4d2 100644 --- a/drivers/tty/serial/8250/Makefile +++ b/drivers/tty/serial/8250/Makefile @@ -36,6 +36,7 @@ obj-$(CONFIG_SERIAL_8250_UNIPHIER) += 8250_uniphier.o obj-$(CONFIG_SERIAL_8250_INGENIC) += 8250_ingenic.o obj-$(CONFIG_SERIAL_8250_LPSS) += 8250_lpss.o obj-$(CONFIG_SERIAL_8250_MID) += 8250_mid.o +obj-$(CONFIG_SERIAL_8250_PERICOM) += 8250_pericom.o obj-$(CONFIG_SERIAL_8250_PXA) += 8250_pxa.o obj-$(CONFIG_SERIAL_8250_TEGRA) += 8250_tegra.o obj-$(CONFIG_SERIAL_8250_BCM7271) += 8250_bcm7271.o -- cgit From b4ccaf5aa2d795ee7f47a6eeb209f3de981e1929 Mon Sep 17 00:00:00 2001 From: Jay Dolan Date: Mon, 22 Nov 2021 15:35:11 +0200 Subject: serial: 8250_pericom: Re-enable higher baud rates Add UPF_MAGIC_MULTIPLIER to the port flags since there is now range checking in serial8250_get_baud_rate() in 8250_port.c. Signed-off-by: Jay Dolan Signed-off-by: Andy Shevchenko Link: https://lore.kernel.org/r/20211122133512.8947-3-andriy.shevchenko@linux.intel.com Signed-off-by: Greg Kroah-Hartman --- drivers/tty/serial/8250/8250_pericom.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers/tty') diff --git a/drivers/tty/serial/8250/8250_pericom.c b/drivers/tty/serial/8250/8250_pericom.c index df27f0daea7a..f0d026325f17 100644 --- a/drivers/tty/serial/8250/8250_pericom.c +++ b/drivers/tty/serial/8250/8250_pericom.c @@ -117,7 +117,7 @@ static int pericom8250_probe(struct pci_dev *pdev, const struct pci_device_id *i uart.port.private_data = pericom; uart.port.iotype = UPIO_PORT; uart.port.uartclk = 921600 * 16; - uart.port.flags = UPF_SKIP_TEST | UPF_BOOT_AUTOCONF | UPF_SHARE_IRQ; + uart.port.flags = UPF_SKIP_TEST | UPF_BOOT_AUTOCONF | UPF_SHARE_IRQ | UPF_MAGIC_MULTIPLIER; uart.port.set_divisor = pericom_do_set_divisor; for (i = 0; i < nr && i < maxnr; i++) { unsigned int offset = (i == 3 && nr == 4) ? 0x38 : i * 0x8; -- cgit From 46dacba8fea90d4b2562d45e8ca132f20a9ff5ce Mon Sep 17 00:00:00 2001 From: Andy Shevchenko Date: Mon, 22 Nov 2021 15:35:12 +0200 Subject: serial: 8250_pericom: Use serial_dl_write() instead of open coded It's better to stick with standard API to write and read DL value when the hardware is compatible with it. In case any quirks are needed it may be easily added in one place rather than modifying code here and there. Signed-off-by: Andy Shevchenko Link: https://lore.kernel.org/r/20211122133512.8947-4-andriy.shevchenko@linux.intel.com Signed-off-by: Greg Kroah-Hartman --- drivers/tty/serial/8250/8250_pericom.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'drivers/tty') diff --git a/drivers/tty/serial/8250/8250_pericom.c b/drivers/tty/serial/8250/8250_pericom.c index f0d026325f17..025b055363c3 100644 --- a/drivers/tty/serial/8250/8250_pericom.c +++ b/drivers/tty/serial/8250/8250_pericom.c @@ -70,11 +70,11 @@ static void pericom_do_set_divisor(struct uart_port *port, unsigned int baud, /* Update delta due to possible divisor change */ delta = maxrate / divisor - baud; if (abs(delta) < baud / 50) { + struct uart_8250_port *up = up_to_u8250p(port); int lcr = serial_port_in(port, UART_LCR); serial_port_out(port, UART_LCR, lcr | 0x80); - serial_port_out(port, UART_DLL, divisor & 0xff); - serial_port_out(port, UART_DLM, (divisor >> 8) & 0xff); + serial_dl_write(up, divisor); serial_port_out(port, 2, 16 - scr); serial_port_out(port, UART_LCR, lcr); return; -- cgit From 712fe4c849829352dd45dc14e027d61500931f85 Mon Sep 17 00:00:00 2001 From: Magnus Damm Date: Tue, 7 Dec 2021 11:02:20 +0900 Subject: serial: sh-sci: Remove BREAK/FRAME/PARITY/OVERRUN printouts Update the SCIF serial driver to remove printouts for break, frame, parity and overrun errors. This reduces the amount of console printouts generated by the defconfig kernel on R-Car Gen3 for certain use cases. To retrieve more information about such errors the user may inspect counters. Also these errors are fed into the TTY layer for further application specific handling. Reviewed-by: Geert Uytterhoeven Reviewed-by: Wolfram Sang Signed-off-by: Magnus Damm Link: https://lore.kernel.org/r/163884254093.18109.2982470198301927679.sendpatchset@octo Signed-off-by: Greg Kroah-Hartman --- drivers/tty/serial/sh-sci.c | 12 ------------ 1 file changed, 12 deletions(-) (limited to 'drivers/tty') diff --git a/drivers/tty/serial/sh-sci.c b/drivers/tty/serial/sh-sci.c index c9073ba3b8da..968967d722d4 100644 --- a/drivers/tty/serial/sh-sci.c +++ b/drivers/tty/serial/sh-sci.c @@ -896,11 +896,9 @@ static void sci_receive_chars(struct uart_port *port) if (status & SCxSR_FER(port)) { flag = TTY_FRAME; port->icount.frame++; - dev_notice(port->dev, "frame error\n"); } else if (status & SCxSR_PER(port)) { flag = TTY_PARITY; port->icount.parity++; - dev_notice(port->dev, "parity error\n"); } else flag = TTY_NORMAL; @@ -940,8 +938,6 @@ static int sci_handle_errors(struct uart_port *port) /* overrun error */ if (tty_insert_flip_char(tport, 0, TTY_OVERRUN)) copied++; - - dev_notice(port->dev, "overrun error\n"); } if (status & SCxSR_FER(port)) { @@ -950,8 +946,6 @@ static int sci_handle_errors(struct uart_port *port) if (tty_insert_flip_char(tport, 0, TTY_FRAME)) copied++; - - dev_notice(port->dev, "frame error\n"); } if (status & SCxSR_PER(port)) { @@ -960,8 +954,6 @@ static int sci_handle_errors(struct uart_port *port) if (tty_insert_flip_char(tport, 0, TTY_PARITY)) copied++; - - dev_notice(port->dev, "parity error\n"); } if (copied) @@ -991,8 +983,6 @@ static int sci_handle_fifo_overrun(struct uart_port *port) tty_insert_flip_char(tport, 0, TTY_OVERRUN); tty_flip_buffer_push(tport); - - dev_dbg(port->dev, "overrun error\n"); copied++; } @@ -1014,8 +1004,6 @@ static int sci_handle_breaks(struct uart_port *port) /* Notify of BREAK */ if (tty_insert_flip_char(tport, 0, TTY_BREAK)) copied++; - - dev_dbg(port->dev, "BREAK detected\n"); } if (copied) -- cgit From e822b4973f49015e1c6f63b91c8641ed9bfaf229 Mon Sep 17 00:00:00 2001 From: Xiang wangx Date: Wed, 8 Dec 2021 22:20:36 +0800 Subject: tty/ldsem: Fix syntax errors in comments Delete the redundant word 'are'. Signed-off-by: Xiang wangx Link: https://lore.kernel.org/r/20211208142036.7956-1-wangxiang@cdjrlc.com Signed-off-by: Greg Kroah-Hartman --- drivers/tty/tty_ldsem.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers/tty') diff --git a/drivers/tty/tty_ldsem.c b/drivers/tty/tty_ldsem.c index ce8291053af3..3be428c16260 100644 --- a/drivers/tty/tty_ldsem.c +++ b/drivers/tty/tty_ldsem.c @@ -163,7 +163,7 @@ down_read_failed(struct ld_semaphore *sem, long count, long timeout) /* * Try to reverse the lock attempt but if the count has changed - * so that reversing fails, check if there are are no waiters, + * so that reversing fails, check if there are no waiters, * and early-out if not */ do { -- cgit From d6d9d17abac8d337ecb052b47e918ca9c0b4ba1b Mon Sep 17 00:00:00 2001 From: Andy Shevchenko Date: Mon, 20 Dec 2021 15:32:50 +0200 Subject: tty: tty_io: Switch to vmalloc() fallback in case of TTY_NO_WRITE_SPLIT When TTY_NO_WRITE_SPLIT is set and 64 KiB chunks are used, allow vmalloc() fallback. Supply __GFP_RETRY_MAYFAIL to make kmalloc() preferable over vmalloc() since we may want a better performance. Note, both current users copy data to another buffer anyway, so the type of our allocation doesn't affect their expectations. Signed-off-by: Andy Shevchenko Link: https://lore.kernel.org/r/20211220133250.3070-1-andriy.shevchenko@linux.intel.com Signed-off-by: Greg Kroah-Hartman --- drivers/tty/tty_io.c | 9 +++------ 1 file changed, 3 insertions(+), 6 deletions(-) (limited to 'drivers/tty') diff --git a/drivers/tty/tty_io.c b/drivers/tty/tty_io.c index a4cfd254fda2..7e8b3bd59c7b 100644 --- a/drivers/tty/tty_io.c +++ b/drivers/tty/tty_io.c @@ -169,7 +169,7 @@ static void free_tty_struct(struct tty_struct *tty) { tty_ldisc_deinit(tty); put_device(tty->dev); - kfree(tty->write_buf); + kvfree(tty->write_buf); tty->magic = 0xDEADDEAD; kfree(tty); } @@ -986,9 +986,6 @@ static inline ssize_t do_tty_write( * layer has problems with bigger chunks. It will * claim to be able to handle more characters than * it actually does. - * - * FIXME: This can probably go away now except that 64K chunks - * are too likely to fail unless switched to vmalloc... */ chunk = 2048; if (test_bit(TTY_NO_WRITE_SPLIT, &tty->flags)) @@ -1003,12 +1000,12 @@ static inline ssize_t do_tty_write( if (chunk < 1024) chunk = 1024; - buf_chunk = kmalloc(chunk, GFP_KERNEL); + buf_chunk = kvmalloc(chunk, GFP_KERNEL | __GFP_RETRY_MAYFAIL); if (!buf_chunk) { ret = -ENOMEM; goto out; } - kfree(tty->write_buf); + kvfree(tty->write_buf); tty->write_cnt = chunk; tty->write_buf = buf_chunk; } -- cgit From fb09d0ac07725b442b32dbf53f0ab0bea54804e9 Mon Sep 17 00:00:00 2001 From: lianzhi chang Date: Wed, 15 Dec 2021 20:51:25 +0800 Subject: tty: Fix the keyboard led light display problem Use the "ctrl+alt+Fn" key combination to switch the system from tty to desktop or switch the system from desktop to tty. After the switch is completed, it is found that the state of the keyboard lock is inconsistent with the state of the keyboard Led light.The reasons are as follows: * The desktop environment (Xorg and other services) is bound to a tty (assuming it is tty1), and the kb->kbdmode attribute value of tty1 will be set to VC_OFF. According to the current code logic, in the desktop environment, the values of ledstate and kb->ledflagstate of tty1 will not be modified anymore, so they are always 0. * When switching between each tty, the final value of ledstate set by the previous tty is compared with the kb->ledflagstate value of the current tty to determine whether to set the state of the keyboard light. The process of switching between desktop and tty is also the process of switching between tty1 and other ttys. There are two situations: - (1) In the desktop environment, tty1 will not set the ledstate, which will cause when switching from the desktop to other ttys, if the desktop lights up the keyboard's led, after the switch is completed, the keyboard's led light will always be on; - (2) When switching from another tty to the desktop, this mechanism will trigger tty1 to set the led state. If other tty lights up the led of the keyboard before switching to the desktop, the led will be forcibly turned off. This situation should be avoided. * The current patch is to solve these problems: When VT is switched, the keyboard led needs to be set once.Ensure that after the switch is completed, the state of the keyboard LED is consistent with the state of the keyboard lock. Suggested-by: Dmitry Torokhov Reviewed-by: Dmitry Torokhov Signed-off-by: lianzhi chang Link: https://lore.kernel.org/r/20211215125125.10554-1-changlianzhi@uniontech.com Signed-off-by: Greg Kroah-Hartman --- drivers/tty/vt/keyboard.c | 12 ++++++++++++ 1 file changed, 12 insertions(+) (limited to 'drivers/tty') diff --git a/drivers/tty/vt/keyboard.c b/drivers/tty/vt/keyboard.c index 3700cd057f27..be8313cdbac3 100644 --- a/drivers/tty/vt/keyboard.c +++ b/drivers/tty/vt/keyboard.c @@ -153,6 +153,7 @@ static int shift_state = 0; static unsigned int ledstate = -1U; /* undefined */ static unsigned char ledioctl; +static bool vt_switch; /* * Notifier list for console keyboard events @@ -414,6 +415,12 @@ void vt_set_leds_compute_shiftstate(void) { unsigned long flags; + /* + * When VT is switched, the keyboard led needs to be set once. + * Ensure that after the switch is completed, the state of the + * keyboard LED is consistent with the state of the keyboard lock. + */ + vt_switch = true; set_leds(); spin_lock_irqsave(&kbd_event_lock, flags); @@ -1255,6 +1262,11 @@ static void kbd_bh(struct tasklet_struct *unused) leds |= (unsigned int)kbd->lockstate << 8; spin_unlock_irqrestore(&led_lock, flags); + if (vt_switch) { + ledstate = ~leds; + vt_switch = false; + } + if (leds != ledstate) { kbd_propagate_led_state(ledstate, leds); ledstate = leds; -- cgit From 5021d709b31b8a14317998a33cbc78be0de9ab30 Mon Sep 17 00:00:00 2001 From: Wander Lairson Costa Date: Wed, 22 Dec 2021 08:28:30 -0300 Subject: tty: serial: Use fifo in 8250 console driver Note: I am using a small test app + driver located at [0] for the problem description. serco is a driver whose write function dispatches to the serial controller. sertest is a user-mode app that writes n bytes to the serial console using the serco driver. While investigating a bug in the RHEL kernel, I noticed that the serial console throughput is way below the configured speed of 115200 bps in a HP Proliant DL380 Gen9. I was expecting something above 10KB/s, but I got 2.5KB/s. $ time ./sertest -n 2500 /tmp/serco real 0m0.997s user 0m0.000s sys 0m0.997s With the help of the function tracer, I then noticed the serial controller was taking around 410us seconds to dispatch one single byte: $ trace-cmd record -p function_graph -g serial8250_console_write \ ./sertest -n 1 /tmp/serco $ trace-cmd report | serial8250_console_write() { 0.384 us | _raw_spin_lock_irqsave(); 1.836 us | io_serial_in(); 1.667 us | io_serial_out(); | uart_console_write() { | serial8250_console_putchar() { | wait_for_xmitr() { 1.870 us | io_serial_in(); 2.238 us | } 1.737 us | io_serial_out(); 4.318 us | } 4.675 us | } | wait_for_xmitr() { 1.635 us | io_serial_in(); | __const_udelay() { 1.125 us | delay_tsc(); 1.429 us | } ... ... ... 1.683 us | io_serial_in(); | __const_udelay() { 1.248 us | delay_tsc(); 1.486 us | } 1.671 us | io_serial_in(); 411.342 us | } In another machine, I measured a throughput of 11.5KB/s, with the serial controller taking between 80-90us to send each byte. That matches the expected throughput for a configuration of 115200 bps. This patch changes the serial8250_console_write to use the 16550 fifo if available. In my benchmarks I got around 25% improvement in the slow machine, and no performance penalty in the fast machine. Signed-off-by: Wander Lairson Costa Link: https://lore.kernel.org/r/20211222112831.1968392-2-wander@redhat.com Signed-off-by: Greg Kroah-Hartman --- drivers/tty/serial/8250/8250_port.c | 61 +++++++++++++++++++++++++++++++++---- 1 file changed, 55 insertions(+), 6 deletions(-) (limited to 'drivers/tty') diff --git a/drivers/tty/serial/8250/8250_port.c b/drivers/tty/serial/8250/8250_port.c index 5d9a0e9f75d4..7e7e67dea0ad 100644 --- a/drivers/tty/serial/8250/8250_port.c +++ b/drivers/tty/serial/8250/8250_port.c @@ -2056,10 +2056,7 @@ static void serial8250_break_ctl(struct uart_port *port, int break_state) serial8250_rpm_put(up); } -/* - * Wait for transmitter & holding register to empty - */ -static void wait_for_xmitr(struct uart_8250_port *up, int bits) +static void wait_for_lsr(struct uart_8250_port *up, int bits) { unsigned int status, tmout = 10000; @@ -2076,6 +2073,16 @@ static void wait_for_xmitr(struct uart_8250_port *up, int bits) udelay(1); touch_nmi_watchdog(); } +} + +/* + * Wait for transmitter & holding register to empty + */ +static void wait_for_xmitr(struct uart_8250_port *up, int bits) +{ + unsigned int tmout; + + wait_for_lsr(up, bits); /* Wait up to 1s for flow control if necessary */ if (up->port.flags & UPF_CONS_FLOW) { @@ -3325,6 +3332,35 @@ static void serial8250_console_restore(struct uart_8250_port *up) serial8250_out_MCR(up, UART_MCR_DTR | UART_MCR_RTS); } +/* + * Print a string to the serial port using the device FIFO + * + * It sends fifosize bytes and then waits for the fifo + * to get empty. + */ +static void serial8250_console_fifo_write(struct uart_8250_port *up, + const char *s, unsigned int count) +{ + int i; + const char *end = s + count; + unsigned int fifosize = up->port.fifosize; + bool cr_sent = false; + + while (s != end) { + wait_for_lsr(up, UART_LSR_THRE); + + for (i = 0; i < fifosize && s != end; ++i) { + if (*s == '\n' && !cr_sent) { + serial_out(up, UART_TX, '\r'); + cr_sent = true; + } else { + serial_out(up, UART_TX, *s++); + cr_sent = false; + } + } + } +} + /* * Print a string to the serial port trying not to disturb * any possible real use of the port... @@ -3340,7 +3376,7 @@ void serial8250_console_write(struct uart_8250_port *up, const char *s, struct uart_8250_em485 *em485 = up->em485; struct uart_port *port = &up->port; unsigned long flags; - unsigned int ier; + unsigned int ier, use_fifo; int locked = 1; touch_nmi_watchdog(); @@ -3372,7 +3408,20 @@ void serial8250_console_write(struct uart_8250_port *up, const char *s, mdelay(port->rs485.delay_rts_before_send); } - uart_console_write(port, s, count, serial8250_console_putchar); + use_fifo = (up->capabilities & UART_CAP_FIFO) && + port->fifosize > 1 && + (serial_port_in(port, UART_FCR) & UART_FCR_ENABLE_FIFO) && + /* + * After we put a data in the fifo, the controller will send + * it regardless of the CTS state. Therefore, only use fifo + * if we don't use control flow. + */ + !(up->port.flags & UPF_CONS_FLOW); + + if (likely(use_fifo)) + serial8250_console_fifo_write(up, s, count); + else + uart_console_write(port, s, count, serial8250_console_putchar); /* * Finally, wait for transmitter to become empty -- cgit From d3b3404df318504ec084213ab1065b73f49b0f1d Mon Sep 17 00:00:00 2001 From: Lukas Wunner Date: Sat, 18 Dec 2021 10:58:56 +0100 Subject: serial: Fix incorrect rs485 polarity on uart open Commit a6845e1e1b78 ("serial: core: Consider rs485 settings to drive RTS") sought to deassert RTS when opening an rs485-enabled uart port. That way, the transceiver does not occupy the bus until it transmits data. Unfortunately, the commit mixed up the logic and *asserted* RTS instead of *deasserting* it: The commit amended uart_port_dtr_rts(), which raises DTR and RTS when opening an rs232 port. "Raising" actually means lowering the signal that's coming out of the uart, because an rs232 transceiver not only changes a signal's voltage level, it also *inverts* the signal. See the simplified schematic in the MAX232 datasheet for an example: https://www.ti.com/lit/ds/symlink/max232.pdf So, to raise RTS on an rs232 port, TIOCM_RTS is *set* in port->mctrl and that results in the signal being driven low. In contrast to rs232, the signal level for rs485 Transmit Enable is the identity, not the inversion: If the transceiver expects a "high" RTS signal for Transmit Enable, the signal coming out of the uart must also be high, so TIOCM_RTS must be *cleared* in port->mctrl. The commit did the exact opposite, but it's easy to see why given the confusing semantics of rs232 and rs485. Fix it. Fixes: a6845e1e1b78 ("serial: core: Consider rs485 settings to drive RTS") Cc: stable@vger.kernel.org # v4.14+ Cc: Rafael Gago Castano Cc: Jan Kiszka Cc: Su Bao Cheng Signed-off-by: Lukas Wunner Link: https://lore.kernel.org/r/9395767847833f2f3193c49cde38501eeb3b5669.1639821059.git.lukas@wunner.de Signed-off-by: Greg Kroah-Hartman --- drivers/tty/serial/serial_core.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'drivers/tty') diff --git a/drivers/tty/serial/serial_core.c b/drivers/tty/serial/serial_core.c index 29f4781db387..259f28ec6c8b 100644 --- a/drivers/tty/serial/serial_core.c +++ b/drivers/tty/serial/serial_core.c @@ -162,7 +162,7 @@ static void uart_port_dtr_rts(struct uart_port *uport, int raise) int RTS_after_send = !!(uport->rs485.flags & SER_RS485_RTS_AFTER_SEND); if (raise) { - if (rs485_on && !RTS_after_send) { + if (rs485_on && RTS_after_send) { uart_set_mctrl(uport, TIOCM_DTR); uart_clear_mctrl(uport, TIOCM_RTS); } else { @@ -171,7 +171,7 @@ static void uart_port_dtr_rts(struct uart_port *uport, int raise) } else { unsigned int clear = TIOCM_DTR; - clear |= (!rs485_on || !RTS_after_send) ? TIOCM_RTS : 0; + clear |= (!rs485_on || RTS_after_send) ? TIOCM_RTS : 0; uart_clear_mctrl(uport, clear); } } -- cgit From b4a29b94804c4774f22555651296b838df6ec0e4 Mon Sep 17 00:00:00 2001 From: Lukas Wunner Date: Tue, 28 Dec 2021 18:22:00 +0100 Subject: serial: 8250: Move Alpha-specific quirk out of the core struct uart_8250_port contains mcr_mask and mcr_force members whose sole purpose is to work around an Alpha-specific quirk. This code doesn't belong in the core where it is executed by everyone else, so move it to a proper ->set_mctrl callback which is used on the affected Alpha machine only. The quirk was introduced in January 1995: https://git.kernel.org/pub/scm/linux/kernel/git/history/history.git/diff/drivers/char/serial.c?h=1.1.83 The members in struct uart_8250_port were added in 2002: https://git.kernel.org/history/history/c/4524aad27854 The quirk applies to non-PCI Alphas and arch/alpha/Kconfig specifies "select FORCE_PCI if !ALPHA_JENSEN". So apparently the only affected machine is the EISA-based Jensen that Linus was working on back then: https://lore.kernel.org/all/CAHk-=wj1JWZ3sCrGz16nxEj7=0O+srMg6Ah3iPTDXSPKEws_SA@mail.gmail.com/ Up until now the quirk is not applied unless CONFIG_PCI is disabled. If users forget to do that or run a generic Alpha kernel, the serial ports aren't usable on Jensen. Avoid by confining the quirk to CONFIG_ALPHA_JENSEN instead of !CONFIG_PCI. On generic Alpha kernels, auto-detect at runtime whether the quirk needs to be applied. Cc: Russell King Cc: Ulrich Teichert Cc: Linus Torvalds Signed-off-by: Lukas Wunner Link: https://lore.kernel.org/r/b83d069cb516549b8a5420e097bb6bdd806f36fc.1640695609.git.lukas@wunner.de Signed-off-by: Greg Kroah-Hartman --- drivers/tty/serial/8250/8250.h | 12 ++---------- drivers/tty/serial/8250/8250_alpha.c | 21 +++++++++++++++++++++ drivers/tty/serial/8250/8250_core.c | 9 ++++----- drivers/tty/serial/8250/8250_port.c | 2 +- drivers/tty/serial/8250/Makefile | 2 ++ drivers/tty/serial/sunsu.c | 3 ++- 6 files changed, 32 insertions(+), 17 deletions(-) create mode 100644 drivers/tty/serial/8250/8250_alpha.c (limited to 'drivers/tty') diff --git a/drivers/tty/serial/8250/8250.h b/drivers/tty/serial/8250/8250.h index 6473361525d1..db784ace25d8 100644 --- a/drivers/tty/serial/8250/8250.h +++ b/drivers/tty/serial/8250/8250.h @@ -241,16 +241,8 @@ static inline int serial8250_in_MCR(struct uart_8250_port *up) return mctrl; } -#if defined(__alpha__) && !defined(CONFIG_PCI) -/* - * Digital did something really horribly wrong with the OUT1 and OUT2 - * lines on at least some ALPHA's. The failure mode is that if either - * is cleared, the machine locks up with endless interrupts. - */ -#define ALPHA_KLUDGE_MCR (UART_MCR_OUT2 | UART_MCR_OUT1) -#else -#define ALPHA_KLUDGE_MCR 0 -#endif +bool alpha_jensen(void); +void alpha_jensen_set_mctrl(struct uart_port *port, unsigned int mctrl); #ifdef CONFIG_SERIAL_8250_PNP int serial8250_pnp_init(void); diff --git a/drivers/tty/serial/8250/8250_alpha.c b/drivers/tty/serial/8250/8250_alpha.c new file mode 100644 index 000000000000..58e70328aa4d --- /dev/null +++ b/drivers/tty/serial/8250/8250_alpha.c @@ -0,0 +1,21 @@ +// SPDX-License-Identifier: GPL-2.0+ + +#include +#include "8250.h" + +bool alpha_jensen(void) +{ + return !strcmp(alpha_mv.vector_name, "Jensen"); +} + +void alpha_jensen_set_mctrl(struct uart_port *port, unsigned int mctrl) +{ + /* + * Digital did something really horribly wrong with the OUT1 and OUT2 + * lines on Alpha Jensen. The failure mode is that if either is + * cleared, the machine locks up with endless interrupts. + */ + mctrl |= TIOCM_OUT1 | TIOCM_OUT2; + + serial8250_do_set_mctrl(port, mctrl); +} diff --git a/drivers/tty/serial/8250/8250_core.c b/drivers/tty/serial/8250/8250_core.c index 1ce193daea7f..01d30f6ed8fb 100644 --- a/drivers/tty/serial/8250/8250_core.c +++ b/drivers/tty/serial/8250/8250_core.c @@ -509,11 +509,10 @@ static void __init serial8250_isa_init_ports(void) up->ops = &univ8250_driver_ops; - /* - * ALPHA_KLUDGE_MCR needs to be killed. - */ - up->mcr_mask = ~ALPHA_KLUDGE_MCR; - up->mcr_force = ALPHA_KLUDGE_MCR; + if (IS_ENABLED(CONFIG_ALPHA_JENSEN) || + (IS_ENABLED(CONFIG_ALPHA_GENERIC) && alpha_jensen())) + port->set_mctrl = alpha_jensen_set_mctrl; + serial8250_set_defaults(up); } diff --git a/drivers/tty/serial/8250/8250_port.c b/drivers/tty/serial/8250/8250_port.c index 7e7e67dea0ad..2abb3de11a48 100644 --- a/drivers/tty/serial/8250/8250_port.c +++ b/drivers/tty/serial/8250/8250_port.c @@ -2026,7 +2026,7 @@ void serial8250_do_set_mctrl(struct uart_port *port, unsigned int mctrl) mcr = serial8250_TIOCM_to_MCR(mctrl); - mcr = (mcr & up->mcr_mask) | up->mcr_force | up->mcr; + mcr |= up->mcr; serial8250_out_MCR(up, mcr); } diff --git a/drivers/tty/serial/8250/Makefile b/drivers/tty/serial/8250/Makefile index 4e4913e0e4d2..bee908f99ea0 100644 --- a/drivers/tty/serial/8250/Makefile +++ b/drivers/tty/serial/8250/Makefile @@ -5,6 +5,8 @@ obj-$(CONFIG_SERIAL_8250) += 8250.o 8250_base.o 8250-y := 8250_core.o +8250-$(CONFIG_ALPHA_GENERIC) += 8250_alpha.o +8250-$(CONFIG_ALPHA_JENSEN) += 8250_alpha.o 8250-$(CONFIG_SERIAL_8250_PNP) += 8250_pnp.o 8250_base-y := 8250_port.o 8250_base-$(CONFIG_SERIAL_8250_DMA) += 8250_dma.o diff --git a/drivers/tty/serial/sunsu.c b/drivers/tty/serial/sunsu.c index 425a016f9db7..98b2f4fb9a99 100644 --- a/drivers/tty/serial/sunsu.c +++ b/drivers/tty/serial/sunsu.c @@ -127,7 +127,8 @@ static void serial_out(struct uart_sunsu_port *up, int offset, int value) * gate outputs a logical one. Since we use level triggered interrupts * we have lockup and watchdog reset. We cannot mask IRQ because * keyboard shares IRQ with us (Word has it as Bob Smelik's design). - * This problem is similar to what Alpha people suffer, see serial.c. + * This problem is similar to what Alpha people suffer, see + * 8250_alpha.c. */ if (offset == UART_MCR) value |= UART_MCR_OUT2; -- cgit From cb559bb974536d75c8385b2caa57ab5a3862c29a Mon Sep 17 00:00:00 2001 From: Muhammad Usama Anjum Date: Tue, 21 Dec 2021 23:41:51 +0500 Subject: serial: lantiq: store and compare return status correctly platform_get_irq() returns signed status. It should be stored and compared as signed value before storing to unsigned variable. Implicit conversion from signed to unsigned and then comparison with less than zero is wrong as unsigned value can never be less than zero. Fixes: f087f01ca2c5 ("serial: lantiq: Use platform_get_irq() to get the interrupt") Acked-by: Rob Herring Signed-off-by: Muhammad Usama Anjum Link: https://lore.kernel.org/r/YcIf7+oSWWn34ND6@debian-BULLSEYE-live-builder-AMD64 Signed-off-by: Greg Kroah-Hartman --- drivers/tty/serial/lantiq.c | 24 ++++++++++++++---------- 1 file changed, 14 insertions(+), 10 deletions(-) (limited to 'drivers/tty') diff --git a/drivers/tty/serial/lantiq.c b/drivers/tty/serial/lantiq.c index bb059418cb82..3e324d3f0a6d 100644 --- a/drivers/tty/serial/lantiq.c +++ b/drivers/tty/serial/lantiq.c @@ -727,16 +727,20 @@ static int fetch_irq_lantiq(struct device *dev, struct ltq_uart_port *ltq_port) { struct uart_port *port = <q_port->port; struct platform_device *pdev = to_platform_device(dev); - - ltq_port->tx_irq = platform_get_irq(pdev, 0); - if (ltq_port->tx_irq < 0) - return ltq_port->tx_irq; - ltq_port->rx_irq = platform_get_irq(pdev, 1); - if (ltq_port->rx_irq < 0) - return ltq_port->rx_irq; - ltq_port->err_irq = platform_get_irq(pdev, 2); - if (ltq_port->err_irq < 0) - return ltq_port->err_irq; + int irq; + + irq = platform_get_irq(pdev, 0); + if (irq < 0) + return irq; + ltq_port->tx_irq = irq; + irq = platform_get_irq(pdev, 1); + if (irq < 0) + return irq; + ltq_port->rx_irq = irq; + irq = platform_get_irq(pdev, 2); + if (irq < 0) + return irq; + ltq_port->err_irq = irq; port->irq = ltq_port->tx_irq; -- cgit From 257538544d42987e740491838519ceee5e97d04e Mon Sep 17 00:00:00 2001 From: Lad Prabhakar Date: Fri, 24 Dec 2021 14:29:07 +0000 Subject: serial: altera: Use platform_get_irq_optional() to get the interrupt platform_get_resource(pdev, IORESOURCE_IRQ, ..) relies on static allocation of IRQ resources in DT core code, this causes an issue when using hierarchical interrupt domains using "interrupts" property in the node as this bypasses the hierarchical setup and messes up the irq chaining. In preparation for removal of static setup of IRQ resource from DT core code use platform_get_irq_optional(). Signed-off-by: Lad Prabhakar Link: https://lore.kernel.org/r/20211224142917.6966-2-prabhakar.mahadev-lad.rj@bp.renesas.com Signed-off-by: Greg Kroah-Hartman --- drivers/tty/serial/altera_uart.c | 9 +++++---- 1 file changed, 5 insertions(+), 4 deletions(-) (limited to 'drivers/tty') diff --git a/drivers/tty/serial/altera_uart.c b/drivers/tty/serial/altera_uart.c index 7c5f4e966b59..64a352b40197 100644 --- a/drivers/tty/serial/altera_uart.c +++ b/drivers/tty/serial/altera_uart.c @@ -553,7 +553,6 @@ static int altera_uart_probe(struct platform_device *pdev) struct altera_uart_platform_uart *platp = dev_get_platdata(&pdev->dev); struct uart_port *port; struct resource *res_mem; - struct resource *res_irq; int i = pdev->id; int ret; @@ -577,9 +576,11 @@ static int altera_uart_probe(struct platform_device *pdev) else return -EINVAL; - res_irq = platform_get_resource(pdev, IORESOURCE_IRQ, 0); - if (res_irq) - port->irq = res_irq->start; + ret = platform_get_irq_optional(pdev, 0); + if (ret < 0 && ret != -ENXIO) + return ret; + if (ret > 0) + port->irq = ret; else if (platp) port->irq = platp->irq; -- cgit From 56c8b1c10e95f9a56952a15b0a1656e04b98208d Mon Sep 17 00:00:00 2001 From: Lad Prabhakar Date: Fri, 24 Dec 2021 14:29:08 +0000 Subject: serial: 8250_bcm7271: Use platform_get_irq() to get the interrupt platform_get_resource(pdev, IORESOURCE_IRQ, ..) relies on static allocation of IRQ resources in DT core code, this causes an issue when using hierarchical interrupt domains using "interrupts" property in the node as this bypasses the hierarchical setup and messes up the irq chaining. In preparation for removal of static setup of IRQ resource from DT core code use platform_get_irq(). Acked-by: Florian Fainelli Signed-off-by: Lad Prabhakar Link: https://lore.kernel.org/r/20211224142917.6966-3-prabhakar.mahadev-lad.rj@bp.renesas.com Signed-off-by: Greg Kroah-Hartman --- drivers/tty/serial/8250/8250_bcm7271.c | 12 +++++------- 1 file changed, 5 insertions(+), 7 deletions(-) (limited to 'drivers/tty') diff --git a/drivers/tty/serial/8250/8250_bcm7271.c b/drivers/tty/serial/8250/8250_bcm7271.c index 5163d60756b7..7ecfcc650d28 100644 --- a/drivers/tty/serial/8250/8250_bcm7271.c +++ b/drivers/tty/serial/8250/8250_bcm7271.c @@ -941,7 +941,7 @@ static int brcmuart_probe(struct platform_device *pdev) struct brcmuart_priv *priv; struct clk *baud_mux_clk; struct uart_8250_port up; - struct resource *irq; + int irq; void __iomem *membase = NULL; resource_size_t mapbase = 0; u32 clk_rate = 0; @@ -952,11 +952,9 @@ static int brcmuart_probe(struct platform_device *pdev) "uart", "dma_rx", "dma_tx", "dma_intr2", "dma_arb" }; - irq = platform_get_resource(pdev, IORESOURCE_IRQ, 0); - if (!irq) { - dev_err(dev, "missing irq\n"); - return -EINVAL; - } + irq = platform_get_irq(pdev, 0); + if (irq < 0) + return irq; priv = devm_kzalloc(dev, sizeof(struct brcmuart_priv), GFP_KERNEL); if (!priv) @@ -1044,7 +1042,7 @@ static int brcmuart_probe(struct platform_device *pdev) up.port.dev = dev; up.port.mapbase = mapbase; up.port.membase = membase; - up.port.irq = irq->start; + up.port.irq = irq; up.port.handle_irq = brcmuart_handle_irq; up.port.regshift = 2; up.port.iotype = of_device_is_big_endian(np) ? -- cgit From c195438f1e84de8fa46b4f5264d12379bee6e9a1 Mon Sep 17 00:00:00 2001 From: Lad Prabhakar Date: Fri, 24 Dec 2021 14:29:09 +0000 Subject: serial: 8250_bcm7271: Propagate error codes from brcmuart_probe() In case of failures brcmuart_probe() always returned -ENODEV, this isn't correct for example platform_get_irq_byname() may return -EPROBE_DEFER to handle such cases propagate error codes in brcmuart_probe() in case of failures. Fixes: 41a469482de25 ("serial: 8250: Add new 8250-core based Broadcom STB driver") Acked-by: Florian Fainelli Signed-off-by: Lad Prabhakar Link: https://lore.kernel.org/r/20211224142917.6966-4-prabhakar.mahadev-lad.rj@bp.renesas.com Signed-off-by: Greg Kroah-Hartman --- drivers/tty/serial/8250/8250_bcm7271.c | 11 ++++++++--- 1 file changed, 8 insertions(+), 3 deletions(-) (limited to 'drivers/tty') diff --git a/drivers/tty/serial/8250/8250_bcm7271.c b/drivers/tty/serial/8250/8250_bcm7271.c index 7ecfcc650d28..cc60a7874e8b 100644 --- a/drivers/tty/serial/8250/8250_bcm7271.c +++ b/drivers/tty/serial/8250/8250_bcm7271.c @@ -1074,14 +1074,18 @@ static int brcmuart_probe(struct platform_device *pdev) priv->rx_bufs = dma_alloc_coherent(dev, priv->rx_size, &priv->rx_addr, GFP_KERNEL); - if (!priv->rx_bufs) + if (!priv->rx_bufs) { + ret = -EINVAL; goto err; + } priv->tx_size = UART_XMIT_SIZE; priv->tx_buf = dma_alloc_coherent(dev, priv->tx_size, &priv->tx_addr, GFP_KERNEL); - if (!priv->tx_buf) + if (!priv->tx_buf) { + ret = -EINVAL; goto err; + } } ret = serial8250_register_8250_port(&up); @@ -1095,6 +1099,7 @@ static int brcmuart_probe(struct platform_device *pdev) if (priv->dma_enabled) { dma_irq = platform_get_irq_byname(pdev, "dma"); if (dma_irq < 0) { + ret = dma_irq; dev_err(dev, "no IRQ resource info\n"); goto err1; } @@ -1114,7 +1119,7 @@ err1: err: brcmuart_free_bufs(dev, priv); brcmuart_arbitration(priv, 0); - return -ENODEV; + return ret; } static int brcmuart_remove(struct platform_device *pdev) -- cgit From 5b68061983471470d4109bac776145245f06bc09 Mon Sep 17 00:00:00 2001 From: Lad Prabhakar Date: Fri, 24 Dec 2021 14:29:10 +0000 Subject: serial: meson: Use platform_get_irq() to get the interrupt platform_get_resource(pdev, IORESOURCE_IRQ, ..) relies on static allocation of IRQ resources in DT core code, this causes an issue when using hierarchical interrupt domains using "interrupts" property in the node as this bypasses the hierarchical setup and messes up the irq chaining. In preparation for removal of static setup of IRQ resource from DT core code use platform_get_irq(). Signed-off-by: Lad Prabhakar Link: https://lore.kernel.org/r/20211224142917.6966-5-prabhakar.mahadev-lad.rj@bp.renesas.com Signed-off-by: Greg Kroah-Hartman --- drivers/tty/serial/meson_uart.c | 11 ++++++----- 1 file changed, 6 insertions(+), 5 deletions(-) (limited to 'drivers/tty') diff --git a/drivers/tty/serial/meson_uart.c b/drivers/tty/serial/meson_uart.c index efee3935917f..4bc87f0c5868 100644 --- a/drivers/tty/serial/meson_uart.c +++ b/drivers/tty/serial/meson_uart.c @@ -713,10 +713,11 @@ static int meson_uart_probe_clocks(struct platform_device *pdev, static int meson_uart_probe(struct platform_device *pdev) { - struct resource *res_mem, *res_irq; + struct resource *res_mem; struct uart_port *port; u32 fifosize = 64; /* Default is 64, 128 for EE UART_0 */ int ret = 0; + int irq; if (pdev->dev.of_node) pdev->id = of_alias_get_id(pdev->dev.of_node, "serial"); @@ -739,9 +740,9 @@ static int meson_uart_probe(struct platform_device *pdev) if (!res_mem) return -ENODEV; - res_irq = platform_get_resource(pdev, IORESOURCE_IRQ, 0); - if (!res_irq) - return -ENODEV; + irq = platform_get_irq(pdev, 0); + if (irq < 0) + return irq; of_property_read_u32(pdev->dev.of_node, "fifo-size", &fifosize); @@ -766,7 +767,7 @@ static int meson_uart_probe(struct platform_device *pdev) port->iotype = UPIO_MEM; port->mapbase = res_mem->start; port->mapsize = resource_size(res_mem); - port->irq = res_irq->start; + port->irq = irq; port->flags = UPF_BOOT_AUTOCONF | UPF_LOW_LATENCY; port->has_sysrq = IS_ENABLED(CONFIG_SERIAL_MESON_CONSOLE); port->dev = &pdev->dev; -- cgit From 6050efac12c6bd1cdb75cf217c37cf3ee9f408c9 Mon Sep 17 00:00:00 2001 From: Lad Prabhakar Date: Fri, 24 Dec 2021 14:29:11 +0000 Subject: serial: pxa: Use platform_get_irq() to get the interrupt platform_get_resource(pdev, IORESOURCE_IRQ, ..) relies on static allocation of IRQ resources in DT core code, this causes an issue when using hierarchical interrupt domains using "interrupts" property in the node as this bypasses the hierarchical setup and messes up the irq chaining. In preparation for removal of static setup of IRQ resource from DT core code use platform_get_irq(). Signed-off-by: Lad Prabhakar Link: https://lore.kernel.org/r/20211224142917.6966-6-prabhakar.mahadev-lad.rj@bp.renesas.com Signed-off-by: Greg Kroah-Hartman --- drivers/tty/serial/pxa.c | 12 ++++++++---- 1 file changed, 8 insertions(+), 4 deletions(-) (limited to 'drivers/tty') diff --git a/drivers/tty/serial/pxa.c b/drivers/tty/serial/pxa.c index 41319ef96fa6..30b099746a75 100644 --- a/drivers/tty/serial/pxa.c +++ b/drivers/tty/serial/pxa.c @@ -842,14 +842,18 @@ static int serial_pxa_probe_dt(struct platform_device *pdev, static int serial_pxa_probe(struct platform_device *dev) { struct uart_pxa_port *sport; - struct resource *mmres, *irqres; + struct resource *mmres; int ret; + int irq; mmres = platform_get_resource(dev, IORESOURCE_MEM, 0); - irqres = platform_get_resource(dev, IORESOURCE_IRQ, 0); - if (!mmres || !irqres) + if (!mmres) return -ENODEV; + irq = platform_get_irq(dev, 0); + if (irq < 0) + return irq; + sport = kzalloc(sizeof(struct uart_pxa_port), GFP_KERNEL); if (!sport) return -ENOMEM; @@ -869,7 +873,7 @@ static int serial_pxa_probe(struct platform_device *dev) sport->port.type = PORT_PXA; sport->port.iotype = UPIO_MEM; sport->port.mapbase = mmres->start; - sport->port.irq = irqres->start; + sport->port.irq = irq; sport->port.fifosize = 64; sport->port.ops = &serial_pxa_pops; sport->port.dev = &dev->dev; -- cgit From 60302276caff50f907bc3391a364691ab4a21b43 Mon Sep 17 00:00:00 2001 From: Lad Prabhakar Date: Fri, 24 Dec 2021 14:29:12 +0000 Subject: serial: altera_jtaguart: Use platform_get_irq_optional() to get the interrupt platform_get_resource(pdev, IORESOURCE_IRQ, ..) relies on static allocation of IRQ resources in DT core code, this causes an issue when using hierarchical interrupt domains using "interrupts" property in the node as this bypasses the hierarchical setup and messes up the irq chaining. In preparation for removal of static setup of IRQ resource from DT core code use platform_get_irq_optional(). Signed-off-by: Lad Prabhakar Link: https://lore.kernel.org/r/20211224142917.6966-7-prabhakar.mahadev-lad.rj@bp.renesas.com Signed-off-by: Greg Kroah-Hartman --- drivers/tty/serial/altera_jtaguart.c | 11 +++++++---- 1 file changed, 7 insertions(+), 4 deletions(-) (limited to 'drivers/tty') diff --git a/drivers/tty/serial/altera_jtaguart.c b/drivers/tty/serial/altera_jtaguart.c index 23c4e0e79694..37bffe406b18 100644 --- a/drivers/tty/serial/altera_jtaguart.c +++ b/drivers/tty/serial/altera_jtaguart.c @@ -418,8 +418,9 @@ static int altera_jtaguart_probe(struct platform_device *pdev) struct altera_jtaguart_platform_uart *platp = dev_get_platdata(&pdev->dev); struct uart_port *port; - struct resource *res_irq, *res_mem; + struct resource *res_mem; int i = pdev->id; + int irq; /* -1 emphasizes that the platform must have one port, no .N suffix */ if (i == -1) @@ -438,9 +439,11 @@ static int altera_jtaguart_probe(struct platform_device *pdev) else return -ENODEV; - res_irq = platform_get_resource(pdev, IORESOURCE_IRQ, 0); - if (res_irq) - port->irq = res_irq->start; + irq = platform_get_irq_optional(pdev, 0); + if (irq < 0 && irq != -ENXIO) + return irq; + if (irq > 0) + port->irq = irq; else if (platp) port->irq = platp->irq; else -- cgit From f63f1ddb5c2a9713c4cafce71d1eb3c1471d42e5 Mon Sep 17 00:00:00 2001 From: Lad Prabhakar Date: Fri, 24 Dec 2021 14:29:13 +0000 Subject: serial: vt8500: Use platform_get_irq() to get the interrupt platform_get_resource(pdev, IORESOURCE_IRQ, ..) relies on static allocation of IRQ resources in DT core code, this causes an issue when using hierarchical interrupt domains using "interrupts" property in the node as this bypasses the hierarchical setup and messes up the irq chaining. In preparation for removal of static setup of IRQ resource from DT core code use platform_get_irq(). Signed-off-by: Lad Prabhakar Link: https://lore.kernel.org/r/20211224142917.6966-8-prabhakar.mahadev-lad.rj@bp.renesas.com Signed-off-by: Greg Kroah-Hartman --- drivers/tty/serial/vt8500_serial.c | 12 ++++++++---- 1 file changed, 8 insertions(+), 4 deletions(-) (limited to 'drivers/tty') diff --git a/drivers/tty/serial/vt8500_serial.c b/drivers/tty/serial/vt8500_serial.c index e15b2bf69904..9adfe3dc970f 100644 --- a/drivers/tty/serial/vt8500_serial.c +++ b/drivers/tty/serial/vt8500_serial.c @@ -621,21 +621,25 @@ static const struct of_device_id wmt_dt_ids[] = { static int vt8500_serial_probe(struct platform_device *pdev) { struct vt8500_port *vt8500_port; - struct resource *mmres, *irqres; + struct resource *mmres; struct device_node *np = pdev->dev.of_node; const unsigned int *flags; int ret; int port; + int irq; flags = of_device_get_match_data(&pdev->dev); if (!flags) return -EINVAL; mmres = platform_get_resource(pdev, IORESOURCE_MEM, 0); - irqres = platform_get_resource(pdev, IORESOURCE_IRQ, 0); - if (!mmres || !irqres) + if (!mmres) return -ENODEV; + irq = platform_get_irq(pdev, 0); + if (irq < 0) + return irq; + if (np) { port = of_alias_get_id(np, "serial"); if (port >= VT8500_MAX_PORTS) @@ -688,7 +692,7 @@ static int vt8500_serial_probe(struct platform_device *pdev) vt8500_port->uart.type = PORT_VT8500; vt8500_port->uart.iotype = UPIO_MEM; vt8500_port->uart.mapbase = mmres->start; - vt8500_port->uart.irq = irqres->start; + vt8500_port->uart.irq = irq; vt8500_port->uart.fifosize = 16; vt8500_port->uart.ops = &vt8500_uart_pops; vt8500_port->uart.line = port; -- cgit From 1129a63e3a4c636f71c8d399313046f7b55f3009 Mon Sep 17 00:00:00 2001 From: Lad Prabhakar Date: Fri, 24 Dec 2021 14:29:14 +0000 Subject: serial: ar933x: Use platform_get_irq() to get the interrupt platform_get_resource(pdev, IORESOURCE_IRQ, ..) relies on static allocation of IRQ resources in DT core code, this causes an issue when using hierarchical interrupt domains using "interrupts" property in the node as this bypasses the hierarchical setup and messes up the irq chaining. In preparation for removal of static setup of IRQ resource from DT core code use platform_get_irq(). Signed-off-by: Lad Prabhakar Link: https://lore.kernel.org/r/20211224142917.6966-9-prabhakar.mahadev-lad.rj@bp.renesas.com Signed-off-by: Greg Kroah-Hartman --- drivers/tty/serial/ar933x_uart.c | 12 +++++------- 1 file changed, 5 insertions(+), 7 deletions(-) (limited to 'drivers/tty') diff --git a/drivers/tty/serial/ar933x_uart.c b/drivers/tty/serial/ar933x_uart.c index 4379ca4842ae..8cabe50c4a33 100644 --- a/drivers/tty/serial/ar933x_uart.c +++ b/drivers/tty/serial/ar933x_uart.c @@ -707,11 +707,11 @@ static int ar933x_uart_probe(struct platform_device *pdev) struct ar933x_uart_port *up; struct uart_port *port; struct resource *mem_res; - struct resource *irq_res; struct device_node *np; unsigned int baud; int id; int ret; + int irq; np = pdev->dev.of_node; if (IS_ENABLED(CONFIG_OF) && np) { @@ -730,11 +730,9 @@ static int ar933x_uart_probe(struct platform_device *pdev) if (id >= CONFIG_SERIAL_AR933X_NR_UARTS) return -EINVAL; - irq_res = platform_get_resource(pdev, IORESOURCE_IRQ, 0); - if (!irq_res) { - dev_err(&pdev->dev, "no IRQ resource\n"); - return -EINVAL; - } + irq = platform_get_irq(pdev, 0); + if (irq < 0) + return irq; up = devm_kzalloc(&pdev->dev, sizeof(struct ar933x_uart_port), GFP_KERNEL); @@ -766,7 +764,7 @@ static int ar933x_uart_probe(struct platform_device *pdev) port->mapbase = mem_res->start; port->line = id; - port->irq = irq_res->start; + port->irq = irq; port->dev = &pdev->dev; port->type = PORT_AR933X; port->iotype = UPIO_MEM32; -- cgit From fc67c913298c97bf5c1aac419ff260b7845613f5 Mon Sep 17 00:00:00 2001 From: Lad Prabhakar Date: Fri, 24 Dec 2021 14:29:15 +0000 Subject: serial: bcm63xx: Use platform_get_irq() to get the interrupt platform_get_resource(pdev, IORESOURCE_IRQ, ..) relies on static allocation of IRQ resources in DT core code, this causes an issue when using hierarchical interrupt domains using "interrupts" property in the node as this bypasses the hierarchical setup and messes up the irq chaining. In preparation for removal of static setup of IRQ resource from DT core code use platform_get_irq(). Acked-by: Florian Fainelli Signed-off-by: Lad Prabhakar Link: https://lore.kernel.org/r/20211224142917.6966-10-prabhakar.mahadev-lad.rj@bp.renesas.com Signed-off-by: Greg Kroah-Hartman --- drivers/tty/serial/bcm63xx_uart.c | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) (limited to 'drivers/tty') diff --git a/drivers/tty/serial/bcm63xx_uart.c b/drivers/tty/serial/bcm63xx_uart.c index 5fb0e84f7fd1..6471a54b616b 100644 --- a/drivers/tty/serial/bcm63xx_uart.c +++ b/drivers/tty/serial/bcm63xx_uart.c @@ -804,7 +804,7 @@ static struct uart_driver bcm_uart_driver = { */ static int bcm_uart_probe(struct platform_device *pdev) { - struct resource *res_mem, *res_irq; + struct resource *res_mem; struct uart_port *port; struct clk *clk; int ret; @@ -833,9 +833,10 @@ static int bcm_uart_probe(struct platform_device *pdev) if (IS_ERR(port->membase)) return PTR_ERR(port->membase); - res_irq = platform_get_resource(pdev, IORESOURCE_IRQ, 0); - if (!res_irq) - return -ENODEV; + ret = platform_get_irq(pdev, 0); + if (ret < 0) + return ret; + port->irq = ret; clk = clk_get(&pdev->dev, "refclk"); if (IS_ERR(clk) && pdev->dev.of_node) @@ -845,7 +846,6 @@ static int bcm_uart_probe(struct platform_device *pdev) return -ENODEV; port->iotype = UPIO_MEM; - port->irq = res_irq->start; port->ops = &bcm_uart_ops; port->flags = UPF_BOOT_AUTOCONF; port->dev = &pdev->dev; -- cgit From e3b27e2f56a5337d2ecdbe3feddc7c75e2205d59 Mon Sep 17 00:00:00 2001 From: Lad Prabhakar Date: Fri, 24 Dec 2021 14:29:16 +0000 Subject: serial: pmac_zilog: Use platform_get_irq() to get the interrupt platform_get_resource(pdev, IORESOURCE_IRQ, ..) relies on static allocation of IRQ resources in DT core code, this causes an issue when using hierarchical interrupt domains using "interrupts" property in the node as this bypasses the hierarchical setup and messes up the irq chaining. In preparation for removal of static setup of IRQ resource from DT core code use platform_get_irq(). Signed-off-by: Lad Prabhakar Link: https://lore.kernel.org/r/20211224142917.6966-11-prabhakar.mahadev-lad.rj@bp.renesas.com Signed-off-by: Greg Kroah-Hartman --- drivers/tty/serial/pmac_zilog.c | 12 ++++++++---- 1 file changed, 8 insertions(+), 4 deletions(-) (limited to 'drivers/tty') diff --git a/drivers/tty/serial/pmac_zilog.c b/drivers/tty/serial/pmac_zilog.c index 12ce150b0ad4..5359236b32d6 100644 --- a/drivers/tty/serial/pmac_zilog.c +++ b/drivers/tty/serial/pmac_zilog.c @@ -1702,17 +1702,21 @@ extern struct platform_device scc_a_pdev, scc_b_pdev; static int __init pmz_init_port(struct uart_pmac_port *uap) { - struct resource *r_ports, *r_irq; + struct resource *r_ports; + int irq; r_ports = platform_get_resource(uap->pdev, IORESOURCE_MEM, 0); - r_irq = platform_get_resource(uap->pdev, IORESOURCE_IRQ, 0); - if (!r_ports || !r_irq) + if (!r_ports) return -ENODEV; + irq = platform_get_irq(uap->pdev, 0); + if (irq < 0) + return irq; + uap->port.mapbase = r_ports->start; uap->port.membase = (unsigned char __iomem *) r_ports->start; uap->port.iotype = UPIO_MEM; - uap->port.irq = r_irq->start; + uap->port.irq = irq; uap->port.uartclk = ZS_CLOCK; uap->port.fifosize = 1; uap->port.ops = &pmz_pops; -- cgit From ad234e2bac274a43c9fa540bde8cd9f0c627b71f Mon Sep 17 00:00:00 2001 From: Yu Tu Date: Thu, 30 Dec 2021 18:21:05 +0800 Subject: tty: serial: meson: Drop the legacy compatible strings and clock code All mainline .dts files have been using the stable UART since Linux 4.16. Drop the legacy compatible strings and related clock code. Signed-off-by: Yu Tu Link: https://lore.kernel.org/r/20211230102110.3861-2-yu.tu@amlogic.com Signed-off-by: Greg Kroah-Hartman --- drivers/tty/serial/meson_uart.c | 34 ++-------------------------------- 1 file changed, 2 insertions(+), 32 deletions(-) (limited to 'drivers/tty') diff --git a/drivers/tty/serial/meson_uart.c b/drivers/tty/serial/meson_uart.c index 4bc87f0c5868..45e00d928253 100644 --- a/drivers/tty/serial/meson_uart.c +++ b/drivers/tty/serial/meson_uart.c @@ -622,10 +622,7 @@ meson_serial_early_console_setup(struct earlycon_device *device, const char *opt device->con->write = meson_serial_early_console_write; return 0; } -/* Legacy bindings, should be removed when no more used */ -OF_EARLYCON_DECLARE(meson, "amlogic,meson-uart", - meson_serial_early_console_setup); -/* Stable bindings */ + OF_EARLYCON_DECLARE(meson, "amlogic,meson-ao-uart", meson_serial_early_console_setup); @@ -668,25 +665,6 @@ static inline struct clk *meson_uart_probe_clock(struct device *dev, return clk; } -/* - * This function gets clocks in the legacy non-stable DT bindings. - * This code will be remove once all the platforms switch to the - * new DT bindings. - */ -static int meson_uart_probe_clocks_legacy(struct platform_device *pdev, - struct uart_port *port) -{ - struct clk *clk = NULL; - - clk = meson_uart_probe_clock(&pdev->dev, NULL); - if (IS_ERR(clk)) - return PTR_ERR(clk); - - port->uartclk = clk_get_rate(clk); - - return 0; -} - static int meson_uart_probe_clocks(struct platform_device *pdev, struct uart_port *port) { @@ -755,12 +733,7 @@ static int meson_uart_probe(struct platform_device *pdev) if (!port) return -ENOMEM; - /* Use legacy way until all platforms switch to new bindings */ - if (of_device_is_compatible(pdev->dev.of_node, "amlogic,meson-uart")) - ret = meson_uart_probe_clocks_legacy(pdev, port); - else - ret = meson_uart_probe_clocks(pdev, port); - + ret = meson_uart_probe_clocks(pdev, port); if (ret) return ret; @@ -805,9 +778,6 @@ static int meson_uart_remove(struct platform_device *pdev) } static const struct of_device_id meson_uart_dt_match[] = { - /* Legacy bindings, should be removed when no more used */ - { .compatible = "amlogic,meson-uart" }, - /* Stable bindings */ { .compatible = "amlogic,meson6-uart" }, { .compatible = "amlogic,meson8-uart" }, { .compatible = "amlogic,meson8b-uart" }, -- cgit From d8e9a406a931f687945703a4bac45042eb81ce92 Mon Sep 17 00:00:00 2001 From: Magnus Damm Date: Sun, 12 Dec 2021 22:21:28 +0900 Subject: serdev: BREAK/FRAME/PARITY/OVERRUN notification prototype V2 Allow serdev device drivers get notified by hardware errors such as BREAK, FRAME, PARITY and OVERRUN. With this patch, in the event of an error detected in the UART device driver the serdev_device_driver will get the newly introduced ->error() callback invoked if serdev_device_set_error_mask() has previously been used to enable the type of error. The errors are taken straight from the TTY layer and fed into the serdev_device_driver after filtering out only enabled errors. Without this patch the hardware errors never reach the serdev_device_driver. Signed-off-by: Magnus Damm Link: https://lore.kernel.org/r/163931528842.27756.3665040315954968747.sendpatchset@octo Signed-off-by: Greg Kroah-Hartman --- drivers/tty/serdev/core.c | 11 +++++++++ drivers/tty/serdev/serdev-ttyport.c | 49 +++++++++++++++++++++++++++++++++++++ 2 files changed, 60 insertions(+) (limited to 'drivers/tty') diff --git a/drivers/tty/serdev/core.c b/drivers/tty/serdev/core.c index f1324fe99378..5c25ae20e508 100644 --- a/drivers/tty/serdev/core.c +++ b/drivers/tty/serdev/core.c @@ -349,6 +349,17 @@ unsigned int serdev_device_set_baudrate(struct serdev_device *serdev, unsigned i } EXPORT_SYMBOL_GPL(serdev_device_set_baudrate); +void serdev_device_set_error_mask(struct serdev_device *serdev, unsigned long mask) +{ + struct serdev_controller *ctrl = serdev->ctrl; + + if (!ctrl || !ctrl->ops->set_error_mask) + return; + + ctrl->ops->set_error_mask(ctrl, mask); +} +EXPORT_SYMBOL_GPL(serdev_device_set_error_mask); + void serdev_device_set_flow_control(struct serdev_device *serdev, bool enable) { struct serdev_controller *ctrl = serdev->ctrl; diff --git a/drivers/tty/serdev/serdev-ttyport.c b/drivers/tty/serdev/serdev-ttyport.c index d367803e2044..239a1d5c66df 100644 --- a/drivers/tty/serdev/serdev-ttyport.c +++ b/drivers/tty/serdev/serdev-ttyport.c @@ -2,6 +2,7 @@ /* * Copyright (C) 2016-2017 Linaro Ltd., Rob Herring */ +#include #include #include #include @@ -9,6 +10,10 @@ #include #define SERPORT_ACTIVE 1 +#define SERPORT_NOTIFY_BREAK 2 +#define SERPORT_NOTIFY_FRAME 3 +#define SERPORT_NOTIFY_PARITY 4 +#define SERPORT_NOTIFY_OVERRUN 5 struct serport { struct tty_port *port; @@ -27,11 +32,39 @@ static int ttyport_receive_buf(struct tty_port *port, const unsigned char *cp, { struct serdev_controller *ctrl = port->client_data; struct serport *serport = serdev_controller_get_drvdata(ctrl); + unsigned long errors = 0; + unsigned int i; int ret; if (!test_bit(SERPORT_ACTIVE, &serport->flags)) return 0; + for (i = 0; fp && i < count; i++) { + switch (fp[i]) { + case TTY_BREAK: + if (test_bit(SERPORT_NOTIFY_BREAK, &serport->flags)) + __set_bit(SERDEV_ERROR_BREAK, &errors); + break; + + case TTY_FRAME: + if (test_bit(SERPORT_NOTIFY_FRAME, &serport->flags)) + __set_bit(SERDEV_ERROR_FRAME, &errors); + break; + + case TTY_PARITY: + if (test_bit(SERPORT_NOTIFY_PARITY, &serport->flags)) + __set_bit(SERDEV_ERROR_PARITY, &errors); + break; + + case TTY_OVERRUN: + if (test_bit(SERPORT_NOTIFY_OVERRUN, &serport->flags)) + __set_bit(SERDEV_ERROR_OVERRUN, &errors); + break; + } + } + if (errors) + serdev_controller_error(ctrl, errors); + ret = serdev_controller_receive_buf(ctrl, cp, count); dev_WARN_ONCE(&ctrl->dev, ret < 0 || ret > count, @@ -180,6 +213,21 @@ static unsigned int ttyport_set_baudrate(struct serdev_controller *ctrl, unsigne return ktermios.c_ospeed; } +static void ttyport_set_error_mask(struct serdev_controller *ctrl, + unsigned long m) +{ + struct serport *sp = serdev_controller_get_drvdata(ctrl); + + assign_bit(SERPORT_NOTIFY_BREAK, &sp->flags, + m & BIT(SERDEV_ERROR_BREAK)); + assign_bit(SERPORT_NOTIFY_FRAME, &sp->flags, + m & BIT(SERDEV_ERROR_FRAME)); + assign_bit(SERPORT_NOTIFY_PARITY, &sp->flags, + m & BIT(SERDEV_ERROR_PARITY)); + assign_bit(SERPORT_NOTIFY_OVERRUN, &sp->flags, + m & BIT(SERDEV_ERROR_OVERRUN)); +} + static void ttyport_set_flow_control(struct serdev_controller *ctrl, bool enable) { struct serport *serport = serdev_controller_get_drvdata(ctrl); @@ -253,6 +301,7 @@ static const struct serdev_controller_ops ctrl_ops = { .write_room = ttyport_write_room, .open = ttyport_open, .close = ttyport_close, + .set_error_mask = ttyport_set_error_mask, .set_flow_control = ttyport_set_flow_control, .set_parity = ttyport_set_parity, .set_baudrate = ttyport_set_baudrate, -- cgit From 5acb78dc72b48bc44226a86368fb442800981a0c Mon Sep 17 00:00:00 2001 From: Lad Prabhakar Date: Fri, 24 Dec 2021 15:37:53 +0000 Subject: tty: goldfish: Use platform_get_irq() to get the interrupt platform_get_resource(pdev, IORESOURCE_IRQ, ..) relies on static allocation of IRQ resources in DT core code, this causes an issue when using hierarchical interrupt domains using "interrupts" property in the node as this bypasses the hierarchical setup and messes up the irq chaining. In preparation for removal of static setup of IRQ resource from DT core code use platform_get_irq(). Signed-off-by: Lad Prabhakar Link: https://lore.kernel.org/r/20211224153753.22210-1-prabhakar.mahadev-lad.rj@bp.renesas.com Signed-off-by: Greg Kroah-Hartman --- drivers/tty/goldfish.c | 10 ++++------ 1 file changed, 4 insertions(+), 6 deletions(-) (limited to 'drivers/tty') diff --git a/drivers/tty/goldfish.c b/drivers/tty/goldfish.c index c01cd36dda41..5ed19a9857ad 100644 --- a/drivers/tty/goldfish.c +++ b/drivers/tty/goldfish.c @@ -298,7 +298,7 @@ static int goldfish_tty_probe(struct platform_device *pdev) struct resource *r; struct device *ttydev; void __iomem *base; - u32 irq; + int irq; unsigned int line; r = platform_get_resource(pdev, IORESOURCE_MEM, 0); @@ -313,14 +313,12 @@ static int goldfish_tty_probe(struct platform_device *pdev) return -ENOMEM; } - r = platform_get_resource(pdev, IORESOURCE_IRQ, 0); - if (!r) { - pr_err("goldfish_tty: No IRQ resource available!\n"); + irq = platform_get_irq(pdev, 0); + if (irq < 0) { + ret = irq; goto err_unmap; } - irq = r->start; - mutex_lock(&goldfish_tty_lock); if (pdev->id == PLATFORM_DEVID_NONE) -- cgit From 99a507a8ea28542ec196e2dd80096708e2482735 Mon Sep 17 00:00:00 2001 From: Greg Kroah-Hartman Date: Fri, 31 Dec 2021 13:42:30 +0100 Subject: Revert "serdev: BREAK/FRAME/PARITY/OVERRUN notification prototype V2" This reverts commit d8e9a406a931f687945703a4bac45042eb81ce92. It needs some future changes as pointed out by Johan and is not ready to be merged just yet. Reported-by: Johan Hovold Cc: Magnus Damm Link: https://lore.kernel.org/r/Yc7oZ/1tu95Z4wPS@hovoldconsulting.com Signed-off-by: Greg Kroah-Hartman --- drivers/tty/serdev/core.c | 11 --------- drivers/tty/serdev/serdev-ttyport.c | 49 ------------------------------------- 2 files changed, 60 deletions(-) (limited to 'drivers/tty') diff --git a/drivers/tty/serdev/core.c b/drivers/tty/serdev/core.c index 5c25ae20e508..f1324fe99378 100644 --- a/drivers/tty/serdev/core.c +++ b/drivers/tty/serdev/core.c @@ -349,17 +349,6 @@ unsigned int serdev_device_set_baudrate(struct serdev_device *serdev, unsigned i } EXPORT_SYMBOL_GPL(serdev_device_set_baudrate); -void serdev_device_set_error_mask(struct serdev_device *serdev, unsigned long mask) -{ - struct serdev_controller *ctrl = serdev->ctrl; - - if (!ctrl || !ctrl->ops->set_error_mask) - return; - - ctrl->ops->set_error_mask(ctrl, mask); -} -EXPORT_SYMBOL_GPL(serdev_device_set_error_mask); - void serdev_device_set_flow_control(struct serdev_device *serdev, bool enable) { struct serdev_controller *ctrl = serdev->ctrl; diff --git a/drivers/tty/serdev/serdev-ttyport.c b/drivers/tty/serdev/serdev-ttyport.c index 239a1d5c66df..d367803e2044 100644 --- a/drivers/tty/serdev/serdev-ttyport.c +++ b/drivers/tty/serdev/serdev-ttyport.c @@ -2,7 +2,6 @@ /* * Copyright (C) 2016-2017 Linaro Ltd., Rob Herring */ -#include #include #include #include @@ -10,10 +9,6 @@ #include #define SERPORT_ACTIVE 1 -#define SERPORT_NOTIFY_BREAK 2 -#define SERPORT_NOTIFY_FRAME 3 -#define SERPORT_NOTIFY_PARITY 4 -#define SERPORT_NOTIFY_OVERRUN 5 struct serport { struct tty_port *port; @@ -32,39 +27,11 @@ static int ttyport_receive_buf(struct tty_port *port, const unsigned char *cp, { struct serdev_controller *ctrl = port->client_data; struct serport *serport = serdev_controller_get_drvdata(ctrl); - unsigned long errors = 0; - unsigned int i; int ret; if (!test_bit(SERPORT_ACTIVE, &serport->flags)) return 0; - for (i = 0; fp && i < count; i++) { - switch (fp[i]) { - case TTY_BREAK: - if (test_bit(SERPORT_NOTIFY_BREAK, &serport->flags)) - __set_bit(SERDEV_ERROR_BREAK, &errors); - break; - - case TTY_FRAME: - if (test_bit(SERPORT_NOTIFY_FRAME, &serport->flags)) - __set_bit(SERDEV_ERROR_FRAME, &errors); - break; - - case TTY_PARITY: - if (test_bit(SERPORT_NOTIFY_PARITY, &serport->flags)) - __set_bit(SERDEV_ERROR_PARITY, &errors); - break; - - case TTY_OVERRUN: - if (test_bit(SERPORT_NOTIFY_OVERRUN, &serport->flags)) - __set_bit(SERDEV_ERROR_OVERRUN, &errors); - break; - } - } - if (errors) - serdev_controller_error(ctrl, errors); - ret = serdev_controller_receive_buf(ctrl, cp, count); dev_WARN_ONCE(&ctrl->dev, ret < 0 || ret > count, @@ -213,21 +180,6 @@ static unsigned int ttyport_set_baudrate(struct serdev_controller *ctrl, unsigne return ktermios.c_ospeed; } -static void ttyport_set_error_mask(struct serdev_controller *ctrl, - unsigned long m) -{ - struct serport *sp = serdev_controller_get_drvdata(ctrl); - - assign_bit(SERPORT_NOTIFY_BREAK, &sp->flags, - m & BIT(SERDEV_ERROR_BREAK)); - assign_bit(SERPORT_NOTIFY_FRAME, &sp->flags, - m & BIT(SERDEV_ERROR_FRAME)); - assign_bit(SERPORT_NOTIFY_PARITY, &sp->flags, - m & BIT(SERDEV_ERROR_PARITY)); - assign_bit(SERPORT_NOTIFY_OVERRUN, &sp->flags, - m & BIT(SERDEV_ERROR_OVERRUN)); -} - static void ttyport_set_flow_control(struct serdev_controller *ctrl, bool enable) { struct serport *serport = serdev_controller_get_drvdata(ctrl); @@ -301,7 +253,6 @@ static const struct serdev_controller_ops ctrl_ops = { .write_room = ttyport_write_room, .open = ttyport_open, .close = ttyport_close, - .set_error_mask = ttyport_set_error_mask, .set_flow_control = ttyport_set_flow_control, .set_parity = ttyport_set_parity, .set_baudrate = ttyport_set_baudrate, -- cgit From 0e479b460e342c5fe138391b29d7bfa0a6204af2 Mon Sep 17 00:00:00 2001 From: Lad Prabhakar Date: Wed, 5 Jan 2022 18:07:03 +0000 Subject: serial: 8250_bcm7271: Fix return error code in case of dma_alloc_coherent() failure In case of dma_alloc_coherent() failure return -ENOMEM instead of returning -EINVAL. Reported-by: Andy Shevchenko Reviewed-by: Andy Shevchenko Acked-by: Florian Fainelli Signed-off-by: Lad Prabhakar Link: https://lore.kernel.org/r/20220105180704.8989-1-prabhakar.mahadev-lad.rj@bp.renesas.com Signed-off-by: Greg Kroah-Hartman --- drivers/tty/serial/8250/8250_bcm7271.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'drivers/tty') diff --git a/drivers/tty/serial/8250/8250_bcm7271.c b/drivers/tty/serial/8250/8250_bcm7271.c index cc60a7874e8b..9b878d023dac 100644 --- a/drivers/tty/serial/8250/8250_bcm7271.c +++ b/drivers/tty/serial/8250/8250_bcm7271.c @@ -1075,7 +1075,7 @@ static int brcmuart_probe(struct platform_device *pdev) priv->rx_size, &priv->rx_addr, GFP_KERNEL); if (!priv->rx_bufs) { - ret = -EINVAL; + ret = -ENOMEM; goto err; } priv->tx_size = UART_XMIT_SIZE; @@ -1083,7 +1083,7 @@ static int brcmuart_probe(struct platform_device *pdev) priv->tx_size, &priv->tx_addr, GFP_KERNEL); if (!priv->tx_buf) { - ret = -EINVAL; + ret = -ENOMEM; goto err; } } -- cgit From 556172fabd226ba14b70c1740d0826a4717473dc Mon Sep 17 00:00:00 2001 From: Alyssa Ross Date: Tue, 4 Jan 2022 13:10:28 +0000 Subject: serial: liteuart: fix MODULE_ALIAS modprobe can't handle spaces in aliases. Fixes: 1da81e5562fa ("drivers/tty/serial: add LiteUART driver") Signed-off-by: Alyssa Ross Link: https://lore.kernel.org/r/20220104131030.1674733-1-hi@alyssa.is Signed-off-by: Greg Kroah-Hartman --- drivers/tty/serial/liteuart.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers/tty') diff --git a/drivers/tty/serial/liteuart.c b/drivers/tty/serial/liteuart.c index 2941659e5274..7f74bf7bdcff 100644 --- a/drivers/tty/serial/liteuart.c +++ b/drivers/tty/serial/liteuart.c @@ -436,4 +436,4 @@ module_exit(liteuart_exit); MODULE_AUTHOR("Antmicro "); MODULE_DESCRIPTION("LiteUART serial driver"); MODULE_LICENSE("GPL v2"); -MODULE_ALIAS("platform: liteuart"); +MODULE_ALIAS("platform:liteuart"); -- cgit From 08a0c6dff91c965e39905cf200d22db989203ccb Mon Sep 17 00:00:00 2001 From: Lukas Wunner Date: Sun, 2 Jan 2022 18:42:44 +0100 Subject: serial: pl010: Drop CR register reset on set_termios pl010_set_termios() briefly resets the CR register to zero. Where does this register write come from? The PL010 driver's IRQ handler ambauart_int() originally modified the CR register without holding the port spinlock. ambauart_set_termios() also modified that register. To prevent concurrent read-modify-writes by the IRQ handler and to prevent transmission while changing baudrate, ambauart_set_termios() had to disable interrupts. That is achieved by writing zero to the CR register. However in 2004 the PL010 driver was amended to acquire the port spinlock in the IRQ handler, obviating the need to disable interrupts in ->set_termios(): https://git.kernel.org/history/history/c/157c0342e591 That rendered the CR register write obsolete. Drop it. Cc: Russell King Signed-off-by: Lukas Wunner Link: https://lore.kernel.org/r/fcaff16e5b1abb4cc3da5a2879ac13f278b99ed0.1641128728.git.lukas@wunner.de Signed-off-by: Greg Kroah-Hartman --- drivers/tty/serial/amba-pl010.c | 3 --- 1 file changed, 3 deletions(-) (limited to 'drivers/tty') diff --git a/drivers/tty/serial/amba-pl010.c b/drivers/tty/serial/amba-pl010.c index e744b953ca34..47654073123d 100644 --- a/drivers/tty/serial/amba-pl010.c +++ b/drivers/tty/serial/amba-pl010.c @@ -446,14 +446,11 @@ pl010_set_termios(struct uart_port *port, struct ktermios *termios, if ((termios->c_cflag & CREAD) == 0) uap->port.ignore_status_mask |= UART_DUMMY_RSR_RX; - /* first, disable everything */ old_cr = readb(uap->port.membase + UART010_CR) & ~UART010_CR_MSIE; if (UART_ENABLE_MS(port, termios->c_cflag)) old_cr |= UART010_CR_MSIE; - writel(0, uap->port.membase + UART010_CR); - /* Set baud rate */ quot -= 1; writel((quot & 0xf00) >> 8, uap->port.membase + UART010_LCRM); -- cgit From e368cc656fd6d0075f1c3ab9676e2001451e3e04 Mon Sep 17 00:00:00 2001 From: Lukas Wunner Date: Sun, 2 Jan 2022 18:45:44 +0100 Subject: serial: pl011: Drop CR register reset on set_termios pl011_set_termios() briefly resets the CR register to zero, thereby glitching DTR/RTS signals. With rs485 this may result in the bus being occupied for no reason. Where does this register write originate from? The PL011 driver was forked from the PL010 driver in 2004: https://git.kernel.org/history/history/c/157c0342e591 Until this commit, the PL010 driver's IRQ handler ambauart_int() modified the CR register without holding the port spinlock. ambauart_set_termios() also modified that register. To prevent concurrent read-modify-writes by the IRQ handler and to prevent transmission while changing baudrate, ambauart_set_termios() had to disable interrupts. On the PL010, that is achieved by writing zero to the CR register. However, on the PL011, interrupts are disabled in the IMSC register, not in the CR register. Additionally, the commit amended both the PL010 and PL011 driver to acquire the port spinlock in the IRQ handler, obviating the need to disable interrupts in ->set_termios(). So the CR register write is obsolete for two reasons. Drop it. Cc: Russell King Signed-off-by: Lukas Wunner Link: https://lore.kernel.org/r/f49f945375f5ccb979893c49f1129f51651ac738.1641129062.git.lukas@wunner.de Signed-off-by: Greg Kroah-Hartman --- drivers/tty/serial/amba-pl011.c | 2 -- 1 file changed, 2 deletions(-) (limited to 'drivers/tty') diff --git a/drivers/tty/serial/amba-pl011.c b/drivers/tty/serial/amba-pl011.c index dbc4b3e2b19c..7ca4f0da8309 100644 --- a/drivers/tty/serial/amba-pl011.c +++ b/drivers/tty/serial/amba-pl011.c @@ -2073,9 +2073,7 @@ pl011_set_termios(struct uart_port *port, struct ktermios *termios, if (port->rs485.flags & SER_RS485_ENABLED) termios->c_cflag &= ~CRTSCTS; - /* first, disable everything */ old_cr = pl011_read(uap, REG_CR); - pl011_write(0, uap, REG_CR); if (termios->c_cflag & CRTSCTS) { if (old_cr & UART011_CR_RTS) -- cgit From 49a80424e3ec23ee2748f360348e167d5c748256 Mon Sep 17 00:00:00 2001 From: Lukas Wunner Date: Sun, 2 Jan 2022 18:49:44 +0100 Subject: serial: pl011: Drop redundant DTR/RTS preservation on close/open Commit d8d8ffa47783 ("amba-pl011: do not disable RTS during shutdown") amended the PL011 serial driver to leave DTR/RTS polarity untouched on tty close. That change made sense. But the commit also added code to save DTR/RTS state to an internal variable on tty close and restore it on tty open. That part of the commit makes less sense: The driver has no ->pm() callback, so the uart remains powered after tty close and automatically preserves register state, including DTR/RTS. Saving and restoring registers isn't the job of the ->startup() and ->shutdown() callbacks anyway. Rather, it should happen in ->pm(). Additionally, after pl011_startup() restores the state, the serial core overrides it in uart_port_dtr_rts() if a baud rate has been set: tty_port_open() uart_port_activate() uart_startup() uart_port_startup() pl011_startup() # restores DTR/RTS from uap->old_cr tty_port_block_til_ready() tty_port_raise_dtr_rts # if (C_BAUD(tty)) uart_dtr_rts() uart_port_dtr_rts() # raises DTR/RTS The serial core also overrides DTR/RTS on tty close in uart_shutdown() if C_HUPCL(tty) is set. So a user-defined DTR/RTS polarity won't survive a close/open cycle anyway, unless the user has set the baud rate to zero and disabled hupcl on the tty. Bottom line is, the code to save and restore DTR/RTS has no effect. Remove it. Cc: Linus Walleij Cc: Russell King Signed-off-by: Lukas Wunner Link: https://lore.kernel.org/r/e22089ab49e6e78822c50c8c4db46bf3ee885623.1641129328.git.lukas@wunner.de Signed-off-by: Greg Kroah-Hartman --- drivers/tty/serial/amba-pl011.c | 7 ++----- 1 file changed, 2 insertions(+), 5 deletions(-) (limited to 'drivers/tty') diff --git a/drivers/tty/serial/amba-pl011.c b/drivers/tty/serial/amba-pl011.c index 7ca4f0da8309..1f1df46242f9 100644 --- a/drivers/tty/serial/amba-pl011.c +++ b/drivers/tty/serial/amba-pl011.c @@ -230,7 +230,6 @@ struct uart_amba_port { unsigned int im; /* interrupt mask */ unsigned int old_status; unsigned int fifosize; /* vendor-specific */ - unsigned int old_cr; /* state during shutdown */ unsigned int fixed_baud; /* vendor-set fixed baud rate */ char type[12]; bool rs485_tx_started; @@ -1805,8 +1804,8 @@ static int pl011_startup(struct uart_port *port) spin_lock_irq(&uap->port.lock); - /* restore RTS and DTR */ - cr = uap->old_cr & (UART011_CR_RTS | UART011_CR_DTR); + cr = pl011_read(uap, REG_CR); + cr &= UART011_CR_RTS | UART011_CR_DTR; cr |= UART01x_CR_UARTEN | UART011_CR_RXE; if (port->rs485.flags & SER_RS485_ENABLED) { @@ -1883,7 +1882,6 @@ static void pl011_disable_uart(struct uart_amba_port *uap) uap->port.status &= ~(UPSTAT_AUTOCTS | UPSTAT_AUTORTS); spin_lock_irq(&uap->port.lock); cr = pl011_read(uap, REG_CR); - uap->old_cr = cr; cr &= UART011_CR_RTS | UART011_CR_DTR; cr |= UART01x_CR_UARTEN | UART011_CR_TXE; pl011_write(cr, uap, REG_CR); @@ -2699,7 +2697,6 @@ static int pl011_setup_port(struct device *dev, struct uart_amba_port *uap, index = pl011_probe_dt_alias(index, dev); - uap->old_cr = 0; uap->port.dev = dev; uap->port.mapbase = mmiobase->start; uap->port.membase = base; -- cgit From 56a23f9319e86e1d62a109896e2c7e52c414e67d Mon Sep 17 00:00:00 2001 From: Valentin Caron Date: Tue, 4 Jan 2022 19:24:42 +0100 Subject: serial: stm32: move tx dma terminate DMA to shutdown Terminate DMA transaction and clear CR3_DMAT when shutdown is requested, instead of when remove is requested. If DMA transfer is not stopped in shutdown ops, driver will fail to start a new DMA transfer after next startup ops. Fixes: 3489187204eb ("serial: stm32: adding dma support") Signed-off-by: Erwan Le Ray Signed-off-by: Valentin Caron Link: https://lore.kernel.org/r/20220104182445.4195-2-valentin.caron@foss.st.com Signed-off-by: Greg Kroah-Hartman --- drivers/tty/serial/stm32-usart.c | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) (limited to 'drivers/tty') diff --git a/drivers/tty/serial/stm32-usart.c b/drivers/tty/serial/stm32-usart.c index 3244e7f6818c..6cfc3bec6749 100644 --- a/drivers/tty/serial/stm32-usart.c +++ b/drivers/tty/serial/stm32-usart.c @@ -883,6 +883,11 @@ static void stm32_usart_shutdown(struct uart_port *port) u32 val, isr; int ret; + if (stm32_port->tx_dma_busy) { + dmaengine_terminate_async(stm32_port->tx_ch); + stm32_usart_clr_bits(port, ofs->cr3, USART_CR3_DMAT); + } + /* Disable modem control interrupts */ stm32_usart_disable_ms(port); @@ -1570,7 +1575,6 @@ static int stm32_usart_serial_remove(struct platform_device *pdev) writel_relaxed(cr3, port->membase + ofs->cr3); if (stm32_port->tx_ch) { - dmaengine_terminate_async(stm32_port->tx_ch); stm32_usart_of_dma_tx_remove(stm32_port, pdev); dma_release_channel(stm32_port->tx_ch); } -- cgit From 9a135f16d228857c5c1212a58050196883343d1e Mon Sep 17 00:00:00 2001 From: Valentin Caron Date: Tue, 4 Jan 2022 19:24:43 +0100 Subject: serial: stm32: rework TX DMA state condition TX DMA state condition is handled by tx_dma_busy boolean. This boolean is set when dma descriptor is requested and reset when dma channel is stopped (dma_terminate). In stm32_usart_serial_remove(), stm32_usart_stop_tx() and stm32_usart_transmit_chars_dma() fallback error case, DMA channel is stopped but tx_dma_busy is not handled. Rework the driver by using two new functions to solve this issue: - stm32_usart_tx_dma_started return true if DMA TX have a descriptor. - stm32_usart_tx_dma_enabled return true if DMAT bit is set. stm32_usart_tx_dma_started uses tx_dma_busy flag to prevent dual DMA transaction at the same time. This flag is set when a DMA transaction begins and is unset when dmaengine_terminate_async function is called. A new DMA transaction cannot be created if this flag is set. Create a new function "stm32_usart_tx_dma_terminate" to be sure the flag is unset after each call of dmaengine_terminate_async. Signed-off-by: Erwan Le Ray Signed-off-by: Valentin Caron Link: https://lore.kernel.org/r/20220104182445.4195-3-valentin.caron@foss.st.com Signed-off-by: Greg Kroah-Hartman --- drivers/tty/serial/stm32-usart.c | 66 +++++++++++++++++++++++++++++----------- drivers/tty/serial/stm32-usart.h | 2 +- 2 files changed, 49 insertions(+), 19 deletions(-) (limited to 'drivers/tty') diff --git a/drivers/tty/serial/stm32-usart.c b/drivers/tty/serial/stm32-usart.c index 6cfc3bec6749..52755a576bc2 100644 --- a/drivers/tty/serial/stm32-usart.c +++ b/drivers/tty/serial/stm32-usart.c @@ -365,6 +365,31 @@ static unsigned int stm32_usart_receive_chars(struct uart_port *port, bool force return size; } +static void stm32_usart_tx_dma_terminate(struct stm32_port *stm32_port) +{ + dmaengine_terminate_async(stm32_port->tx_ch); + stm32_port->tx_dma_busy = false; +} + +static bool stm32_usart_tx_dma_started(struct stm32_port *stm32_port) +{ + /* + * We cannot use the function "dmaengine_tx_status" to know the + * status of DMA. This function does not show if the "dma complete" + * callback of the DMA transaction has been called. So we prefer + * to use "tx_dma_busy" flag to prevent dual DMA transaction at the + * same time. + */ + return stm32_port->tx_dma_busy; +} + +static bool stm32_usart_tx_dma_enabled(struct stm32_port *stm32_port) +{ + const struct stm32_usart_offsets *ofs = &stm32_port->info->ofs; + + return !!(readl_relaxed(stm32_port->port.membase + ofs->cr3) & USART_CR3_DMAT); +} + static void stm32_usart_tx_dma_complete(void *arg) { struct uart_port *port = arg; @@ -372,9 +397,8 @@ static void stm32_usart_tx_dma_complete(void *arg) const struct stm32_usart_offsets *ofs = &stm32port->info->ofs; unsigned long flags; - dmaengine_terminate_async(stm32port->tx_ch); stm32_usart_clr_bits(port, ofs->cr3, USART_CR3_DMAT); - stm32port->tx_dma_busy = false; + stm32_usart_tx_dma_terminate(stm32port); /* Let's see if we have pending data to send */ spin_lock_irqsave(&port->lock, flags); @@ -428,10 +452,8 @@ static void stm32_usart_transmit_chars_pio(struct uart_port *port) const struct stm32_usart_offsets *ofs = &stm32_port->info->ofs; struct circ_buf *xmit = &port->state->xmit; - if (stm32_port->tx_dma_busy) { + if (stm32_usart_tx_dma_enabled(stm32_port)) stm32_usart_clr_bits(port, ofs->cr3, USART_CR3_DMAT); - stm32_port->tx_dma_busy = false; - } while (!uart_circ_empty(xmit)) { /* Check that TDR is empty before filling FIFO */ @@ -457,10 +479,11 @@ static void stm32_usart_transmit_chars_dma(struct uart_port *port) struct dma_async_tx_descriptor *desc = NULL; unsigned int count, i; - if (stm32port->tx_dma_busy) + if (stm32_usart_tx_dma_started(stm32port)) { + if (!stm32_usart_tx_dma_enabled(stm32port)) + stm32_usart_set_bits(port, ofs->cr3, USART_CR3_DMAT); return; - - stm32port->tx_dma_busy = true; + } count = uart_circ_chars_pending(xmit); @@ -491,13 +514,21 @@ static void stm32_usart_transmit_chars_dma(struct uart_port *port) if (!desc) goto fallback_err; + /* + * Set "tx_dma_busy" flag. This flag will be released when + * dmaengine_terminate_async will be called. This flag helps + * transmit_chars_dma not to start another DMA transaction + * if the callback of the previous is not yet called. + */ + stm32port->tx_dma_busy = true; + desc->callback = stm32_usart_tx_dma_complete; desc->callback_param = port; /* Push current DMA TX transaction in the pending queue */ if (dma_submit_error(dmaengine_submit(desc))) { /* dma no yet started, safe to free resources */ - dmaengine_terminate_async(stm32port->tx_ch); + stm32_usart_tx_dma_terminate(stm32port); goto fallback_err; } @@ -522,12 +553,13 @@ static void stm32_usart_transmit_chars(struct uart_port *port) struct circ_buf *xmit = &port->state->xmit; if (port->x_char) { - if (stm32_port->tx_dma_busy) + if (stm32_usart_tx_dma_started(stm32_port) && + stm32_usart_tx_dma_enabled(stm32_port)) stm32_usart_clr_bits(port, ofs->cr3, USART_CR3_DMAT); writel_relaxed(port->x_char, port->membase + ofs->tdr); port->x_char = 0; port->icount.tx++; - if (stm32_port->tx_dma_busy) + if (stm32_usart_tx_dma_started(stm32_port)) stm32_usart_set_bits(port, ofs->cr3, USART_CR3_DMAT); return; } @@ -719,9 +751,8 @@ static void stm32_usart_flush_buffer(struct uart_port *port) const struct stm32_usart_offsets *ofs = &stm32_port->info->ofs; if (stm32_port->tx_ch) { - dmaengine_terminate_async(stm32_port->tx_ch); + stm32_usart_tx_dma_terminate(stm32_port); stm32_usart_clr_bits(port, ofs->cr3, USART_CR3_DMAT); - stm32_port->tx_dma_busy = false; } } @@ -883,10 +914,11 @@ static void stm32_usart_shutdown(struct uart_port *port) u32 val, isr; int ret; - if (stm32_port->tx_dma_busy) { - dmaengine_terminate_async(stm32_port->tx_ch); + if (stm32_usart_tx_dma_enabled(stm32_port)) stm32_usart_clr_bits(port, ofs->cr3, USART_CR3_DMAT); - } + + if (stm32_usart_tx_dma_started(stm32_port)) + stm32_usart_tx_dma_terminate(stm32_port); /* Disable modem control interrupts */ stm32_usart_disable_ms(port); @@ -1424,8 +1456,6 @@ static int stm32_usart_of_dma_tx_probe(struct stm32_port *stm32port, struct dma_slave_config config; int ret; - stm32port->tx_dma_busy = false; - stm32port->tx_buf = dma_alloc_coherent(dev, TX_BUF_L, &stm32port->tx_dma_buf, GFP_KERNEL); diff --git a/drivers/tty/serial/stm32-usart.h b/drivers/tty/serial/stm32-usart.h index e23916bfbb60..feab952aec16 100644 --- a/drivers/tty/serial/stm32-usart.h +++ b/drivers/tty/serial/stm32-usart.h @@ -264,7 +264,7 @@ struct stm32_port { u32 cr1_irq; /* USART_CR1_RXNEIE or RTOIE */ u32 cr3_irq; /* USART_CR3_RXFTIE */ int last_res; - bool tx_dma_busy; /* dma tx busy */ + bool tx_dma_busy; /* dma tx transaction in progress */ bool throttled; /* port throttled */ bool hw_flow_control; bool swap; /* swap RX & TX pins */ -- cgit From 2a3bcfe03725472607110507b6860d823e0deb41 Mon Sep 17 00:00:00 2001 From: Valentin Caron Date: Tue, 4 Jan 2022 19:24:44 +0100 Subject: serial: stm32: fix flow control transfer in DMA mode If flow control is enabled, framework will call stop_tx to pause transfer and then call start_tx to resume transfer. Clear USART_CR3_DMAT bit in stop_tx ops to pause DMA transfer. Signed-off-by: Erwan Le Ray Signed-off-by: Valentin Caron Link: https://lore.kernel.org/r/20220104182445.4195-4-valentin.caron@foss.st.com Signed-off-by: Greg Kroah-Hartman --- drivers/tty/serial/stm32-usart.c | 3 +++ 1 file changed, 3 insertions(+) (limited to 'drivers/tty') diff --git a/drivers/tty/serial/stm32-usart.c b/drivers/tty/serial/stm32-usart.c index 52755a576bc2..788e002688f2 100644 --- a/drivers/tty/serial/stm32-usart.c +++ b/drivers/tty/serial/stm32-usart.c @@ -707,8 +707,11 @@ static void stm32_usart_stop_tx(struct uart_port *port) { struct stm32_port *stm32_port = to_stm32_port(port); struct serial_rs485 *rs485conf = &port->rs485; + const struct stm32_usart_offsets *ofs = &stm32_port->info->ofs; stm32_usart_tx_interrupt_disable(port); + if (stm32_usart_tx_dma_started(stm32_port) && stm32_usart_tx_dma_enabled(stm32_port)) + stm32_usart_clr_bits(port, ofs->cr3, USART_CR3_DMAT); if (rs485conf->flags & SER_RS485_ENABLED) { if (rs485conf->flags & SER_RS485_RTS_ON_SEND) { -- cgit From 195437d14fb424a2ee50d51441181f16fd549789 Mon Sep 17 00:00:00 2001 From: Valentin Caron Date: Tue, 4 Jan 2022 19:24:45 +0100 Subject: serial: stm32: correct loop for dma error handling In this error handling, "transmit_chars_dma" function will call "transmit_chars_pio" once per characters. But "transmit_chars_pio" will continue to send characters while xmit buffer is not empty. Remove this useless loop, one call is sufficient. Signed-off-by: Valentin Caron Link: https://lore.kernel.org/r/20220104182445.4195-5-valentin.caron@foss.st.com Signed-off-by: Greg Kroah-Hartman --- drivers/tty/serial/stm32-usart.c | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) (limited to 'drivers/tty') diff --git a/drivers/tty/serial/stm32-usart.c b/drivers/tty/serial/stm32-usart.c index 788e002688f2..1f89ab0e49ac 100644 --- a/drivers/tty/serial/stm32-usart.c +++ b/drivers/tty/serial/stm32-usart.c @@ -477,7 +477,7 @@ static void stm32_usart_transmit_chars_dma(struct uart_port *port) const struct stm32_usart_offsets *ofs = &stm32port->info->ofs; struct circ_buf *xmit = &port->state->xmit; struct dma_async_tx_descriptor *desc = NULL; - unsigned int count, i; + unsigned int count; if (stm32_usart_tx_dma_started(stm32port)) { if (!stm32_usart_tx_dma_enabled(stm32port)) @@ -542,8 +542,7 @@ static void stm32_usart_transmit_chars_dma(struct uart_port *port) return; fallback_err: - for (i = count; i > 0; i--) - stm32_usart_transmit_chars_pio(port); + stm32_usart_transmit_chars_pio(port); } static void stm32_usart_transmit_chars(struct uart_port *port) -- cgit From 93a770b7e16772530196674ffc79bb13fa927dc6 Mon Sep 17 00:00:00 2001 From: Lukas Wunner Date: Sun, 2 Jan 2022 18:52:44 +0100 Subject: serial: core: Keep mctrl register state and cached copy in sync struct uart_port contains a cached copy of the Modem Control signals. It is used to skip register writes in uart_update_mctrl() if the new signal state equals the old signal state. It also avoids a register read to obtain the current state of output signals. When a uart_port is registered, uart_configure_port() changes signal state but neglects to keep the cached copy in sync. That may cause a subsequent register write to be incorrectly skipped. Fix it before it trips somebody up. This behavior has been present ever since the serial core was introduced in 2002: https://git.kernel.org/history/history/c/33c0d1b0c3eb So far it was never an issue because the cached copy is initialized to 0 by kzalloc() and when uart_configure_port() is executed, at most DTR has been set by uart_set_options() or sunsu_console_setup(). Therefore, a stable designation seems unnecessary. Signed-off-by: Lukas Wunner Link: https://lore.kernel.org/r/bceeaba030b028ed810272d55d5fc6f3656ddddb.1641129752.git.lukas@wunner.de Signed-off-by: Greg Kroah-Hartman --- drivers/tty/serial/serial_core.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) (limited to 'drivers/tty') diff --git a/drivers/tty/serial/serial_core.c b/drivers/tty/serial/serial_core.c index 259f28ec6c8b..dc40c4155356 100644 --- a/drivers/tty/serial/serial_core.c +++ b/drivers/tty/serial/serial_core.c @@ -2389,7 +2389,8 @@ uart_configure_port(struct uart_driver *drv, struct uart_state *state, * We probably don't need a spinlock around this, but */ spin_lock_irqsave(&port->lock, flags); - port->ops->set_mctrl(port, port->mctrl & TIOCM_DTR); + port->mctrl &= TIOCM_DTR; + port->ops->set_mctrl(port, port->mctrl); spin_unlock_irqrestore(&port->lock, flags); /* -- cgit