diff mbox

serial: pl010/pl011: move clk_enable from console write to setup

Message ID 1359475526-17523-1-git-send-email-walimisdev@gmail.com (mailing list archive)
State New, archived
Headers show

Commit Message

walimis Jan. 29, 2013, 4:05 p.m. UTC
There seems no need to call clk_enable in every console writing. And we
can move clk_enable to setup function to enable the clock only once.
Also combine the clk_enable and clk_prepare to clk_prepare_enable.

Signed-off-by: Liming Wang <walimisdev@gmail.com>
---
 drivers/tty/serial/amba-pl010.c |    6 +-----
 drivers/tty/serial/amba-pl011.c |    6 +-----
 2 files changed, 2 insertions(+), 10 deletions(-)

Comments

Russell King - ARM Linux Jan. 29, 2013, 4:08 p.m. UTC | #1
On Wed, Jan 30, 2013 at 12:05:26AM +0800, Liming Wang wrote:
> There seems no need to call clk_enable in every console writing. And we
> can move clk_enable to setup function to enable the clock only once.
> Also combine the clk_enable and clk_prepare to clk_prepare_enable.

NAK.  Just Nak.
Linus Walleij Jan. 29, 2013, 5:45 p.m. UTC | #2
On Tue, Jan 29, 2013 at 5:05 PM, Liming Wang <walimisdev@gmail.com> wrote:

> There seems no need to call clk_enable in every console writing. And we
> can move clk_enable to setup function to enable the clock only once.
> Also combine the clk_enable and clk_prepare to clk_prepare_enable.
>
> Signed-off-by: Liming Wang <walimisdev@gmail.com>

NAK.

Consider the case where the console outputs nothing or
a string every 30 minutes. Why should we not gate off the
clock between these sporadic prints?

Yours,
Linus Walleij
walimis Jan. 30, 2013, 10:41 a.m. UTC | #3
Resend to mailling list.

2013/1/30 Linus Walleij <linus.walleij@linaro.org>:
> On Tue, Jan 29, 2013 at 5:05 PM, Liming Wang <walimisdev@gmail.com> wrote:
>
>> There seems no need to call clk_enable in every console writing. And we
>> can move clk_enable to setup function to enable the clock only once.
>> Also combine the clk_enable and clk_prepare to clk_prepare_enable.
>>
>> Signed-off-by: Liming Wang <walimisdev@gmail.com>
>
> NAK.
>
> Consider the case where the console outputs nothing or
> a string every 30 minutes. Why should we not gate off the

Yes, it's reasonable. But I haven't see any other serial drivers do that except
pl010/pl011. Except the above consideration, is there any reason that we have to
do clk_enable in console write?

> clock between these sporadic prints?

It works fine under the normal condition, but I encountered backtrace
while using kgdboc under preempt_rt  kernel:

