[<prev] [next>] [thread-next>] [day] [month] [year] [list]
Message-Id: <20200602001813.30459-1-tony@atomide.com>
Date: Mon, 1 Jun 2020 17:18:13 -0700
From: Tony Lindgren <tony@...mide.com>
To: Peter Hurley <peter@...leysoftware.com>,
Greg Kroah-Hartman <gregkh@...uxfoundation.org>
Cc: Vignesh Raghavendra <vigneshr@...com>,
linux-serial@...r.kernel.org, linux-omap@...r.kernel.org,
linux-kernel@...r.kernel.org,
Andy Shevchenko <andriy.shevchenko@...ux.intel.com>,
Merlijn Wajer <merlijn@...zup.org>,
Pavel Machek <pavel@....cz>, Sebastian Reichel <sre@...nel.org>
Subject: [PATCH] serial: 8250_port: Fix imprecise external abort for mctrl if inactive
We can get an imprecise external abort on uart_shutdown() at
serial8250_do_set_mctrl() if the UART is autoidled.
We don't want to add PM runtime calls to serial8250_do_set_mctrl()
beyond checking the usage count as it gets called from interrupts
disabled and spinlock held from uart_update_mctrl().
We can just bail out early from serial8250_do_set_mctrl() if the UART
is inactive. We have uart_shutdown() call uart_port_dtr_rts() with
value of 0 just to disable DTR and RTS.
Cc: Andy Shevchenko <andriy.shevchenko@...ux.intel.com>
Cc: Merlijn Wajer <merlijn@...zup.org>
Cc: Pavel Machek <pavel@....cz>
Cc: Sebastian Reichel <sre@...nel.org>
Cc: Vignesh Raghavendra <vigneshr@...com>
Signed-off-by: Tony Lindgren <tony@...mide.com>
---
drivers/tty/serial/8250/8250_port.c | 12 ++++++++++++
1 file changed, 12 insertions(+)
diff --git a/drivers/tty/serial/8250/8250_port.c b/drivers/tty/serial/8250/8250_port.c
--- a/drivers/tty/serial/8250/8250_port.c
+++ b/drivers/tty/serial/8250/8250_port.c
@@ -2001,11 +2001,20 @@ static unsigned int serial8250_get_mctrl(struct uart_port *port)
return serial8250_do_get_mctrl(port);
}
+/*
+ * Called from uart_update_mctrl() with spinlock held, so we don't want
+ * add PM runtime calls here beyond checking the usage count. If the
+ * UART is not active, we can just bail out early.
+ */
void serial8250_do_set_mctrl(struct uart_port *port, unsigned int mctrl)
{
struct uart_8250_port *up = up_to_u8250p(port);
unsigned char mcr;
+ if (up->capabilities & UART_CAP_RPM &&
+ !pm_runtime_get_if_in_use(up->port.dev))
+ return;
+
if (port->rs485.flags & SER_RS485_ENABLED) {
if (serial8250_in_MCR(up) & UART_MCR_RTS)
mctrl |= TIOCM_RTS;
@@ -2018,6 +2027,9 @@ void serial8250_do_set_mctrl(struct uart_port *port, unsigned int mctrl)
mcr = (mcr & up->mcr_mask) | up->mcr_force | up->mcr;
serial8250_out_MCR(up, mcr);
+
+ if (up->capabilities & UART_CAP_RPM)
+ pm_runtime_put(up->port.dev);
}
EXPORT_SYMBOL_GPL(serial8250_do_set_mctrl);
--
2.26.2
Powered by blists - more mailing lists