All of lore.kernel.org
 help / color / mirror / Atom feed
* [PATCH] serial: pxa: add spin lock for console write
@ 2012-05-21  2:33 Chao Xie
  2012-05-22  3:07 ` Haojian Zhuang
  0 siblings, 1 reply; 2+ messages in thread
From: Chao Xie @ 2012-05-21  2:33 UTC (permalink / raw)
  To: linux-serial, haojian.zhuang; +Cc: Chao Xie

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>
---
 drivers/tty/serial/pxa.c |   15 +++++++++++++++
 1 files changed, 15 insertions(+), 0 deletions(-)

diff --git a/drivers/tty/serial/pxa.c b/drivers/tty/serial/pxa.c
index 5847a4b..d94387f 100644
--- a/drivers/tty/serial/pxa.c
+++ b/drivers/tty/serial/pxa.c
@@ -670,6 +670,16 @@ 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;
+
+	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);
 
 	clk_prepare_enable(up->clk);
 
@@ -689,6 +699,11 @@ serial_pxa_console_write(struct console *co, const char *s, unsigned int count)
 	serial_out(up, UART_IER, ier);
 
 	clk_disable_unprepare(up->clk);
+
+	if (locked)
+		spin_unlock(&up->port.lock);
+	local_irq_restore(flags);
+
 }
 
 static int __init
-- 
1.7.0.4


^ permalink raw reply related	[flat|nested] 2+ messages in thread

* RE: [PATCH] serial: pxa: add spin lock for console write
  2012-05-21  2:33 [PATCH] serial: pxa: add spin lock for console write Chao Xie
@ 2012-05-22  3:07 ` Haojian Zhuang
  0 siblings, 0 replies; 2+ messages in thread
From: Haojian Zhuang @ 2012-05-22  3:07 UTC (permalink / raw)
  To: linux-serial; +Cc: Chao Xie

int clk_prepare(struct clk *clk)
{
        int ret;

        mutex_lock(&prepare_lock);
        ret = __clk_prepare(clk);
        mutex_unlock(&prepare_lock);

        return ret;
}
EXPORT_SYMBOL_GPL(clk_prepare);

So invoking local_irq_save() before clk_prepare_enable() is wrong behavior.

Regards
Haojian
________________________________________
From: Chao Xie [chao.xie@marvell.com]
Sent: Monday, May 21, 2012 10:33 AM
To: linux-serial@vger.kernel.org; Haojian Zhuang
Cc: Chao Xie
Subject: [PATCH] serial: pxa: add spin lock for console write

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>
---
 drivers/tty/serial/pxa.c |   15 +++++++++++++++
 1 files changed, 15 insertions(+), 0 deletions(-)

diff --git a/drivers/tty/serial/pxa.c b/drivers/tty/serial/pxa.c
index 5847a4b..d94387f 100644
--- a/drivers/tty/serial/pxa.c
+++ b/drivers/tty/serial/pxa.c
@@ -670,6 +670,16 @@ 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;
+
+       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);

        clk_prepare_enable(up->clk);

@@ -689,6 +699,11 @@ serial_pxa_console_write(struct console *co, const char *s, unsigned int count)
        serial_out(up, UART_IER, ier);

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

 static int __init
--
1.7.0.4


^ permalink raw reply related	[flat|nested] 2+ messages in thread

end of thread, other threads:[~2012-05-22  3:12 UTC | newest]

Thread overview: 2+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2012-05-21  2:33 [PATCH] serial: pxa: add spin lock for console write Chao Xie
2012-05-22  3:07 ` Haojian Zhuang

This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.