# echo "g" >/proc/sysrq-trigger
SysRq : DEBUG
<3>BUG: sleeping function called from invalid context at kernel/rtmutex.c:646
<3>in_atomic(): 1, irqs_disabled(): 128, pid: 676, name: sh
[<80017d64>] (unwind_backtrace+0x0/0x104) from [<8068fc24>]
(dump_stack+0x20/0x24)
[<8068fc24>] (dump_stack+0x20/0x24) from [<80061130>] (__might_sleep+0xf4/0x108)
[<80061130>] (__might_sleep+0xf4/0x108) from [<80698fc4>]
(rt_spin_lock+0x2c/0x38)
[<80698fc4>] (rt_spin_lock+0x2c/0x38) from [<80027f1c>] (clk_enable+0x2c/0x4c)
[<80027f1c>] (clk_enable+0x2c/0x4c) from [<803fddcc>]
(pl011_console_write+0x34/0x148)
[<803fddcc>] (pl011_console_write+0x34/0x148) from [<8009e60c>]
(vkdb_printf+0x384/0xa78)
[<8009e60c>] (vkdb_printf+0x384/0xa78) from [<8009ed44>] (kdb_printf+0x44/0x58)
[<8009ed44>] (kdb_printf+0x44/0x58) from [<800a399c>]
(kdb_main_loop+0x10c/0x914)
[<800a399c>] (kdb_main_loop+0x10c/0x914) from [<800a7a34>]
(kdb_stub+0x800/0x95c)
[<800a7a34>] (kdb_stub+0x800/0x95c) from [<8009b7b0>]
(kgdb_cpu_enter+0x350/0x780)
[<8009b7b0>] (kgdb_cpu_enter+0x350/0x780) from [<8009be64>]
(kgdb_handle_exception+0x94/0x1bc)
[<8009be64>] (kgdb_handle_exception+0x94/0x1bc) from [<80016efc>]
(kgdb_compiled_brk_fn+0x38/0x40)
[<80016efc>] (kgdb_compiled_brk_fn+0x38/0x40) from [<800082f4>]
(do_undefinstr+0x154/0x184)
[<800082f4>] (do_undefinstr+0x154/0x184) from [<80699a2c>]
(__und_svc_finish+0x0/0x14)
Exception stack(0xbcd6de08 to 0xbcd6de50)
de00:                   bcd6c000 bcd6c028 bcd6de68 80020318 809b77c0 809b77c8
de20: 80923e5c 00000007 00000000 bcd6c000 bcd6df68 bcd6deac bcd6de38 bcd6de90
de40: 800627d8 8009ac28 600d0013 ffffffff
[<80699a2c>] (__und_svc_finish+0x0/0x14) from [<8009ac28>]
(kgdb_breakpoint+0x50/0x80)
[<8009ac28>] (kgdb_breakpoint+0x50/0x80) from [<8009af18>]
(sysrq_handle_dbg+0x4c/0x70)
[<8009af18>] (sysrq_handle_dbg+0x4c/0x70) from [<803e9c38>]
(__handle_sysrq+0x138/0x19c)
[<803e9c38>] (__handle_sysrq+0x138/0x19c) from [<803e9ce4>]
(write_sysrq_trigger+0x48/0x58)
[<803e9ce4>] (write_sysrq_trigger+0x48/0x58) from [<801886c8>]
(proc_reg_write+0x88/0xb0)
[<801886c8>] (proc_reg_write+0x88/0xb0) from [<80132b1c>] (vfs_write+0xb8/0x148)
[<80132b1c>] (vfs_write+0xb8/0x148) from [<80132e64>] (sys_write+0x50/0x124)
[<80132e64>] (sys_write+0x50/0x124) from [<8000e7a0>]
(ret_fast_syscall+0x0/0x30)
[<80132e64>] (sys_write+0x50/0x124) from [<8on processor 1 due to Keyboard Entry
[1]kdb>

It seems that clk_enable/clk_disable are called in pl011_console_write
function with the irq disabeld. So that spin_lock in clk_enable/clk_disable
trips the rtmutex debug code.

There are two ways to resolve the issues:
1. One way is to convert spin_lock in clk_enable/clk_disable to raw spin_lock.
2. Another way is to move clk_enable/clk_disable from console write.

This patch is an attempt to make clear whether we can move
clk_enable/clk_disable from console write.

Thanks
Liming Wang

>
> Yours,
> Linus Walleij
Russell King - ARM Linux Jan. 30, 2013, 10:48 a.m. UTC | #4
On Wed, Jan 30, 2013 at 06:41:34PM +0800, walimis wrote:
> 2013/1/30 Linus Walleij <linus.walleij@linaro.org>:
> > On Tue, Jan 29, 2013 at 5:05 PM, Liming Wang <walimisdev@gmail.com> wrote:
> >
> >> There seems no need to call clk_enable in every console writing. And we
> >> can move clk_enable to setup function to enable the clock only once.
> >> Also combine the clk_enable and clk_prepare to clk_prepare_enable.
> >>
> >> Signed-off-by: Liming Wang <walimisdev@gmail.com>
> >
> > NAK.
> >
> > Consider the case where the console outputs nothing or
> > a string every 30 minutes. Why should we not gate off the
> 
> Yes, it's reasonable. But I haven't see any other serial drivers do that except
> pl010/pl011. Except the above consideration, is there any reason that we have to
> do clk_enable in console write?

The reason that it's done is because the author of the driver (me) is also
the author of the clk API, and I know how these things work, and I know
how to code drivers to work most effectively with it.

Everyone else appears to be totally and utterly lazy about it.

> It works fine under the normal condition, but I encountered backtrace
> while using kgdboc under preempt_rt  kernel:
> 
> # echo "g" >/proc/sysrq-trigger
> SysRq : DEBUG
> <3>BUG: sleeping function called from invalid context at kernel/rtmutex.c:646
> <3>in_atomic(): 1, irqs_disabled(): 128, pid: 676, name: sh
> [<80017d64>] (unwind_backtrace+0x0/0x104) from [<8068fc24>]
> (dump_stack+0x20/0x24)
> [<8068fc24>] (dump_stack+0x20/0x24) from [<80061130>] (__might_sleep+0xf4/0x108)
> [<80061130>] (__might_sleep+0xf4/0x108) from [<80698fc4>]
> (rt_spin_lock+0x2c/0x38)
> [<80698fc4>] (rt_spin_lock+0x2c/0x38) from [<80027f1c>] (clk_enable+0x2c/0x4c)

Well, I guess that's down to the use of rt_spin_lock there.  I think that's
one for the RT Preempt guys; I don't deal with RT kernels at all - I know
nothing about that.

In standard kernel programming it is perfectly acceptable to take spinlocks
in non-preemptable contexts like this.

> This patch is an attempt to make clear whether we can move
> clk_enable/clk_disable from console write.

clk_enable/clk_disable should be callable from this context; the bug is that
they aren't.
diff mbox

Patch

diff --git a/drivers/tty/serial/amba-pl010.c b/drivers/tty/serial/amba-pl010.c
index 22317dd..9b77188 100644
--- a/drivers/tty/serial/amba-pl010.c
+++ b/drivers/tty/serial/amba-pl010.c
@@ -569,8 +569,6 @@  pl010_console_write(struct console *co, const char *s, unsigned int count)
 	struct uart_amba_port *uap = amba_ports[co->index];
 	unsigned int status, old_cr;
 
-	clk_enable(uap->clk);
-
 	/*
 	 *	First save the CR then disable the interrupts
 	 */
@@ -588,8 +586,6 @@  pl010_console_write(struct console *co, const char *s, unsigned int count)
 		barrier();
 	} while (status & UART01x_FR_BUSY);
 	writel(old_cr, uap->port.membase + UART010_CR);
