Commit a5e1baf7dca10f8cf945394034013260297bc416
Committed by
Michael Turquette
1 parent
b71e8ecd57
Exists in
ti-lsk-linux-4.1.y
and in
10 other branches
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"]
Showing 1 changed file with 6 additions and 4 deletions Side-by-side Diff
drivers/clk/rockchip/clk-cpu.c
... | ... | @@ -124,10 +124,11 @@ |
124 | 124 | { |
125 | 125 | const struct rockchip_cpuclk_reg_data *reg_data = cpuclk->reg_data; |
126 | 126 | unsigned long alt_prate, alt_div; |
127 | + unsigned long flags; | |
127 | 128 | |
128 | 129 | alt_prate = clk_get_rate(cpuclk->alt_parent); |
129 | 130 | |
130 | - spin_lock(cpuclk->lock); | |
131 | + spin_lock_irqsave(cpuclk->lock, flags); | |
131 | 132 | |
132 | 133 | /* |
133 | 134 | * If the old parent clock speed is less than the clock speed |
... | ... | @@ -164,7 +165,7 @@ |
164 | 165 | cpuclk->reg_base + reg_data->core_reg); |
165 | 166 | } |
166 | 167 | |
167 | - spin_unlock(cpuclk->lock); | |
168 | + spin_unlock_irqrestore(cpuclk->lock, flags); | |
168 | 169 | return 0; |
169 | 170 | } |
170 | 171 | |
... | ... | @@ -173,6 +174,7 @@ |
173 | 174 | { |
174 | 175 | const struct rockchip_cpuclk_reg_data *reg_data = cpuclk->reg_data; |
175 | 176 | const struct rockchip_cpuclk_rate_table *rate; |
177 | + unsigned long flags; | |
176 | 178 | |
177 | 179 | rate = rockchip_get_cpuclk_settings(cpuclk, ndata->new_rate); |
178 | 180 | if (!rate) { |
... | ... | @@ -181,7 +183,7 @@ |
181 | 183 | return -EINVAL; |
182 | 184 | } |
183 | 185 | |
184 | - spin_lock(cpuclk->lock); | |
186 | + spin_lock_irqsave(cpuclk->lock, flags); | |
185 | 187 | |
186 | 188 | if (ndata->old_rate < ndata->new_rate) |
187 | 189 | rockchip_cpuclk_set_dividers(cpuclk, rate); |
... | ... | @@ -201,7 +203,7 @@ |
201 | 203 | if (ndata->old_rate > ndata->new_rate) |
202 | 204 | rockchip_cpuclk_set_dividers(cpuclk, rate); |
203 | 205 | |
204 | - spin_unlock(cpuclk->lock); | |
206 | + spin_unlock_irqrestore(cpuclk->lock, flags); | |
205 | 207 | return 0; |
206 | 208 | } |
207 | 209 |