From: Greg Kroah-Hartman Date: Wed, 2 Nov 2022 01:56:16 +0000 (+0100) Subject: 5.10-stable patches X-Git-Tag: v4.9.332~2 X-Git-Url: http://git.ipfire.org/?a=commitdiff_plain;h=ad590b8e343883c6b2b84d691736d488ad9c3852;p=thirdparty%2Fkernel%2Fstable-queue.git 5.10-stable patches added patches: serial-core-move-rs485-configuration-tasks-from-drivers-into-core.patch serial-deassert-transmit-enable-on-probe-in-driver-specific-way.patch --- diff --git a/queue-5.10/serial-core-move-rs485-configuration-tasks-from-drivers-into-core.patch b/queue-5.10/serial-core-move-rs485-configuration-tasks-from-drivers-into-core.patch new file mode 100644 index 00000000000..0157eaa4f42 --- /dev/null +++ b/queue-5.10/serial-core-move-rs485-configuration-tasks-from-drivers-into-core.patch @@ -0,0 +1,85 @@ +From 0ed12afa5655512ee418047fb3546d229df20aa1 Mon Sep 17 00:00:00 2001 +From: Lino Sanfilippo +Date: Sun, 10 Apr 2022 12:46:34 +0200 +Subject: serial: core: move RS485 configuration tasks from drivers into core + +From: Lino Sanfilippo + +commit 0ed12afa5655512ee418047fb3546d229df20aa1 upstream. + +Several drivers that support setting the RS485 configuration via userspace +implement one or more of the following tasks: + +- in case of an invalid RTS configuration (both RTS after send and RTS on + send set or both unset) fall back to enable RTS on send and disable RTS + after send + +- nullify the padding field of the returned serial_rs485 struct + +- copy the configuration into the uart port struct + +- limit RTS delays to 100 ms + +Move these tasks into the serial core to make them generic and to provide +a consistent behaviour among all drivers. + +Signed-off-by: Lino Sanfilippo +Link: https://lore.kernel.org/r/20220410104642.32195-2-LinoSanfilippo@gmx.de +Signed-off-by: Daisuke Mizobuchi +Signed-off-by: Dominique Martinet +Signed-off-by: Greg Kroah-Hartman +--- + drivers/tty/serial/serial_core.c | 33 +++++++++++++++++++++++++++++++++ + 1 file changed, 33 insertions(+) + +--- a/drivers/tty/serial/serial_core.c ++++ b/drivers/tty/serial/serial_core.c +@@ -42,6 +42,11 @@ static struct lock_class_key port_lock_k + + #define HIGH_BITS_OFFSET ((sizeof(long)-sizeof(int))*8) + ++/* ++ * Max time with active RTS before/after data is sent. ++ */ ++#define RS485_MAX_RTS_DELAY 100 /* msecs */ ++ + static void uart_change_speed(struct tty_struct *tty, struct uart_state *state, + struct ktermios *old_termios); + static void uart_wait_until_sent(struct tty_struct *tty, int timeout); +@@ -1326,8 +1331,36 @@ static int uart_set_rs485_config(struct + if (copy_from_user(&rs485, rs485_user, sizeof(*rs485_user))) + return -EFAULT; + ++ /* pick sane settings if the user hasn't */ ++ if (!(rs485.flags & SER_RS485_RTS_ON_SEND) == ++ !(rs485.flags & SER_RS485_RTS_AFTER_SEND)) { ++ dev_warn_ratelimited(port->dev, ++ "%s (%d): invalid RTS setting, using RTS_ON_SEND instead\n", ++ port->name, port->line); ++ rs485.flags |= SER_RS485_RTS_ON_SEND; ++ rs485.flags &= ~SER_RS485_RTS_AFTER_SEND; ++ } ++ ++ if (rs485.delay_rts_before_send > RS485_MAX_RTS_DELAY) { ++ rs485.delay_rts_before_send = RS485_MAX_RTS_DELAY; ++ dev_warn_ratelimited(port->dev, ++ "%s (%d): RTS delay before sending clamped to %u ms\n", ++ port->name, port->line, rs485.delay_rts_before_send); ++ } ++ ++ if (rs485.delay_rts_after_send > RS485_MAX_RTS_DELAY) { ++ rs485.delay_rts_after_send = RS485_MAX_RTS_DELAY; ++ dev_warn_ratelimited(port->dev, ++ "%s (%d): RTS delay after sending clamped to %u ms\n", ++ port->name, port->line, rs485.delay_rts_after_send); ++ } ++ /* Return clean padding area to userspace */ ++ memset(rs485.padding, 0, sizeof(rs485.padding)); ++ + spin_lock_irqsave(&port->lock, flags); + ret = port->rs485_config(port, &rs485); ++ if (!ret) ++ port->rs485 = rs485; + spin_unlock_irqrestore(&port->lock, flags); + if (ret) + return ret; diff --git a/queue-5.10/serial-deassert-transmit-enable-on-probe-in-driver-specific-way.patch b/queue-5.10/serial-deassert-transmit-enable-on-probe-in-driver-specific-way.patch new file mode 100644 index 00000000000..2305fa37326 --- /dev/null +++ b/queue-5.10/serial-deassert-transmit-enable-on-probe-in-driver-specific-way.patch @@ -0,0 +1,279 @@ +From 7c7f9bc986e698873b489c371a08f206979d06b7 Mon Sep 17 00:00:00 2001 +From: Lukas Wunner +Date: Thu, 22 Sep 2022 18:27:33 +0200 +Subject: serial: Deassert Transmit Enable on probe in driver-specific way +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit + +From: Lukas Wunner + +commit 7c7f9bc986e698873b489c371a08f206979d06b7 upstream. + +When a UART port is newly registered, uart_configure_port() seeks to +deassert RS485 Transmit Enable by setting the RTS bit in port->mctrl. +However a number of UART drivers interpret a set RTS bit as *assertion* +instead of deassertion: Affected drivers include those using +serial8250_em485_config() (except 8250_bcm2835aux.c) and some using +mctrl_gpio (e.g. imx.c). + +Since the interpretation of the RTS bit is driver-specific, it is not +suitable as a means to centrally deassert Transmit Enable in the serial +core. Instead, the serial core must call on drivers to deassert it in +their driver-specific way. One way to achieve that is to call +->rs485_config(). It implicitly deasserts Transmit Enable. + +So amend uart_configure_port() and uart_resume_port() to invoke +uart_rs485_config(). That allows removing calls to uart_rs485_config() +from drivers' ->probe() hooks and declaring the function static. + +Skip any invocation of ->set_mctrl() if RS485 is enabled. RS485 has no +hardware flow control, so the modem control lines are irrelevant and +need not be touched. When leaving RS485 mode, reset the modem control +lines to the state stored in port->mctrl. That way, UARTs which are +muxed between RS485 and RS232 transceivers drive the lines correctly +when switched to RS232. (serial8250_do_startup() historically raises +the OUT1 modem signal because otherwise interrupts are not signaled on +ancient PC UARTs, but I believe that no longer applies to modern, +RS485-capable UARTs and is thus safe to be skipped.) + +imx.c modifies port->mctrl whenever Transmit Enable is asserted and +deasserted. Stop it from doing that so port->mctrl reflects the RS232 +line state. + +8250_omap.c deasserts Transmit Enable on ->runtime_resume() by calling +->set_mctrl(). Because that is now a no-op in RS485 mode, amend the +function to call serial8250_em485_stop_tx(). + +fsl_lpuart.c retrieves and applies the RS485 device tree properties +after registering the UART port. Because applying now happens on +registration in uart_configure_port(), move retrieval of the properties +ahead of uart_add_one_port(). + +Link: https://lore.kernel.org/all/20220329085050.311408-1-matthias.schiffer@ew.tq-group.com/ +Link: https://lore.kernel.org/all/8f538a8903795f22f9acc94a9a31b03c9c4ccacb.camel@ginzinger.com/ +Fixes: d3b3404df318 ("serial: Fix incorrect rs485 polarity on uart open") +Cc: stable@vger.kernel.org # v4.14+ +Reported-by: Matthias Schiffer +Reported-by: Roosen Henri +Tested-by: Matthias Schiffer +Reviewed-by: Ilpo Järvinen +Signed-off-by: Lukas Wunner +Link: https://lore.kernel.org/r/2de36eba3fbe11278d5002e4e501afe0ceaca039.1663863805.git.lukas@wunner.de +Signed-off-by: Daisuke Mizobuchi +Signed-off-by: Dominique Martinet +Signed-off-by: Greg Kroah-Hartman +--- + drivers/tty/serial/8250/8250_omap.c | 3 +++ + drivers/tty/serial/8250/8250_pci.c | 9 +-------- + drivers/tty/serial/8250/8250_port.c | 12 +++++++----- + drivers/tty/serial/fsl_lpuart.c | 8 +++----- + drivers/tty/serial/imx.c | 8 ++------ + drivers/tty/serial/serial_core.c | 30 +++++++++++++++++------------- + 6 files changed, 33 insertions(+), 37 deletions(-) + +--- a/drivers/tty/serial/8250/8250_omap.c ++++ b/drivers/tty/serial/8250/8250_omap.c +@@ -342,6 +342,9 @@ static void omap8250_restore_regs(struct + omap8250_update_mdr1(up, priv); + + up->port.ops->set_mctrl(&up->port, up->port.mctrl); ++ ++ if (up->port.rs485.flags & SER_RS485_ENABLED) ++ serial8250_em485_stop_tx(up); + } + + /* +--- a/drivers/tty/serial/8250/8250_pci.c ++++ b/drivers/tty/serial/8250/8250_pci.c +@@ -1531,7 +1531,6 @@ static int pci_fintek_init(struct pci_de + resource_size_t bar_data[3]; + u8 config_base; + struct serial_private *priv = pci_get_drvdata(dev); +- struct uart_8250_port *port; + + if (!(pci_resource_flags(dev, 5) & IORESOURCE_IO) || + !(pci_resource_flags(dev, 4) & IORESOURCE_IO) || +@@ -1578,13 +1577,7 @@ static int pci_fintek_init(struct pci_de + + pci_write_config_byte(dev, config_base + 0x06, dev->irq); + +- if (priv) { +- /* re-apply RS232/485 mode when +- * pciserial_resume_ports() +- */ +- port = serial8250_get_port(priv->line[i]); +- pci_fintek_rs485_config(&port->port, NULL); +- } else { ++ if (!priv) { + /* First init without port data + * force init to RS232 Mode + */ +--- a/drivers/tty/serial/8250/8250_port.c ++++ b/drivers/tty/serial/8250/8250_port.c +@@ -592,7 +592,7 @@ EXPORT_SYMBOL_GPL(serial8250_rpm_put); + static int serial8250_em485_init(struct uart_8250_port *p) + { + if (p->em485) +- return 0; ++ goto deassert_rts; + + p->em485 = kmalloc(sizeof(struct uart_8250_em485), GFP_ATOMIC); + if (!p->em485) +@@ -608,7 +608,9 @@ static int serial8250_em485_init(struct + p->em485->active_timer = NULL; + p->em485->tx_stopped = true; + +- p->rs485_stop_tx(p); ++deassert_rts: ++ if (p->em485->tx_stopped) ++ p->rs485_stop_tx(p); + + return 0; + } +@@ -2030,6 +2032,9 @@ EXPORT_SYMBOL_GPL(serial8250_do_set_mctr + + static void serial8250_set_mctrl(struct uart_port *port, unsigned int mctrl) + { ++ if (port->rs485.flags & SER_RS485_ENABLED) ++ return; ++ + if (port->set_mctrl) + port->set_mctrl(port, mctrl); + else +@@ -3161,9 +3166,6 @@ static void serial8250_config_port(struc + if (flags & UART_CONFIG_TYPE) + autoconfig(up); + +- if (port->rs485.flags & SER_RS485_ENABLED) +- port->rs485_config(port, &port->rs485); +- + /* if access method is AU, it is a 16550 with a quirk */ + if (port->type == PORT_16550A && port->iotype == UPIO_AU) + up->bugs |= UART_BUG_NOMSR; +--- a/drivers/tty/serial/fsl_lpuart.c ++++ b/drivers/tty/serial/fsl_lpuart.c +@@ -2669,10 +2669,6 @@ static int lpuart_probe(struct platform_ + if (ret) + goto failed_irq_request; + +- ret = uart_add_one_port(&lpuart_reg, &sport->port); +- if (ret) +- goto failed_attach_port; +- + ret = uart_get_rs485_mode(&sport->port); + if (ret) + goto failed_get_rs485; +@@ -2684,7 +2680,9 @@ static int lpuart_probe(struct platform_ + sport->port.rs485.delay_rts_after_send) + dev_err(&pdev->dev, "driver doesn't support RTS delays\n"); + +- sport->port.rs485_config(&sport->port, &sport->port.rs485); ++ ret = uart_add_one_port(&lpuart_reg, &sport->port); ++ if (ret) ++ goto failed_attach_port; + + return 0; + +--- a/drivers/tty/serial/imx.c ++++ b/drivers/tty/serial/imx.c +@@ -398,8 +398,7 @@ static void imx_uart_rts_active(struct i + { + *ucr2 &= ~(UCR2_CTSC | UCR2_CTS); + +- sport->port.mctrl |= TIOCM_RTS; +- mctrl_gpio_set(sport->gpios, sport->port.mctrl); ++ mctrl_gpio_set(sport->gpios, sport->port.mctrl | TIOCM_RTS); + } + + /* called with port.lock taken and irqs caller dependent */ +@@ -408,8 +407,7 @@ static void imx_uart_rts_inactive(struct + *ucr2 &= ~UCR2_CTSC; + *ucr2 |= UCR2_CTS; + +- sport->port.mctrl &= ~TIOCM_RTS; +- mctrl_gpio_set(sport->gpios, sport->port.mctrl); ++ mctrl_gpio_set(sport->gpios, sport->port.mctrl & ~TIOCM_RTS); + } + + static void start_hrtimer_ms(struct hrtimer *hrt, unsigned long msec) +@@ -2381,8 +2379,6 @@ static int imx_uart_probe(struct platfor + dev_err(&pdev->dev, + "low-active RTS not possible when receiver is off, enabling receiver\n"); + +- imx_uart_rs485_config(&sport->port, &sport->port.rs485); +- + /* Disable interrupts before requesting them */ + ucr1 = imx_uart_readl(sport, UCR1); + ucr1 &= ~(UCR1_ADEN | UCR1_TRDYEN | UCR1_IDEN | UCR1_RRDYEN | UCR1_RTSDEN); +--- a/drivers/tty/serial/serial_core.c ++++ b/drivers/tty/serial/serial_core.c +@@ -149,15 +149,10 @@ uart_update_mctrl(struct uart_port *port + unsigned long flags; + unsigned int old; + +- if (port->rs485.flags & SER_RS485_ENABLED) { +- set &= ~TIOCM_RTS; +- clear &= ~TIOCM_RTS; +- } +- + spin_lock_irqsave(&port->lock, flags); + old = port->mctrl; + port->mctrl = (old & ~clear) | set; +- if (old != port->mctrl) ++ if (old != port->mctrl && !(port->rs485.flags & SER_RS485_ENABLED)) + port->ops->set_mctrl(port, port->mctrl); + spin_unlock_irqrestore(&port->lock, flags); + } +@@ -1359,8 +1354,13 @@ static int uart_set_rs485_config(struct + + spin_lock_irqsave(&port->lock, flags); + ret = port->rs485_config(port, &rs485); +- if (!ret) ++ if (!ret) { + port->rs485 = rs485; ++ ++ /* Reset RTS and other mctrl lines when disabling RS485 */ ++ if (!(rs485.flags & SER_RS485_ENABLED)) ++ port->ops->set_mctrl(port, port->mctrl); ++ } + spin_unlock_irqrestore(&port->lock, flags); + if (ret) + return ret; +@@ -2335,7 +2335,8 @@ int uart_resume_port(struct uart_driver + + uart_change_pm(state, UART_PM_STATE_ON); + spin_lock_irq(&uport->lock); +- ops->set_mctrl(uport, 0); ++ if (!(uport->rs485.flags & SER_RS485_ENABLED)) ++ ops->set_mctrl(uport, 0); + spin_unlock_irq(&uport->lock); + if (console_suspend_enabled || !uart_console(uport)) { + /* Protected by port mutex for now */ +@@ -2346,7 +2347,10 @@ int uart_resume_port(struct uart_driver + if (tty) + uart_change_speed(tty, state, NULL); + spin_lock_irq(&uport->lock); +- ops->set_mctrl(uport, uport->mctrl); ++ if (!(uport->rs485.flags & SER_RS485_ENABLED)) ++ ops->set_mctrl(uport, uport->mctrl); ++ else ++ uport->rs485_config(uport, &uport->rs485); + ops->start_tx(uport); + spin_unlock_irq(&uport->lock); + tty_port_set_initialized(port, 1); +@@ -2444,10 +2448,10 @@ uart_configure_port(struct uart_driver * + */ + spin_lock_irqsave(&port->lock, flags); + port->mctrl &= TIOCM_DTR; +- if (port->rs485.flags & SER_RS485_ENABLED && +- !(port->rs485.flags & SER_RS485_RTS_AFTER_SEND)) +- port->mctrl |= TIOCM_RTS; +- port->ops->set_mctrl(port, port->mctrl); ++ if (!(port->rs485.flags & SER_RS485_ENABLED)) ++ port->ops->set_mctrl(port, port->mctrl); ++ else ++ port->rs485_config(port, &port->rs485); + spin_unlock_irqrestore(&port->lock, flags); + + /* diff --git a/queue-5.10/series b/queue-5.10/series index bbe799304ef..6a2a343ad3b 100644 --- a/queue-5.10/series +++ b/queue-5.10/series @@ -89,3 +89,5 @@ scsi-sd-revert-scsi-sd-remove-a-local-variable.patch arm64-mm-fix-__enable_mmu-for-new-tgran-range-values.patch arm64-kexec-test-page-size-support-with-new-tgran-range-values.patch can-rcar_canfd-rcar_canfd_handle_global_receive-fix-irq-storm-on-global-fifo-receive.patch +serial-core-move-rs485-configuration-tasks-from-drivers-into-core.patch +serial-deassert-transmit-enable-on-probe-in-driver-specific-way.patch