mirror of
https://github.com/torvalds/linux.git
synced 2024-11-01 17:51:43 +00:00
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>
This commit is contained in:
parent
9862048abf
commit
93d199a13a
@ -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);
|
||||
|
Loading…
Reference in New Issue
Block a user