mirror of https://lore.kernel.org/lkml/
 help / color / mirror / Atom feed
From: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
To: Jiri Slaby <jirislaby@kernel.org>,
	Joshua Rogers <linux@joshua.hu>,  Chris Mason <mason@kernel.org>,
	Josef Bacik <josef@toxicpanda.com>
Cc: "Tony Lindgren" <tony@atomide.com>,
	"Rafael Gago Castano" <rgc@hms.se>,
	"Florian Fainelli" <f.fainelli@gmail.com>,
	"Ilpo Järvinen" <ilpo.jarvinen@linux.intel.com>,
	"Andy Shevchenko" <andriy.shevchenko@linux.intel.com>,
	"Peter Hurley" <peter@hurleysoftware.com>,
	"Heikki Krogerus" <heikki.krogerus@linux.intel.com>,
	"Crescent Hsieh" <crescentcy.hsieh@moxa.com>,
	"Frank Li" <Frank.Li@nxp.com>, "Sherry Sun" <sherry.sun@nxp.com>,
	"Sascha Hauer" <s.hauer@pengutronix.de>,
	"Pengutronix Kernel Team" <kernel@pengutronix.de>,
	"Fabio Estevam" <festevam@gmail.com>,
	"Manivannan Sadhasivam" <mani@kernel.org>,
	"Olof Johansson" <olof@lixom.net>,
	"Andreas Färber" <afaerber@suse.de>,
	"Arnd Bergmann" <arnd@arndb.de>,
	"Krzysztof Kozlowski" <krzk@kernel.org>,
	"Peter Griffin" <peter.griffin@linaro.org>,
	"Alim Akhtar" <alim.akhtar@samsung.com>,
	"Robert Baldyga" <r.baldyga@samsung.com>,
	"Thomas Abraham" <thomas.abraham@linaro.org>,
	"Kukjin Kim" <kgene.kim@samsung.com>,
	"Patrice Chotard" <patrice.chotard@foss.st.com>,
	"Srinivas Kandagatla" <srini@kernel.org>,
	"Maxime Coquelin" <mcoquelin.stm32@gmail.com>,
	"Alexandre Torgue" <alexandre.torgue@foss.st.com>,
	"Andy Shevchenko" <andy.shevchenko@gmail.com>,
	"Vladimir Zapolskiy" <vladimir_zapolskiy@mentor.com>,
	"Al Cooper" <alcooperx@gmail.com>,
	linux-kernel@vger.kernel.org, linux-serial@vger.kernel.org,
	"Greg Kroah-Hartman" <gregkh@linuxfoundation.org>,
	stable <stable@kernel.org>,
	"Andy Shevchenko" <andriy.shevchenko@intel.com>,
	"Hugo Villeneuve" <hvilleneuve@dimonoff.com>,
	"Uwe Kleine-König (The Capable Hub)"
	<u.kleine-koenig@baylibre.com>,
	"Tate Whiteberg" <whiteberg@arista.com>,
	"Christian Marangi" <ansuelsmth@gmail.com>,
	"John Ogness" <john.ogness@linutronix.de>,
	"Fushuai Wang" <wangfushuai@baidu.com>
Subject: [PATCH 03/24] serial: 8250: don't wait for the em485 timers locked
Date: Tue, 27 Oct 2026 12:06:29 +0100	[thread overview]
Message-ID: <20261027-tty-llm-v1-3-99b0202ae546@linuxfoundation.org> (raw)
In-Reply-To: <20261027-tty-llm-v1-0-99b0202ae546@linuxfoundation.org>

From: Josef Bacik <josef@toxicpanda.com>

serial8250_em485_destroy() is called with the port lock held and
interrupts off, from ->rs485_config() and from
serial8250_unregister_port().  It calls hrtimer_cancel(), which waits
for a handler which is running, and both handlers start by taking the
port lock:

  CPU0                                  CPU1
  ioctl(TIOCSRS485), rs485 off
  uart_set_rs485_config()
    uart_port_lock_irqsave()            serial8250_em485_handle_stop_tx()
    serial8250_em485_config()             uart_port_lock_irqsave()
      serial8250_em485_destroy()            spins
        hrtimer_cancel()
          spins

