summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorRoland Stigge <stigge@antcom.de>2012-02-08 21:41:05 +0100
committerOlof Johansson <olof@lixom.net>2012-02-10 00:55:49 +0100
commitb84518625183e87c6930b11db0592be786181128 (patch)
tree7d6a2351696d1ca2b5622bebda64d6bb84f2fe76
parentARM: LPC32xx: clock.c: warning fix (diff)
downloadlinux-b84518625183e87c6930b11db0592be786181128.tar.xz
linux-b84518625183e87c6930b11db0592be786181128.zip
ARM: LPC32xx: clock.c: Fix mutex lock issues
This patch fixes the mutex issue in clock.c, as done in Kevin Wells' original driver update: In some cases, the clock drivers could grab a mutex twice in an improper context. This patch changes the mutex mechanism to a simple irq lock/unlock mechanism and removes un-needed locks from some functions. (See also git.lpclinux.com) Signed-off-by: Roland Stigge <stigge@antcom.de> Tested-by: Wolfram Sang <w.sang@pengutronix.de> Acked-by: Kevin Wells <kevin.wells@nxp.com> Signed-off-by: Olof Johansson <olof@lixom.net>
-rw-r--r--arch/arm/mach-lpc32xx/clock.c41
1 files changed, 11 insertions, 30 deletions
diff --git a/arch/arm/mach-lpc32xx/clock.c b/arch/arm/mach-lpc32xx/clock.c
index 39dcbd0e68b2..fef863062a5e 100644
--- a/arch/arm/mach-lpc32xx/clock.c
+++ b/arch/arm/mach-lpc32xx/clock.c
@@ -97,9 +97,10 @@
#include "clock.h"
#include "common.h"
+static DEFINE_SPINLOCK(global_clkregs_lock);
+
static struct clk clk_armpll;
static struct clk clk_usbpll;
-static DEFINE_MUTEX(clkm_lock);
/*
* Post divider values for PLLs based on selected register value
@@ -891,16 +892,6 @@ static struct clk clk_lcd = {
.enable_mask = LPC32XX_CLKPWR_LCDCTRL_CLK_EN,
};
-static inline void clk_lock(void)
-{
- mutex_lock(&clkm_lock);
-}
-
-static inline void clk_unlock(void)
-{
- mutex_unlock(&clkm_lock);
-}
-
static void local_clk_disable(struct clk *clk)
{
/* Don't attempt to disable clock if it has no users */
@@ -945,10 +936,11 @@ static int local_clk_enable(struct clk *clk)
int clk_enable(struct clk *clk)
{
int ret;
+ unsigned long flags;
- clk_lock();
+ spin_lock_irqsave(&global_clkregs_lock, flags);
ret = local_clk_enable(clk);
- clk_unlock();
+ spin_unlock_irqrestore(&global_clkregs_lock, flags);
return ret;
}
@@ -959,9 +951,11 @@ EXPORT_SYMBOL(clk_enable);
*/
void clk_disable(struct clk *clk)
{
- clk_lock();
+ unsigned long flags;
+
+ spin_lock_irqsave(&global_clkregs_lock, flags);
local_clk_disable(clk);
- clk_unlock();
+ spin_unlock_irqrestore(&global_clkregs_lock, flags);
}
EXPORT_SYMBOL(clk_disable);
@@ -970,13 +964,7 @@ EXPORT_SYMBOL(clk_disable);
*/
unsigned long clk_get_rate(struct clk *clk)
{
- unsigned long rate;
-
- clk_lock();
- rate = clk->get_rate(clk);
- clk_unlock();
-
- return rate;
+ return clk->get_rate(clk);
}
EXPORT_SYMBOL(clk_get_rate);
@@ -992,11 +980,8 @@ int clk_set_rate(struct clk *clk, unsigned long rate)
* the actual rate set as part of the peripheral dividers
* instead of high level clock control
*/
- if (clk->set_rate) {
- clk_lock();
+ if (clk->set_rate)
ret = clk->set_rate(clk, rate);
- clk_unlock();
- }
return ret;
}
@@ -1007,15 +992,11 @@ EXPORT_SYMBOL(clk_set_rate);
*/
long clk_round_rate(struct clk *clk, unsigned long rate)
{
- clk_lock();
-
if (clk->round_rate)
rate = clk->round_rate(clk, rate);
else
rate = clk->get_rate(clk);
- clk_unlock();
-
return rate;
}
EXPORT_SYMBOL(clk_round_rate);