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.shevche...@linux.intel.com>
Cc: Merlijn Wajer <merl...@wizzup.org>
Cc: Pavel Machek <pa...@ucw.cz>
Cc: Sebastian Reichel <s...@kernel.org>
Cc: Vignesh Raghavendra <vigne...@ti.com>
Signed-off-by: Tony Lindgren <t...@atomide.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

Reply via email to