clk: rockchip: fix deadlock possibility in cpuclk
Lockdep reported a possible deadlock between the cpuclk lock and for example the i2c driver. CPU0 CPU1 ---- ---- lock(clk_lock); local_irq_disable(); lock(&(&i2c->lock)->rlock); lock(clk_lock); <Interrupt> lock(&(&i2c->lock)->rlock); *** DEADLOCK *** The generic clock-types of the core ccf already use spin_lock_irqsave when touching clock registers, so do the same for the cpuclk. Signed-off-by: Heiko Stuebner <heiko@sntech.de> Reviewed-by: Doug Anderson <dianders@chromium.org> Signed-off-by: Michael Turquette <mturquette@linaro.org> [mturquette@linaro.org: removed initialization of "flags"]
This commit is contained in:
parent
b71e8ecd57
commit
a5e1baf7dc
|
@ -124,10 +124,11 @@ static int rockchip_cpuclk_pre_rate_change(struct rockchip_cpuclk *cpuclk,
|
|||
{
|
||||
const struct rockchip_cpuclk_reg_data *reg_data = cpuclk->reg_data;
|
||||
unsigned long alt_prate, alt_div;
|
||||
unsigned long flags;
|
||||
|
||||
alt_prate = clk_get_rate(cpuclk->alt_parent);
|
||||
|
||||
spin_lock(cpuclk->lock);
|
||||
spin_lock_irqsave(cpuclk->lock, flags);
|
||||
|
||||
/*
|
||||
* If the old parent clock speed is less than the clock speed
|
||||
|
@ -164,7 +165,7 @@ static int rockchip_cpuclk_pre_rate_change(struct rockchip_cpuclk *cpuclk,
|
|||
cpuclk->reg_base + reg_data->core_reg);
|
||||
}
|
||||
|
||||
spin_unlock(cpuclk->lock);
|
||||
spin_unlock_irqrestore(cpuclk->lock, flags);
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
@ -173,6 +174,7 @@ static int rockchip_cpuclk_post_rate_change(struct rockchip_cpuclk *cpuclk,
|
|||
{
|
||||
const struct rockchip_cpuclk_reg_data *reg_data = cpuclk->reg_data;
|
||||
const struct rockchip_cpuclk_rate_table *rate;
|
||||
unsigned long flags;
|
||||
|
||||
rate = rockchip_get_cpuclk_settings(cpuclk, ndata->new_rate);
|
||||
if (!rate) {
|
||||
|
@ -181,7 +183,7 @@ static int rockchip_cpuclk_post_rate_change(struct rockchip_cpuclk *cpuclk,
|
|||
return -EINVAL;
|
||||
}
|
||||
|
||||
spin_lock(cpuclk->lock);
|
||||
spin_lock_irqsave(cpuclk->lock, flags);
|
||||
|
||||
if (ndata->old_rate < ndata->new_rate)
|
||||
rockchip_cpuclk_set_dividers(cpuclk, rate);
|
||||
|
@ -201,7 +203,7 @@ static int rockchip_cpuclk_post_rate_change(struct rockchip_cpuclk *cpuclk,
|
|||
if (ndata->old_rate > ndata->new_rate)
|
||||
rockchip_cpuclk_set_dividers(cpuclk, rate);
|
||||
|
||||
spin_unlock(cpuclk->lock);
|
||||
spin_unlock_irqrestore(cpuclk->lock, flags);
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
|
Loading…
Reference in New Issue