Skip to content

Commit

Permalink
serial: pxa: add spin lock for console write
Browse files Browse the repository at this point in the history
v3:
Remove empty line

v2:
Move local_irq_save() after clk_prepare_enable()

v1:
At UP mode, when cpu want to print message in kernel, it will invoke
peempt_disable and disable irq. So it is safe for UP mode.
For SMP mode, it is not safe to protect the HW reigsters.
one CPU will run a program which will invoke printf.
another CPU will run a program in kernel that invoke printk.
So when second CPU is trying to printk, it will do
1. save ier register
2. enable uue bit of ier register
3. push buffer to uart fifo
4 .restore ier register
when first CPU want to printf, and it happens between 1 and 4, it will
enable thre bit of ier, and waiting for transmit intterupt. while step 4
will make the ier lost thre bit.
add spin lock here to protect the ier register for console write.

Signed-off-by: Chao Xie <chao.xie@marvell.com>
Signed-off-by: Haojian Zhuang <haojian.zhuang@gmail.com>
Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
  • Loading branch information
Chao Xie authored and Greg Kroah-Hartman committed Jun 15, 2012
1 parent 2fc4691 commit cfe275c
Showing 1 changed file with 14 additions and 0 deletions.
14 changes: 14 additions & 0 deletions drivers/tty/serial/pxa.c
Original file line number Diff line number Diff line change
Expand Up @@ -670,9 +670,19 @@ serial_pxa_console_write(struct console *co, const char *s, unsigned int count)
{
struct uart_pxa_port *up = serial_pxa_ports[co->index];
unsigned int ier;
unsigned long flags;
int locked = 1;

clk_prepare_enable(up->clk);

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 IER then disable the interrupts
*/
Expand All @@ -688,6 +698,10 @@ serial_pxa_console_write(struct console *co, const char *s, unsigned int count)
wait_for_xmitr(up);
serial_out(up, UART_IER, ier);

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

clk_disable_unprepare(up->clk);
}

Expand Down

0 comments on commit cfe275c

Please sign in to comment.