Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit b8451862 authored by Roland Stigge's avatar Roland Stigge Committed by Olof Johansson
Browse files

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: default avatarRoland Stigge <stigge@antcom.de>
Tested-by: default avatarWolfram Sang <w.sang@pengutronix.de>
Acked-by: default avatarKevin Wells <kevin.wells@nxp.com>
Signed-off-by: default avatarOlof Johansson <olof@lixom.net>
parent 0cf0d815
Loading
Loading
Loading
Loading
+11 −30
Original line number Diff line number Diff line
@@ -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);