[PATCH] serial/amba-pl011: enable uart clk in setup for console

Uwe Kleine-König u.kleine-koenig at pengutronix.de
Thu Dec 23 10:21:22 EST 2010


The .write callback for console drivers must not sleep.  So
pl011_console_write must call clk_enable that is allowed to sleep (and
does sleep on mxs).

So enable the clock in the .setup callback instead of .write.

This fixes bugs like:

	udevd (74): /proc/74/oom_adj is deprecated, please use /proc/74/oom_score_adj instead.
	BUG: sleeping function called from invalid context at /ptx/work/octopus/WORK_2_A/ukl/backup/gsrc/linux-2.6/kernel/mutex.c:278
	in_atomic(): 0, irqs_disabled(): 128, pid: 74, name: udevd
	2 locks held by udevd/74:
	 #0:  (&(&p->alloc_lock)->rlock){+.+...}, at: [<c0132ff8>] oom_adjust_write+0xf8/0x290
	 #1:  (&(&sighand->siglock)->rlock){......}, at: [<c005d1ec>] __lock_task_sighand+0x64/0xac
	irq event stamp: 673
	hardirqs last  enabled at (672): [<c0033fdc>] vector_swi+0x3c/0x90
	hardirqs last disabled at (673): [<c02882e0>] _raw_spin_lock_irqsave+0x30/0x64
	softirqs last  enabled at (0): [<c004a000>] copy_process+0x3a8/0xf90
	softirqs last disabled at (0): [<  (null)>]   (null)
	Backtrace:
	[<c0037b54>] (dump_backtrace+0x0/0x110) from [<c02853a4>] (dump_stack+0x1c/0x20)
	 r7:c79f0000 r6:c003dd00 r5:c030ce72 r4:c79f0000
	[<c0285388>] (dump_stack+0x0/0x20) from [<c0046a58>] (__might_sleep+0x100/0x120)
	[<c0046958>] (__might_sleep+0x0/0x120) from [<c0287054>] (mutex_lock_nested+0x3c/0x2b4)
	 r5:00000000 r4:00000000
	[<c0287018>] (mutex_lock_nested+0x0/0x2b4) from [<c003dd00>] (clk_enable+0x30/0x58)
	[<c003dcd0>] (clk_enable+0x0/0x58) from [<c01d9888>] (pl011_console_write+0x30/0x8c)
	 r4:00000066
	[<c01d9858>] (pl011_console_write+0x0/0x8c) from [<c004b9a4>] (__call_console_drivers+0x68/0x84)
	 r6:00000066 r5:00007401 r4:c0372950
	[<c004b93c>] (__call_console_drivers+0x0/0x84) from [<c004ba48>] (_call_console_drivers+0x88/0x9c)
	 r8:ffff8b99 r7:60000093 r6:c0352c24 r5:c0352ba0 r4:00007467
	[<c004b9c0>] (_call_console_drivers+0x0/0x9c) from [<c004c040>] (release_console_sem+0x158/0x244)
	 r5:00007467 r4:00007467
	[<c004bee8>] (release_console_sem+0x0/0x244) from [<c004c7fc>] (vprintk+0x388/0x404)
	[<c004c474>] (vprintk+0x0/0x404) from [<c0285560>] (printk+0x20/0x28)
	[<c0285540>] (printk+0x0/0x28) from [<c01330f0>] (oom_adjust_write+0x1f0/0x290)
	 r3:0000004a r2:0000004a r1:c795595c r0:c031998c
	[<c0132f00>] (oom_adjust_write+0x0/0x290) from [<c00eb008>] (vfs_write+0xb8/0x18c)
	 r8:0001a4ac r7:c79f1f70 r6:0001a4ac r5:00000003 r4:c79dbc00
	[<c00eaf50>] (vfs_write+0x0/0x18c) from [<c00eb1a8>] (sys_write+0x48/0x74)
	 r8:0001a4ac r7:00000003 r6:c79dbc00 r5:00000000 r4:00000000
	[<c00eb160>] (sys_write+0x0/0x74) from [<c0033e80>] (ret_fast_syscall+0x0/0x38)
	 r8:c0034088 r7:00000004 r6:00000000 r5:00000003 r4:00000003

Signed-off-by: Uwe Kleine-König <u.kleine-koenig at pengutronix.de>
Cc: Russell King <linux at arm.linux.org.uk>
Cc: Linus Walleij <linus.walleij at stericsson.com>
Cc: Steven Rostedt <rostedt at goodmis.org>
---
 drivers/serial/amba-pl011.c |    9 +++++----
 1 files changed, 5 insertions(+), 4 deletions(-)

diff --git a/drivers/serial/amba-pl011.c b/drivers/serial/amba-pl011.c
index 6ca7a44..e890ae8 100644
--- a/drivers/serial/amba-pl011.c
+++ b/drivers/serial/amba-pl011.c
@@ -710,8 +710,6 @@ pl011_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, new_cr;
 
-	clk_enable(uap->clk);
-
 	/*
 	 *	First save the CR then disable the interrupts
 	 */
@@ -730,8 +728,6 @@ pl011_console_write(struct console *co, const char *s, unsigned int count)
 		status = readw(uap->port.membase + UART01x_FR);
 	} while (status & UART01x_FR_BUSY);
 	writew(old_cr, uap->port.membase + UART011_CR);
-
-	clk_disable(uap->clk);
 }
 
 static void __init
@@ -776,6 +772,7 @@ static int __init pl011_console_setup(struct console *co, char *options)
 	int bits = 8;
 	int parity = 'n';
 	int flow = 'n';
+	int ret;
 
 	/*
 	 * Check whether an invalid uart number has been specified, and
@@ -788,6 +785,10 @@ static int __init pl011_console_setup(struct console *co, char *options)
 	if (!uap)
 		return -ENODEV;
 
+	ret = clk_enable(uap->clk);
+	if (ret)
+		return ret;
+
 	uap->port.uartclk = clk_get_rate(uap->clk);
 
 	if (options)
-- 
1.7.2.3




More information about the linux-arm-kernel mailing list