Skip to content

Commit 067bb17

Browse files
Tero KristoMike Turquette
authored andcommitted
clk: prevent erronous parsing of children during rate change
In some cases, clocks can switch their parent with clk_set_rate, for example clk_mux can do this in some cases. Current implementation of clk_change_rate uses un-safe list iteration on the clock children, which will cause wrong clocks to be parsed in case any of the clock children change their parents during the change rate operation. Fixed by using the safe list iterator instead. The problem was detected due to some divide by zero errors generated by clock init on dra7-evm board, see discussion under http://article.gmane.org/gmane.linux.ports.arm.kernel/349180 for details. Fixes: 71472c0 ("clk: add support for clock reparent on set_rate") Signed-off-by: Tero Kristo <t-kristo@ti.com> Reported-by: Nishanth Menon <nm@ti.com> Signed-off-by: Mike Turquette <mturquette@linaro.org>
1 parent f4ee3c8 commit 067bb17

File tree

1 file changed

+6
-1
lines changed

1 file changed

+6
-1
lines changed

drivers/clk/clk.c

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1467,6 +1467,7 @@ static struct clk *clk_propagate_rate_change(struct clk *clk, unsigned long even
14671467
static void clk_change_rate(struct clk *clk)
14681468
{
14691469
struct clk *child;
1470+
struct hlist_node *tmp;
14701471
unsigned long old_rate;
14711472
unsigned long best_parent_rate = 0;
14721473
bool skip_set_rate = false;
@@ -1502,7 +1503,11 @@ static void clk_change_rate(struct clk *clk)
15021503
if (clk->notifier_count && old_rate != clk->rate)
15031504
__clk_notify(clk, POST_RATE_CHANGE, old_rate, clk->rate);
15041505

1505-
hlist_for_each_entry(child, &clk->children, child_node) {
1506+
/*
1507+
* Use safe iteration, as change_rate can actually swap parents
1508+
* for certain clock types.
1509+
*/
1510+
hlist_for_each_entry_safe(child, tmp, &clk->children, child_node) {
15061511
/* Skip children who will be reparented to another clock */
15071512
if (child->new_parent && child->new_parent != clk)
15081513
continue;

0 commit comments

Comments
 (0)