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