Commit 5a7efdac authored by Stephen Boyd's avatar Stephen Boyd

clkdev: Hold clocks_mutex while iterating clocks list

We recently introduced a change to support devm clk lookups. That change
introduced a code-path that used clk_find() without holding the
'clocks_mutex'. Unfortunately, clk_find() iterates over the 'clocks'
list and so we need to prevent the list from being modified at the same
time. Do this by holding the mutex and checking to make sure it's held
while iterating the list.

Note, we don't really care if the lookup is freed after we find it with
clk_find() because we're just doing a pointer comparison, but if we did
care we would need to keep holding the mutex while we dereference the
clk_lookup pointer.

Fixes: 3eee6c7d ("clkdev: add managed clkdev lookup registration")
Cc: Miquel Raynal <miquel.raynal@bootlin.com>
Cc: Jerome Brunet <jbrunet@baylibre.com>
Cc: Russell King <linux@armlinux.org.uk>
Cc: Michael Turquette <mturquette@baylibre.com>
Cc: Jeffrey Hugo <jhugo@codeaurora.org>
Cc: Chen-Yu Tsai <wens@csie.org>
Cc: Matti Vaittinen <matti.vaittinen@fi.rohmeurope.com>
Acked-by: default avatarMatti Vaittinen <matti.vaittinen@fi.rohmeurope.com>
Tested-by: default avatarJeffrey Hugo <jhugo@codeaurora.org>
Signed-off-by: default avatarStephen Boyd <sboyd@kernel.org>
parent f89b9e1b
...@@ -46,6 +46,8 @@ static struct clk_lookup *clk_find(const char *dev_id, const char *con_id) ...@@ -46,6 +46,8 @@ static struct clk_lookup *clk_find(const char *dev_id, const char *con_id)
if (con_id) if (con_id)
best_possible += 1; best_possible += 1;
lockdep_assert_held(&clocks_mutex);
list_for_each_entry(p, &clocks, node) { list_for_each_entry(p, &clocks, node) {
match = 0; match = 0;
if (p->dev_id) { if (p->dev_id) {
...@@ -402,7 +404,10 @@ void devm_clk_release_clkdev(struct device *dev, const char *con_id, ...@@ -402,7 +404,10 @@ void devm_clk_release_clkdev(struct device *dev, const char *con_id,
struct clk_lookup *cl; struct clk_lookup *cl;
int rval; int rval;
mutex_lock(&clocks_mutex);
cl = clk_find(dev_id, con_id); cl = clk_find(dev_id, con_id);
mutex_unlock(&clocks_mutex);
WARN_ON(!cl); WARN_ON(!cl);
rval = devres_release(dev, devm_clkdev_release, rval = devres_release(dev, devm_clkdev_release,
devm_clk_match_clkdev, cl); devm_clk_match_clkdev, cl);
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment