From 6e2ad51190cdb11b364377882134513f60dec6b9 Mon Sep 17 00:00:00 2001 From: Ole Henrik Jahren Date: Sun, 6 Mar 2011 20:42:39 +0100 Subject: [PATCH] avr32: fix deadlock when reading clock list in debugfs When writing out /sys/kernel/debug/at32ap_clk, clock list lock is being held while clk_get() is called. clk_get() attempts to take the same lock, which results in deadlock. Introduce and call lock free version, __clk_get(), instead. Signed-off-by: Ole Henrik Jahren Cc: Hans-Christian Egtvedt Signed-off-by: Hans-Christian Egtvedt --- arch/avr32/mach-at32ap/clock.c | 24 ++++++++++++++++-------- 1 file changed, 16 insertions(+), 8 deletions(-) diff --git a/arch/avr32/mach-at32ap/clock.c b/arch/avr32/mach-at32ap/clock.c index 442f08c5e641..86925fd6ea5b 100644 --- a/arch/avr32/mach-at32ap/clock.c +++ b/arch/avr32/mach-at32ap/clock.c @@ -35,22 +35,30 @@ void at32_clk_register(struct clk *clk) spin_unlock(&clk_list_lock); } -struct clk *clk_get(struct device *dev, const char *id) +static struct clk *__clk_get(struct device *dev, const char *id) { struct clk *clk; - spin_lock(&clk_list_lock); - list_for_each_entry(clk, &at32_clock_list, list) { if (clk->dev == dev && strcmp(id, clk->name) == 0) { - spin_unlock(&clk_list_lock); return clk; } } - spin_unlock(&clk_list_lock); return ERR_PTR(-ENOENT); } + +struct clk *clk_get(struct device *dev, const char *id) +{ + struct clk *clk; + + spin_lock(&clk_list_lock); + clk = __clk_get(dev, id); + spin_unlock(&clk_list_lock); + + return clk; +} + EXPORT_SYMBOL(clk_get); void clk_put(struct clk *clk) @@ -257,15 +265,15 @@ static int clk_show(struct seq_file *s, void *unused) spin_lock(&clk_list_lock); /* show clock tree as derived from the three oscillators */ - clk = clk_get(NULL, "osc32k"); + clk = __clk_get(NULL, "osc32k"); dump_clock(clk, &r); clk_put(clk); - clk = clk_get(NULL, "osc0"); + clk = __clk_get(NULL, "osc0"); dump_clock(clk, &r); clk_put(clk); - clk = clk_get(NULL, "osc1"); + clk = __clk_get(NULL, "osc1"); dump_clock(clk, &r); clk_put(clk); -- 2.20.1