From: Andy Shevchenko <andriy.shevche...@linux.intel.com>

Backport:
 - Upstream-Status: Pending.
 - Backport fix.
 
[https://bitbucket.org/andy-shev/linux/commits/8517d7ba8853e79bf2f4583b1653526d2927dbf2?at=master]

Should be cleaned up and split at least to two patches.
One is preventing warning from static analyzers (unbalanced lock).

Signed-off-by: Andy Shevchenko <andriy.shevche...@linux.intel.com>
Signed-off-by: Nilesh Bacchewar <nilesh.bacche...@intel.com>
---
 drivers/tty/serial/serial_core.c | 73 +++++++++++++++++++++++++++++++++++++++-
 1 file changed, 72 insertions(+), 1 deletion(-)

diff --git a/drivers/tty/serial/serial_core.c b/drivers/tty/serial/serial_core.c
index 84c26d5..b3b11c4 100644
--- a/drivers/tty/serial/serial_core.c
+++ b/drivers/tty/serial/serial_core.c
@@ -34,6 +34,7 @@
 #include <linux/serial_core.h>
 #include <linux/delay.h>
 #include <linux/mutex.h>
+#include <linux/pm_runtime.h>
 
 #include <asm/irq.h>
 #include <asm/uaccess.h>
@@ -116,12 +117,15 @@ uart_update_mctrl(struct uart_port *port, unsigned int 
set, unsigned int clear)
        unsigned long flags;
        unsigned int old;
 
+       pm_runtime_get_sync(port->dev);
        spin_lock_irqsave(&port->lock, flags);
        old = port->mctrl;
        port->mctrl = (old & ~clear) | set;
        if (old != port->mctrl)
                port->ops->set_mctrl(port, port->mctrl);
        spin_unlock_irqrestore(&port->lock, flags);
+       pm_runtime_mark_last_busy(port->dev);
+       pm_runtime_put_autosuspend(port->dev);
 }
 
 #define uart_set_mctrl(port, set)      uart_update_mctrl(port, set, 0)
@@ -160,7 +164,11 @@ static int uart_port_startup(struct tty_struct *tty, 
struct uart_state *state,
                uart_circ_clear(&state->xmit);
        }
 
+       pm_runtime_get_sync(uport->dev);
        retval = uport->ops->startup(uport);