All it takes is to turn RS485 off right after the end of a transmission,
when the timer for delay_rts_after_send expires.

The handlers do nothing unless em485->active_timer points to their
timer, so it is enough to clear that pointer.  What cannot be done with
the lock held is to free the structure: hrtimer_try_to_cancel() fails
for a timer whose handler is running, even if it has been started again
in the meantime.  So keep the structure in the port when RS485 is turned
off, use it again when RS485 is turned on, and free it when the port is
unregistered, where the timers can be waited for without the lock.

A port on which RS485 emulation has been used once keeps the structure,
about 150 bytes, until it is unregistered.

Fixes: 6e0a5de2136b ("serial: 8250: Use hrtimers for rs485 delays")
Cc: stable <stable@kernel.org>
Cc: Jiri Slaby <jirislaby@kernel.org>
Cc: Andy Shevchenko <andriy.shevchenko@intel.com>
Cc: Hugo Villeneuve <hvilleneuve@dimonoff.com>
Cc: "Uwe Kleine-König (The Capable Hub)" <u.kleine-koenig@baylibre.com>
Cc: "Ilpo Järvinen" <ilpo.jarvinen@linux.intel.com>
Cc: Tate Whiteberg <whiteberg@arista.com>
Cc: Christian Marangi <ansuelsmth@gmail.com>
Cc: John Ogness <john.ogness@linutronix.de>
Cc: Crescent Hsieh <crescentcy.hsieh@moxa.com>
Cc: Fushuai Wang <wangfushuai@baidu.com>
Cc: Rafael Gago Castano <rgc@hms.se>
Signed-off-by: Josef Bacik <josef@toxicpanda.com>
Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
---
 drivers/tty/serial/8250/8250.h      |  1 +
 drivers/tty/serial/8250/8250_core.c |  5 +---
 drivers/tty/serial/8250/8250_port.c | 60 ++++++++++++++++++++++++++++++-------
 include/linux/serial_8250.h         |  1 +
 4 files changed, 52 insertions(+), 15 deletions(-)