-
-	clk_disable(uap->clk);
 }
 
 static void __init
@@ -639,7 +635,7 @@  static int __init pl010_console_setup(struct console *co, char *options)
 	if (!uap)
 		return -ENODEV;
 
-	ret = clk_prepare(uap->clk);
+	ret = clk_prepare_enable(uap->clk);
 	if (ret)
 		return ret;
 
diff --git a/drivers/tty/serial/amba-pl011.c b/drivers/tty/serial/amba-pl011.c
index 7fca402..53aafd4 100644
--- a/drivers/tty/serial/amba-pl011.c
+++ b/drivers/tty/serial/amba-pl011.c
@@ -1777,8 +1777,6 @@  pl011_console_write(struct console *co, const char *s, unsigned int count)
 	unsigned long flags;
 	int locked = 1;
 
-	clk_enable(uap->clk);
-
 	local_irq_save(flags);
 	if (uap->port.sysrq)
 		locked = 0;
@@ -1809,8 +1807,6 @@  pl011_console_write(struct console *co, const char *s, unsigned int count)
 	if (locked)
 		spin_unlock(&uap->port.lock);
 	local_irq_restore(flags);
-
-	clk_disable(uap->clk);
 }
 
 static void __init
@@ -1876,7 +1872,7 @@  static int __init pl011_console_setup(struct console *co, char *options)
 				"could not set default pins\n");
 	}
 
-	ret = clk_prepare(uap->clk);
+	ret = clk_prepare_enable(uap->clk);
 	if (ret)
 		return ret;