Skip to content

Commit

Permalink
ARM: LPC32xx: clock.c: Fix mutex lock issues
Browse files Browse the repository at this point in the history
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>
  • Loading branch information
Roland Stigge authored and Olof Johansson committed Feb 9, 2012
1 parent 0cf0d81 commit b845186
Showing 1 changed file with 11 additions and 30 deletions.
41 changes: 11 additions & 30 deletions arch/arm/mach-lpc32xx/clock.c
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down Expand Up @@ -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 */
Expand Down Expand Up @@ -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;
}
Expand All @@ -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);

Expand All @@ -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);

Expand All @@ -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;
}
Expand All @@ -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);
Expand Down

0 comments on commit b845186

Please sign in to comment.