+       pm_runtime_mark_last_busy(uport->dev);
+       pm_runtime_put_autosuspend(uport->dev);
+
        if (retval == 0) {
                if (uart_console(uport) && uport->cons->cflag) {
                        tty->termios.c_cflag = uport->cons->cflag;
@@ -455,6 +463,8 @@ static void uart_change_speed(struct tty_struct *tty, 
struct uart_state *state,
                return;
 
        termios = &tty->termios;
+
+       pm_runtime_get_sync(uport->dev);
        uport->ops->set_termios(uport, termios, old_termios);
 
        /*
@@ -483,6 +493,8 @@ static void uart_change_speed(struct tty_struct *tty, 
struct uart_state *state,
                        __uart_start(tty);
        }
        spin_unlock_irq(&uport->lock);
+       pm_runtime_mark_last_busy(uport->dev);
+       pm_runtime_put_autosuspend(uport->dev);
 }
 
 static inline int __uart_put_char(struct uart_port *port,
@@ -955,7 +967,10 @@ static int uart_get_lsr_info(struct tty_struct *tty,
        struct uart_port *uport = state->uart_port;
        unsigned int result;
 
+       pm_runtime_get_sync(uport->dev);
        result = uport->ops->tx_empty(uport);
+       pm_runtime_mark_last_busy(uport->dev);
+       pm_runtime_put_autosuspend(uport->dev);
 
        /*
         * If we're about to load something into the transmit
@@ -981,9 +996,13 @@ static int uart_tiocmget(struct tty_struct *tty)
        mutex_lock(&port->mutex);
        if (!(tty->flags & (1 << TTY_IO_ERROR))) {
                result = uport->mctrl;
+
+               pm_runtime_get_sync(uport->dev);
                spin_lock_irq(&uport->lock);
                result |= uport->ops->get_mctrl(uport);
                spin_unlock_irq(&uport->lock);
+               pm_runtime_mark_last_busy(uport->dev);
+               pm_runtime_put_autosuspend(uport->dev);
        }
        mutex_unlock(&port->mutex);
 
@@ -1015,9 +1034,13 @@ static int uart_break_ctl(struct tty_struct *tty, int 
break_state)
 
        mutex_lock(&port->mutex);
 
+       pm_runtime_get_sync(uport->dev);
        if (uport->type != PORT_UNKNOWN)
                uport->ops->break_ctl(uport, break_state);
 
+       pm_runtime_mark_last_busy(uport->dev);
+       pm_runtime_put_autosuspend(uport->dev);
+
        mutex_unlock(&port->mutex);
        return 0;
 }
@@ -1058,7 +1081,10 @@ static int uart_do_autoconfig(struct tty_struct 
*tty,struct uart_state *state)
                 * This will claim the ports resources if
                 * a port is found.
                 */
+               pm_runtime_get_sync(uport->dev);
                uport->ops->config_port(uport, flags);
+               pm_runtime_mark_last_busy(uport->dev);
+               pm_runtime_put_autosuspend(uport->dev);
 
                ret = uart_startup(tty, state, 1);
        }
@@ -1309,7 +1335,10 @@ static void uart_set_ldisc(struct tty_struct *tty)
 
        if (uport->ops->set_ldisc) {
                mutex_lock(&state->port.mutex);
+               pm_runtime_get_sync(uport->dev);
                uport->ops->set_ldisc(uport, &tty->termios);
+               pm_runtime_mark_last_busy(uport->dev);
+               pm_runtime_put_autosuspend(uport->dev);
                mutex_unlock(&state->port.mutex);
        }
 }
@@ -1546,7 +1575,10 @@ static void uart_port_shutdown(struct tty_port *port)
        /*
         * Free the IRQ and disable the port.
         */
+       pm_runtime_get_sync(uport->dev);
        uport->ops->shutdown(uport);
+       pm_runtime_mark_last_busy(uport->dev);
+       pm_runtime_put_autosuspend(uport->dev);
 
        /*
         * Ensure that the IRQ handler isn't running on another CPU.
@@ -1690,9 +1722,12 @@ static void uart_line_info(struct seq_file *m, struct 
uart_driver *drv, int i)
                pm_state = state->pm_state;
                if (pm_state != UART_PM_STATE_ON)
                        uart_change_pm(state, UART_PM_STATE_ON);
+               pm_runtime_get_sync(uport->dev);
                spin_lock_irq(&uport->lock);
                status = uport->ops->get_mctrl(uport);
                spin_unlock_irq(&uport->lock);
+               pm_runtime_mark_last_busy(uport->dev);
+               pm_runtime_put_autosuspend(uport->dev);
                if (pm_state != UART_PM_STATE_ON)
                        uart_change_pm(state, pm_state);
                mutex_unlock(&port->mutex);
@@ -1976,7 +2011,15 @@ uart_set_options(struct uart_port *port, struct console 
*co,
         */
        port->mctrl |= TIOCM_DTR;
 
-       port->ops->set_termios(port, &termios, &dummy);
+       /* At early stage device is not created yet, we can't do PM */
+       if (port->dev) {
+               pm_runtime_get_sync(port->dev);
+               port->ops->set_termios(port, &termios, &dummy);
+               pm_runtime_mark_last_busy(port->dev);
+               pm_runtime_put_autosuspend(port->dev);
+       } else
+               port->ops->set_termios(port, &termios, &dummy);
+
        /*
         * Allow the setting of the UART parameters with a NULL console
         * too:
@@ -2056,11 +2099,14 @@ int uart_suspend_port(struct uart_driver *drv, struct 
uart_port *uport)
                set_bit(ASYNCB_SUSPENDED, &port->flags);
                clear_bit(ASYNCB_INITIALIZED, &port->flags);
 
+               pm_runtime_get_sync(uport->dev);
                spin_lock_irq(&uport->lock);
                ops->stop_tx(uport);
                ops->set_mctrl(uport, 0);
                ops->stop_rx(uport);
                spin_unlock_irq(&uport->lock);
+               pm_runtime_mark_last_busy(uport->dev);
+               pm_runtime_put_autosuspend(uport->dev);
 
                /*
                 * Wait for the transmitter to empty.
@@ -2072,7 +2118,10 @@ int uart_suspend_port(struct uart_driver *drv, struct 
uart_port *uport)
                                drv->dev_name,
                                drv->tty_driver->name_base + uport->line);
 
+               pm_runtime_get_sync(uport->dev);
                ops->shutdown(uport);
+               pm_runtime_mark_last_busy(uport->dev);
+               pm_runtime_put_autosuspend(uport->dev);
        }
 
        /*
@@ -2129,7 +2178,12 @@ int uart_resume_port(struct uart_driver *drv, struct 
uart_port *uport)
 
                if (console_suspend_enabled)
                        uart_change_pm(state, UART_PM_STATE_ON);
+
+               pm_runtime_get_sync(uport->dev);
                uport->ops->set_termios(uport, &termios, NULL);
+               pm_runtime_mark_last_busy(uport->dev);
+               pm_runtime_put_autosuspend(uport->dev);
+
                if (console_suspend_enabled)
                        console_start(uport->cons);
        }
@@ -2139,20 +2193,31 @@ int uart_resume_port(struct uart_driver *drv, struct 
uart_port *uport)
                int ret;
 
                uart_change_pm(state, UART_PM_STATE_ON);
+               pm_runtime_get_sync(uport->dev);
                spin_lock_irq(&uport->lock);
                ops->set_mctrl(uport, 0);
                spin_unlock_irq(&uport->lock);
+               pm_runtime_mark_last_busy(uport->dev);
+               pm_runtime_put_autosuspend(uport->dev);
+
                if (console_suspend_enabled || !uart_console(uport)) {
                        /* Protected by port mutex for now */
                        struct tty_struct *tty = port->tty;
+
+                       pm_runtime_get_sync(uport->dev);
                        ret = ops->startup(uport);
+                       pm_runtime_mark_last_busy(uport->dev);
+                       pm_runtime_put_autosuspend(uport->dev);
                        if (ret == 0) {
                                if (tty)
                                        uart_change_speed(tty, state, NULL);
+                               pm_runtime_get_sync(uport->dev);
                                spin_lock_irq(&uport->lock);
                                ops->set_mctrl(uport, uport->mctrl);
                                ops->start_tx(uport);
                                spin_unlock_irq(&uport->lock);
+                               pm_runtime_mark_last_busy(uport->dev);
+                               pm_runtime_put_autosuspend(uport->dev);
                                set_bit(ASYNCB_INITIALIZED, &port->flags);
                        } else {
                                /*
@@ -2246,9 +2311,12 @@ uart_configure_port(struct uart_driver *drv, struct 
uart_state *state,
                 * keep the DTR setting that is set in uart_set_options()
                 * We probably don't need a spinlock around this, but
                 */
+               pm_runtime_get_sync(port->dev);
                spin_lock_irqsave(&port->lock, flags);
                port->ops->set_mctrl(port, port->mctrl & TIOCM_DTR);
                spin_unlock_irqrestore(&port->lock, flags);
+               pm_runtime_mark_last_busy(port->dev);
+               pm_runtime_put_autosuspend(port->dev);
 
                /*
                 * If this driver supports console, and it hasn't been
@@ -2890,6 +2958,7 @@ void uart_handle_cts_change(struct uart_port *uport, 
unsigned int status)
        uport->icount.cts++;
 
        if (uart_softcts_mode(uport)) {
+               pm_runtime_get_sync(uport->dev);
                if (uport->hw_stopped) {
                        if (status) {
                                uport->hw_stopped = 0;
@@ -2902,6 +2971,8 @@ void uart_handle_cts_change(struct uart_port *uport, 
unsigned int status)
                                uport->ops->stop_tx(uport);
                        }
                }
+               pm_runtime_mark_last_busy(uport->dev);
+               pm_runtime_put_autosuspend(uport->dev);
 
        }
 }
-- 
1.9.1

-- 
_______________________________________________
linux-yocto mailing list
linux-yocto@yoctoproject.org
https://lists.yoctoproject.org/listinfo/linux-yocto

Reply via email to