Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit f3c681c0 authored by David S. Miller's avatar David S. Miller
Browse files

[SERIAL]: Fix console write locking in sparc drivers.



Mirror the logic in 8250 for proper console write locking
when SYSRQ is triggered or an OOPS is in progress.

Signed-off-by: default avatarDavid S. Miller <davem@davemloft.net>
parent 9918cc2e
Loading
Loading
Loading
Loading
+26 −4
Original line number Diff line number Diff line
@@ -440,8 +440,16 @@ static void sunhv_console_write_paged(struct console *con, const char *s, unsign
{
	struct uart_port *port = sunhv_port;
	unsigned long flags;
	int locked = 1;

	local_irq_save(flags);
	if (port->sysrq) {
		locked = 0;
	} else if (oops_in_progress) {
		locked = spin_trylock(&port->lock);
	} else
		spin_lock(&port->lock);

	spin_lock_irqsave(&port->lock, flags);
	while (n > 0) {
		unsigned long ra = __pa(con_write_page);
		unsigned long page_bytes;
@@ -469,7 +477,10 @@ static void sunhv_console_write_paged(struct console *con, const char *s, unsign
			ra += written;
		}
	}
	spin_unlock_irqrestore(&port->lock, flags);

	if (locked)
		spin_unlock(&port->lock);
	local_irq_restore(flags);
}

static inline void sunhv_console_putchar(struct uart_port *port, char c)
@@ -488,7 +499,15 @@ static void sunhv_console_write_bychar(struct console *con, const char *s, unsig
{
	struct uart_port *port = sunhv_port;
	unsigned long flags;
	int i;
	int i, locked = 1;

	local_irq_save(flags);
	if (port->sysrq) {
		locked = 0;
	} else if (oops_in_progress) {
		locked = spin_trylock(&port->lock);
	} else
		spin_lock(&port->lock);

	spin_lock_irqsave(&port->lock, flags);
	for (i = 0; i < n; i++) {
@@ -496,7 +515,10 @@ static void sunhv_console_write_bychar(struct console *con, const char *s, unsig
			sunhv_console_putchar(port, '\r');
		sunhv_console_putchar(port, *s++);
	}
	spin_unlock_irqrestore(&port->lock, flags);

	if (locked)
		spin_unlock(&port->lock);
	local_irq_restore(flags);
}

static struct console sunhv_console = {
+14 −5
Original line number Diff line number Diff line
@@ -860,22 +860,31 @@ static int num_channels;
static void sunsab_console_putchar(struct uart_port *port, int c)
{
	struct uart_sunsab_port *up = (struct uart_sunsab_port *)port;
	unsigned long flags;

	spin_lock_irqsave(&up->port.lock, flags);

	sunsab_tec_wait(up);
	writeb(c, &up->regs->w.tic);

	spin_unlock_irqrestore(&up->port.lock, flags);
}

static void sunsab_console_write(struct console *con, const char *s, unsigned n)
{
	struct uart_sunsab_port *up = &sunsab_ports[con->index];
	unsigned long flags;
	int locked = 1;

	local_irq_save(flags);
	if (up->port.sysrq) {
		locked = 0;
	} else if (oops_in_progress) {
		locked = spin_trylock(&up->port.lock);
	} else
		spin_lock(&up->port.lock);

	uart_console_write(&up->port, s, n, sunsab_console_putchar);
	sunsab_tec_wait(up);

	if (locked)
		spin_unlock(&up->port.lock);
	local_irq_restore(flags);
}

static int sunsab_console_setup(struct console *con, char *options)
+14 −0
Original line number Diff line number Diff line
@@ -1288,7 +1288,17 @@ static void sunsu_console_write(struct console *co, const char *s,
				unsigned int count)
{
	struct uart_sunsu_port *up = &sunsu_ports[co->index];
	unsigned long flags;
	unsigned int ier;
	int locked = 1;

	local_irq_save(flags);
	if (up->port.sysrq) {
		locked = 0;
	} else if (oops_in_progress) {
		locked = spin_trylock(&up->port.lock);
	} else
		spin_lock(&up->port.lock);

	/*
	 *	First save the UER then disable the interrupts
@@ -1304,6 +1314,10 @@ static void sunsu_console_write(struct console *co, const char *s,
	 */
	wait_for_xmitr(up);
	serial_out(up, UART_IER, ier);

	if (locked)
		spin_unlock(&up->port.lock);
	local_irq_restore(flags);
}

/*
+14 −3
Original line number Diff line number Diff line
@@ -9,7 +9,7 @@
 * C. Dost, Pete Zaitcev, Ted Ts'o and Alex Buell for their
 * work there.
 *
 *  Copyright (C) 2002, 2006 David S. Miller (davem@davemloft.net)
 * Copyright (C) 2002, 2006, 2007 David S. Miller (davem@davemloft.net)
 */

#include <linux/module.h>
@@ -1151,11 +1151,22 @@ sunzilog_console_write(struct console *con, const char *s, unsigned int count)
{
	struct uart_sunzilog_port *up = &sunzilog_port_table[con->index];
	unsigned long flags;
	int locked = 1;

	local_irq_save(flags);
	if (up->port.sysrq) {
		locked = 0;
	} else if (oops_in_progress) {
		locked = spin_trylock(&up->port.lock);
	} else
		spin_lock(&up->port.lock);

	spin_lock_irqsave(&up->port.lock, flags);
	uart_console_write(&up->port, s, count, sunzilog_putchar);
	udelay(2);
	spin_unlock_irqrestore(&up->port.lock, flags);

	if (locked)
		spin_unlock(&up->port.lock);
	local_irq_restore(flags);
}

static int __init sunzilog_console_setup(struct console *con, char *options)