Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

serial: liteuart: Use port lock wrappers

When a serial port is used for kernel console output, then all
modifications to the UART registers which are done from other contexts,
e.g. getty, termios, are interference points for the kernel console.

So far this has been ignored and the printk output is based on the
principle of hope. The rework of the console infrastructure which aims to
support threaded and atomic consoles, requires to mark sections which
modify the UART registers as unsafe. This allows the atomic write function
to make informed decisions and eventually to restore operational state. It
also allows to prevent the regular UART code from modifying UART registers
while printk output is in progress.

All modifications of UART registers are guarded by the UART port lock,
which provides an obvious synchronization point with the console
infrastructure.

To avoid adding this functionality to all UART drivers, wrap the
spin_[un]lock*() invocations for uart_port::lock into helper functions
which just contain the spin_[un]lock*() invocations for now. In a
subsequent step these helpers will gain the console synchronization
mechanisms.

Converted with coccinelle. No functional change.

Signed-off-by: Thomas Gleixner <tglx@linutronix.de>
Acked-by: Gabriel Somlo <gsomlo@gmail.com>
Signed-off-by: John Ogness <john.ogness@linutronix.de>
Link: https://lore.kernel.org/r/20230914183831.587273-33-john.ogness@linutronix.de
Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>

authored by

Thomas Gleixner and committed by
Greg Kroah-Hartman
12e67550 e0e6d8b4

+10 -10
+10 -10
drivers/tty/serial/liteuart.c
··· 139 139 * if polling, the context would be "in_serving_softirq", so use 140 140 * irq[save|restore] spin_lock variants to cover all possibilities 141 141 */ 142 - spin_lock_irqsave(&port->lock, flags); 142 + uart_port_lock_irqsave(port, &flags); 143 143 isr = litex_read8(port->membase + OFF_EV_PENDING) & uart->irq_reg; 144 144 if (isr & EV_RX) 145 145 liteuart_rx_chars(port); 146 146 if (isr & EV_TX) 147 147 liteuart_tx_chars(port); 148 - spin_unlock_irqrestore(&port->lock, flags); 148 + uart_port_unlock_irqrestore(port, flags); 149 149 150 150 return IRQ_RETVAL(isr); 151 151 } ··· 195 195 } 196 196 } 197 197 198 - spin_lock_irqsave(&port->lock, flags); 198 + uart_port_lock_irqsave(port, &flags); 199 199 /* only enabling rx irqs during startup */ 200 200 liteuart_update_irq_reg(port, true, EV_RX); 201 - spin_unlock_irqrestore(&port->lock, flags); 201 + uart_port_unlock_irqrestore(port, flags); 202 202 203 203 if (!port->irq) { 204 204 timer_setup(&uart->timer, liteuart_timer, 0); ··· 213 213 struct liteuart_port *uart = to_liteuart_port(port); 214 214 unsigned long flags; 215 215 216 - spin_lock_irqsave(&port->lock, flags); 216 + uart_port_lock_irqsave(port, &flags); 217 217 liteuart_update_irq_reg(port, false, EV_RX | EV_TX); 218 - spin_unlock_irqrestore(&port->lock, flags); 218 + uart_port_unlock_irqrestore(port, flags); 219 219 220 220 if (port->irq) 221 221 free_irq(port->irq, port); ··· 229 229 unsigned int baud; 230 230 unsigned long flags; 231 231 232 - spin_lock_irqsave(&port->lock, flags); 232 + uart_port_lock_irqsave(port, &flags); 233 233 234 234 /* update baudrate */ 235 235 baud = uart_get_baud_rate(port, new, old, 0, 460800); 236 236 uart_update_timeout(port, new->c_cflag, baud); 237 237 238 - spin_unlock_irqrestore(&port->lock, flags); 238 + uart_port_unlock_irqrestore(port, flags); 239 239 } 240 240 241 241 static const char *liteuart_type(struct uart_port *port) ··· 382 382 uart = (struct liteuart_port *)xa_load(&liteuart_array, co->index); 383 383 port = &uart->port; 384 384 385 - spin_lock_irqsave(&port->lock, flags); 385 + uart_port_lock_irqsave(port, &flags); 386 386 uart_console_write(port, s, count, liteuart_putchar); 387 - spin_unlock_irqrestore(&port->lock, flags); 387 + uart_port_unlock_irqrestore(port, flags); 388 388 } 389 389 390 390 static int liteuart_console_setup(struct console *co, char *options)