diff options
author | Linus Torvalds <torvalds@linux-foundation.org> | 2022-04-03 12:21:14 -0700 |
---|---|---|
committer | Linus Torvalds <torvalds@linux-foundation.org> | 2022-04-03 12:21:14 -0700 |
commit | 34a53ff911eb30629baad788fbed892f711bdd3e (patch) | |
tree | a6345810457d933d4dfa9cb4871e5c4bd5aa5854 | |
parent | 8b5656bc4e3707da642cb4a9126f4849fb518423 (diff) | |
parent | 859c2c7b1d0623a6f523f970043db85ce0e5aa60 (diff) |
Merge tag 'clk-for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/clk/linux
Pull clk fix from Stephen Boyd:
"A single revert to fix a boot regression seen when clk_put() started
dropping rate range requests. It's best to keep various systems
booting so we'll kick this out and try again next time"
* tag 'clk-for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/clk/linux:
Revert "clk: Drop the rate range on clk_put()"
-rw-r--r-- | drivers/clk/clk.c | 42 | ||||
-rw-r--r-- | drivers/clk/clk_test.c | 108 |
2 files changed, 14 insertions, 136 deletions
diff --git a/drivers/clk/clk.c b/drivers/clk/clk.c index 07a27b65b773..ed119182aa1b 100644 --- a/drivers/clk/clk.c +++ b/drivers/clk/clk.c @@ -2332,15 +2332,19 @@ int clk_set_rate_exclusive(struct clk *clk, unsigned long rate) } EXPORT_SYMBOL_GPL(clk_set_rate_exclusive); -static int clk_set_rate_range_nolock(struct clk *clk, - unsigned long min, - unsigned long max) +/** + * clk_set_rate_range - set a rate range for a clock source + * @clk: clock source + * @min: desired minimum clock rate in Hz, inclusive + * @max: desired maximum clock rate in Hz, inclusive + * + * Returns success (0) or negative errno. + */ +int clk_set_rate_range(struct clk *clk, unsigned long min, unsigned long max) { int ret = 0; unsigned long old_min, old_max, rate; - lockdep_assert_held(&prepare_lock); - if (!clk) return 0; @@ -2353,6 +2357,8 @@ static int clk_set_rate_range_nolock(struct clk *clk, return -EINVAL; } + clk_prepare_lock(); + if (clk->exclusive_count) clk_core_rate_unprotect(clk->core); @@ -2396,28 +2402,6 @@ out: if (clk->exclusive_count) clk_core_rate_protect(clk->core); - return ret; -} - -/** - * clk_set_rate_range - set a rate range for a clock source - * @clk: clock source - * @min: desired minimum clock rate in Hz, inclusive - * @max: desired maximum clock rate in Hz, inclusive - * - * Return: 0 for success or negative errno on failure. - */ -int clk_set_rate_range(struct clk *clk, unsigned long min, unsigned long max) -{ - int ret; - - if (!clk) - return 0; - - clk_prepare_lock(); - - ret = clk_set_rate_range_nolock(clk, min, max); - clk_prepare_unlock(); return ret; @@ -4419,7 +4403,9 @@ void __clk_put(struct clk *clk) } hlist_del(&clk->clks_node); - clk_set_rate_range_nolock(clk, 0, ULONG_MAX); + if (clk->min_rate > clk->core->req_rate || + clk->max_rate < clk->core->req_rate) + clk_core_set_rate_nolock(clk->core, clk->core->req_rate); owner = clk->core->owner; kref_put(&clk->core->ref, __clk_release); diff --git a/drivers/clk/clk_test.c b/drivers/clk/clk_test.c index fd2339cc5898..6731a822f4e3 100644 --- a/drivers/clk/clk_test.c +++ b/drivers/clk/clk_test.c @@ -760,65 +760,9 @@ static void clk_range_test_multiple_set_range_rate_maximized(struct kunit *test) clk_put(user1); } -/* - * Test that if we have several subsequent calls to - * clk_set_rate_range(), across multiple users, the core will reevaluate - * whether a new rate is needed, including when a user drop its clock. - * - * With clk_dummy_maximize_rate_ops, this means that the rate will - * trail along the maximum as it evolves. - */ -static void clk_range_test_multiple_set_range_rate_put_maximized(struct kunit *test) -{ - struct clk_dummy_context *ctx = test->priv; - struct clk_hw *hw = &ctx->hw; - struct clk *clk = hw->clk; - struct clk *user1, *user2; - unsigned long rate; - - user1 = clk_hw_get_clk(hw, NULL); - KUNIT_ASSERT_NOT_ERR_OR_NULL(test, user1); - - user2 = clk_hw_get_clk(hw, NULL); - KUNIT_ASSERT_NOT_ERR_OR_NULL(test, user2); - - KUNIT_ASSERT_EQ(test, - clk_set_rate(clk, DUMMY_CLOCK_RATE_2 + 1000), - 0); - - KUNIT_ASSERT_EQ(test, - clk_set_rate_range(user1, - 0, - DUMMY_CLOCK_RATE_2), - 0); - - rate = clk_get_rate(clk); - KUNIT_ASSERT_GT(test, rate, 0); - KUNIT_EXPECT_EQ(test, rate, DUMMY_CLOCK_RATE_2); - - KUNIT_ASSERT_EQ(test, - clk_set_rate_range(user2, - 0, - DUMMY_CLOCK_RATE_1), - 0); - - rate = clk_get_rate(clk); - KUNIT_ASSERT_GT(test, rate, 0); - KUNIT_EXPECT_EQ(test, rate, DUMMY_CLOCK_RATE_1); - - clk_put(user2); - - rate = clk_get_rate(clk); - KUNIT_ASSERT_GT(test, rate, 0); - KUNIT_EXPECT_EQ(test, rate, DUMMY_CLOCK_RATE_2); - - clk_put(user1); -} - static struct kunit_case clk_range_maximize_test_cases[] = { KUNIT_CASE(clk_range_test_set_range_rate_maximized), KUNIT_CASE(clk_range_test_multiple_set_range_rate_maximized), - KUNIT_CASE(clk_range_test_multiple_set_range_rate_put_maximized), {} }; @@ -933,61 +877,9 @@ static void clk_range_test_multiple_set_range_rate_minimized(struct kunit *test) clk_put(user1); } -/* - * Test that if we have several subsequent calls to - * clk_set_rate_range(), across multiple users, the core will reevaluate - * whether a new rate is needed, including when a user drop its clock. - * - * With clk_dummy_minimize_rate_ops, this means that the rate will - * trail along the minimum as it evolves. - */ -static void clk_range_test_multiple_set_range_rate_put_minimized(struct kunit *test) -{ - struct clk_dummy_context *ctx = test->priv; - struct clk_hw *hw = &ctx->hw; - struct clk *clk = hw->clk; - struct clk *user1, *user2; - unsigned long rate; - - user1 = clk_hw_get_clk(hw, NULL); - KUNIT_ASSERT_NOT_ERR_OR_NULL(test, user1); - - user2 = clk_hw_get_clk(hw, NULL); - KUNIT_ASSERT_NOT_ERR_OR_NULL(test, user2); - - KUNIT_ASSERT_EQ(test, - clk_set_rate_range(user1, - DUMMY_CLOCK_RATE_1, - ULONG_MAX), - 0); - - rate = clk_get_rate(clk); - KUNIT_ASSERT_GT(test, rate, 0); - KUNIT_EXPECT_EQ(test, rate, DUMMY_CLOCK_RATE_1); - - KUNIT_ASSERT_EQ(test, - clk_set_rate_range(user2, - DUMMY_CLOCK_RATE_2, - ULONG_MAX), - 0); - - rate = clk_get_rate(clk); - KUNIT_ASSERT_GT(test, rate, 0); - KUNIT_EXPECT_EQ(test, rate, DUMMY_CLOCK_RATE_2); - - clk_put(user2); - - rate = clk_get_rate(clk); - KUNIT_ASSERT_GT(test, rate, 0); - KUNIT_EXPECT_EQ(test, rate, DUMMY_CLOCK_RATE_1); - - clk_put(user1); -} - static struct kunit_case clk_range_minimize_test_cases[] = { KUNIT_CASE(clk_range_test_set_range_rate_minimized), KUNIT_CASE(clk_range_test_multiple_set_range_rate_minimized), - KUNIT_CASE(clk_range_test_multiple_set_range_rate_put_minimized), {} }; |