diff --git a/drivers/tty/serial/8250/8250.h b/drivers/tty/serial/8250/8250.h
index 21ed9c41b751..82a3b8359643 100644
--- a/drivers/tty/serial/8250/8250.h
+++ b/drivers/tty/serial/8250/8250.h
@@ -235,6 +235,7 @@ int serial8250_em485_config(struct uart_port *port, struct ktermios *termios,
 void serial8250_em485_start_tx(struct uart_8250_port *p, bool toggle_ier);
 void serial8250_em485_stop_tx(struct uart_8250_port *p, bool toggle_ier);
 void serial8250_em485_destroy(struct uart_8250_port *p);
+void serial8250_em485_free(struct uart_8250_port *p);
 extern struct serial_rs485 serial8250_em485_supported;
 
 /* MCR <-> TIOCM conversion */
diff --git a/drivers/tty/serial/8250/8250_core.c b/drivers/tty/serial/8250/8250_core.c
index 42319843cb5b..0951d3e42e1f 100644
--- a/drivers/tty/serial/8250/8250_core.c
+++ b/drivers/tty/serial/8250/8250_core.c
@@ -947,10 +947,7 @@ void serial8250_unregister_port(struct uart_8250_port *uart)
 {
 	guard(mutex)(&serial_mutex);
 
-	if (uart->em485) {
-		guard(uart_port_lock_irqsave)(&uart->port);
-		serial8250_em485_destroy(uart);
-	}
+	serial8250_em485_free(uart);
 
 	uart_remove_one_port(&serial8250_reg, &uart->port);
 	if (serial8250_isa_devs) {
diff --git a/drivers/tty/serial/8250/8250_port.c b/drivers/tty/serial/8250/8250_port.c
index 36b2b0a2c05c..3d47f535d6f1 100644
--- a/drivers/tty/serial/8250/8250_port.c
+++ b/drivers/tty/serial/8250/8250_port.c
@@ -574,15 +574,22 @@ static int serial8250_em485_init(struct uart_8250_port *p)
 	if (p->em485)
 		goto deassert_rts;
 
-	p->em485 = kmalloc_obj(struct uart_8250_em485, GFP_ATOMIC);
-	if (!p->em485)
-		return -ENOMEM;
+	if (p->em485_idle) {
+		p->em485 = p->em485_idle;
+		p->em485_idle = NULL;
+	} else {
+		p->em485 = kmalloc_obj(struct uart_8250_em485, GFP_ATOMIC);
+		if (!p->em485)
+			return -ENOMEM;
 
-	hrtimer_setup(&p->em485->stop_tx_timer, &serial8250_em485_handle_stop_tx, CLOCK_MONOTONIC,
-		      HRTIMER_MODE_REL);
-	hrtimer_setup(&p->em485->start_tx_timer, &serial8250_em485_handle_start_tx, CLOCK_MONOTONIC,
-		      HRTIMER_MODE_REL);
-	p->em485->port = p;
+		hrtimer_setup(&p->em485->stop_tx_timer,
+			      &serial8250_em485_handle_stop_tx, CLOCK_MONOTONIC,
+			      HRTIMER_MODE_REL);
+		hrtimer_setup(&p->em485->start_tx_timer,
+			      &serial8250_em485_handle_start_tx, CLOCK_MONOTONIC,
+			      HRTIMER_MODE_REL);
+		p->em485->port = p;
+	}
 	p->em485->active_timer = NULL;
 	p->em485->tx_stopped = true;
 
@@ -604,6 +611,11 @@ static int serial8250_em485_init(struct uart_8250_port *p)
  *	The function is supposed to be called from .rs485_config callback
  *	or from any other callback protected with p->port.lock spinlock.
  *
+ *	The handlers of the timers take that lock, so they cannot be waited for
+ *	here. One which is running does nothing, as no timer is active any more.
+ *	The memory is kept for the next serial8250_em485_init() and freed by
+ *	serial8250_em485_free().
+ *
  *	See also serial8250_em485_init()
  */
 void serial8250_em485_destroy(struct uart_8250_port *p)
@@ -611,14 +623,40 @@ void serial8250_em485_destroy(struct uart_8250_port *p)
 	if (!p->em485)
 		return;
 
-	hrtimer_cancel(&p->em485->start_tx_timer);
-	hrtimer_cancel(&p->em485->stop_tx_timer);
+	hrtimer_try_to_cancel(&p->em485->start_tx_timer);
+	hrtimer_try_to_cancel(&p->em485->stop_tx_timer);
+	p->em485->active_timer = NULL;
 
-	kfree(p->em485);
+	p->em485_idle = p->em485;
 	p->em485 = NULL;
 }
 EXPORT_SYMBOL_GPL(serial8250_em485_destroy);
 
+/**
+ *	serial8250_em485_free() - release the rs485 emulation of a port
+ *	@p:	uart_8250_port port instance
+ *
+ *	Must be called without p->port.lock, as it waits for the timers.
+ */
+void serial8250_em485_free(struct uart_8250_port *p)
+{
+	struct uart_8250_em485 *em485;
+
+	scoped_guard(uart_port_lock_irqsave, &p->port) {
+		serial8250_em485_destroy(p);
+		em485 = p->em485_idle;
+		p->em485_idle = NULL;
+	}
+
+	if (!em485)
+		return;
+
+	hrtimer_cancel(&em485->start_tx_timer);
+	hrtimer_cancel(&em485->stop_tx_timer);
+	kfree(em485);
+}
+EXPORT_SYMBOL_GPL(serial8250_em485_free);
+
 struct serial_rs485 serial8250_em485_supported = {
 	.flags = SER_RS485_ENABLED | SER_RS485_RTS_ON_SEND | SER_RS485_RTS_AFTER_SEND |
 		 SER_RS485_TERMINATE_BUS | SER_RS485_RX_DURING_TX,
diff --git a/include/linux/serial_8250.h b/include/linux/serial_8250.h
index d91c0477be9d..0556bb722db4 100644
--- a/include/linux/serial_8250.h
+++ b/include/linux/serial_8250.h
@@ -173,6 +173,7 @@ struct uart_8250_port {
 	void			(*dl_write)(struct uart_8250_port *up, u32 value);
 
 	struct uart_8250_em485 *em485;
+	struct uart_8250_em485 *em485_idle;	/* kept while rs485 is off */
 	void			(*rs485_start_tx)(struct uart_8250_port *up, bool toggle_ier);
 	void			(*rs485_stop_tx)(struct uart_8250_port *up, bool toggle_ier);
 

-- 
2.56.0


  parent reply	other threads:[~2026-10-27 11:06 UTC|newest]

Thread overview: 57+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2026-10-27 11:06 [PATCH 00/24] tty/serial: a bunch of llm-found fixes Greg Kroah-Hartman
2026-10-27 11:06 ` [PATCH 01/24] vt: serialise the producers of the flip buffer Greg Kroah-Hartman
2026-10-27 11:06 ` [PATCH 02/24] serial: core: respect runtime PM when sending x_char Greg Kroah-Hartman
2026-10-27 11:06 ` Greg Kroah-Hartman [this message]
2026-10-27 11:39   ` [PATCH 03/24] serial: 8250: don't wait for the em485 timers locked Ilpo Järvinen
2026-10-27 11:06 ` [PATCH 04/24] serial: 8250: don't report a wakeup to a closed tty Greg Kroah-Hartman
2026-10-27 11:43   ` Ilpo Järvinen
2026-10-27 11:06 ` [PATCH 05/24] serial: 8250: clear subdriver state on port unregister Greg Kroah-Hartman
2026-10-27 11:16   ` Jiri Slaby
2026-10-27 15:28     ` James Hilliard
2026-10-27 11:06 ` [PATCH 06/24] serial: 8250: add bounds check for line array in setup_serial() Greg Kroah-Hartman
2026-10-27 11:57   ` Ilpo Järvinen
2026-10-27 11:06 ` [PATCH 07/24] serial: 8250: hold hash_mutex across irq_info lookup and linking Greg Kroah-Hartman
2026-10-27 12:00   ` Ilpo Järvinen
2026-10-27 11:06 ` [PATCH 08/24] serial: 8250: cancel overrun backoff work on port shutdown and unregister Greg Kroah-Hartman
2026-10-27 12:15   ` Ilpo Järvinen
2026-10-27 11:06 ` [PATCH 09/24] serial: 8250: 8250_bcm7271: fix DMA address truncation to 32 bits Greg Kroah-Hartman
2026-10-27 12:18   ` Ilpo Järvinen
2026-10-27 15:10   ` Andy Shevchenko
2026-10-27 16:41     ` Florian Fainelli
2026-10-27 17:14       ` Andy Shevchenko
2026-10-27 17:19         ` Florian Fainelli
2026-10-27 18:37           ` Arnd Bergmann
2026-10-27 11:06 ` [PATCH 10/24] serial: 8250: pericom: validate port offset against BAR length Greg Kroah-Hartman
2026-10-27 15:13   ` Andy Shevchenko
2026-10-27 11:06 ` [PATCH 11/24] serial: 8250: cap OxSemi Tornado UART count against BAR size Greg Kroah-Hartman
2026-10-27 11:23   ` Jiri Slaby
2026-10-27 11:33     ` Greg Kroah-Hartman
2026-10-27 12:24   ` Ilpo Järvinen
2026-10-27 14:29   ` Maciej W. Rozycki
2026-10-27 15:23     ` Andy Shevchenko
2026-10-27 21:13       ` Maciej W. Rozycki
2026-10-27 11:06 ` [PATCH 12/24] serial: 8250: dfl: add bounds check for device-provided regshift Greg Kroah-Hartman
2026-10-27 15:36   ` Andy Shevchenko
2026-10-27 11:06 ` [PATCH 13/24] serial: 8250: dfl: validate MMIO resource size and regshift Greg Kroah-Hartman
2026-10-27 12:30   ` Ilpo Järvinen
2026-10-27 15:38   ` Andy Shevchenko
2026-10-27 11:06 ` [PATCH 14/24] serial: 8250: ioc3: store registered line number in driver data Greg Kroah-Hartman
2026-10-27 12:38   ` Ilpo Järvinen
2026-10-27 13:10     ` Greg Kroah-Hartman
2026-10-27 11:06 ` [PATCH 15/24] serial: 8250: omap: acquire rx_dma_lock in DMA completion callback Greg Kroah-Hartman
2026-10-27 12:52   ` Ilpo Järvinen
2026-10-27 11:06 ` [PATCH 16/24] serial: 8250_lpss: don't divide by 0 above 6.25 Mbaud Greg Kroah-Hartman
2026-10-27 11:06 ` [PATCH 17/24] serial: 8250_mxpcie: handle hangup during break Greg Kroah-Hartman
2026-10-27 11:06 ` [PATCH 18/24] serial: fsl_lpuart: fix tty ref of wakeup event Greg Kroah-Hartman
2026-10-27 11:06 ` [PATCH 19/24] serial: imx: fix the tty reference of the " Greg Kroah-Hartman
2026-10-27 11:06 ` [PATCH 20/24] serial: rda: free the interrupt on shutdown Greg Kroah-Hartman
2026-10-27 12:38   ` Manivannan Sadhasivam
2026-10-27 11:06 ` [PATCH 21/24] serial: samsung: don't leak the tty on an RX IRQ Greg Kroah-Hartman
2026-10-27 11:06 ` [PATCH 22/24] serial: samsung: put the previous baud clock Greg Kroah-Hartman
2026-10-27 11:06 ` [PATCH 23/24] serial: st-asc: don't report a wakeup to a closed tty Greg Kroah-Hartman
2026-10-27 15:51   ` Andy Shevchenko
2026-10-27 11:06 ` [PATCH 24/24] serial: stm32: " Greg Kroah-Hartman
2026-10-27 13:02   ` Ilpo Järvinen
2026-10-27 15:06 ` [PATCH 00/24] tty/serial: a bunch of llm-found fixes Andy Shevchenko
2026-10-27 15:50   ` Greg Kroah-Hartman
2026-10-27 16:32     ` Andy Shevchenko

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=20261027-tty-llm-v1-3-99b0202ae546@linuxfoundation.org \
    --to=gregkh@linuxfoundation.org \
    --cc=Frank.Li@nxp.com \
    --cc=afaerber@suse.de \
    --cc=alcooperx@gmail.com \
    --cc=alexandre.torgue@foss.st.com \
    --cc=alim.akhtar@samsung.com \
    --cc=andriy.shevchenko@intel.com \
    --cc=andriy.shevchenko@linux.intel.com \
    --cc=andy.shevchenko@gmail.com \
    --cc=ansuelsmth@gmail.com \
    --cc=arnd@arndb.de \
    --cc=crescentcy.hsieh@moxa.com \
    --cc=f.fainelli@gmail.com \
    --cc=festevam@gmail.com \
    --cc=heikki.krogerus@linux.intel.com \
    --cc=hvilleneuve@dimonoff.com \
    --cc=ilpo.jarvinen@linux.intel.com \
    --cc=jirislaby@kernel.org \
    --cc=john.ogness@linutronix.de \
    --cc=josef@toxicpanda.com \
    --cc=kernel@pengutronix.de \
    --cc=kgene.kim@samsung.com \
    --cc=krzk@kernel.org \
    --cc=linux-kernel@vger.kernel.org \
    --cc=linux-serial@vger.kernel.org \
    --cc=linux@joshua.hu \
    --cc=mani@kernel.org \
    --cc=mason@kernel.org \
    --cc=mcoquelin.stm32@gmail.com \
    --cc=olof@lixom.net \
    --cc=patrice.chotard@foss.st.com \
    --cc=peter.griffin@linaro.org \
    --cc=peter@hurleysoftware.com \
    --cc=r.baldyga@samsung.com \
    --cc=rgc@hms.se \
    --cc=s.hauer@pengutronix.de \
    --cc=sherry.sun@nxp.com \
    --cc=srini@kernel.org \
    --cc=stable@kernel.org \
    --cc=thomas.abraham@linaro.org \
    --cc=tony@atomide.com \
    --cc=u.kleine-koenig@baylibre.com \
    --cc=vladimir_zapolskiy@mentor.com \
    --cc=wangfushuai@baidu.com \
    --cc=whiteberg@arista.com \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox

all inboxes | Powered by JetHome®