Skip to content

Commit d773882

Browse files
mripardbebarino
authored andcommitted
clk: Drop the rate range on clk_put()
When clk_put() is called we don't make another clk_set_rate() call to re-evaluate the rate boundaries. This is unlike clk_set_rate_range() that evaluates the rate again each time it is called. However, clk_put() is essentially equivalent to clk_set_rate_range() since after clk_put() completes the consumer's boundaries shouldn't be enforced anymore. Let's add a call to clk_set_rate_range() in clk_put() to make sure those rate boundaries are dropped and the clock provider drivers can react. In order to be as non-intrusive as possible, we'll just make that call if the clock had non-default boundaries. Also add a few tests to make sure this case is covered. Fixes: c80ac50 ("clk: Always set the rate on clk_set_range_rate") Tested-by: Alexander Stein <[email protected]> # imx8mp Tested-by: Marek Szyprowski <[email protected]> # exynos4210, meson g12b Signed-off-by: Maxime Ripard <[email protected]> Link: https://lore.kernel.org/r/[email protected] Tested-by: Linux Kernel Functional Testing <[email protected]> Tested-by: Naresh Kamboju <[email protected]> Signed-off-by: Stephen Boyd <[email protected]>
1 parent aac00c7 commit d773882

File tree

2 files changed

+141
-14
lines changed

2 files changed

+141
-14
lines changed

drivers/clk/clk.c

Lines changed: 31 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -2325,19 +2325,15 @@ int clk_set_rate_exclusive(struct clk *clk, unsigned long rate)
23252325
}
23262326
EXPORT_SYMBOL_GPL(clk_set_rate_exclusive);
23272327

2328-
/**
2329-
* clk_set_rate_range - set a rate range for a clock source
2330-
* @clk: clock source
2331-
* @min: desired minimum clock rate in Hz, inclusive
2332-
* @max: desired maximum clock rate in Hz, inclusive
2333-
*
2334-
* Returns success (0) or negative errno.
2335-
*/
2336-
int clk_set_rate_range(struct clk *clk, unsigned long min, unsigned long max)
2328+
static int clk_set_rate_range_nolock(struct clk *clk,
2329+
unsigned long min,
2330+
unsigned long max)
23372331
{
23382332
int ret = 0;
23392333
unsigned long old_min, old_max, rate;
23402334

2335+
lockdep_assert_held(&prepare_lock);
2336+
23412337
if (!clk)
23422338
return 0;
23432339

@@ -2350,8 +2346,6 @@ int clk_set_rate_range(struct clk *clk, unsigned long min, unsigned long max)
23502346
return -EINVAL;
23512347
}
23522348

2353-
clk_prepare_lock();
2354-
23552349
if (clk->exclusive_count)
23562350
clk_core_rate_unprotect(clk->core);
23572351

@@ -2395,6 +2389,28 @@ int clk_set_rate_range(struct clk *clk, unsigned long min, unsigned long max)
23952389
if (clk->exclusive_count)
23962390
clk_core_rate_protect(clk->core);
23972391

2392+
return ret;
2393+
}
2394+
2395+
/**
2396+
* clk_set_rate_range - set a rate range for a clock source
2397+
* @clk: clock source
2398+
* @min: desired minimum clock rate in Hz, inclusive
2399+
* @max: desired maximum clock rate in Hz, inclusive
2400+
*
2401+
* Return: 0 for success or negative errno on failure.
2402+
*/
2403+
int clk_set_rate_range(struct clk *clk, unsigned long min, unsigned long max)
2404+
{
2405+
int ret;
2406+
2407+
if (!clk)
2408+
return 0;
2409+
2410+
clk_prepare_lock();
2411+
2412+
ret = clk_set_rate_range_nolock(clk, min, max);
2413+
23982414
clk_prepare_unlock();
23992415

24002416
return ret;
@@ -4348,9 +4364,10 @@ void __clk_put(struct clk *clk)
43484364
}
43494365

43504366
hlist_del(&clk->clks_node);
4351-
if (clk->min_rate > clk->core->req_rate ||
4352-
clk->max_rate < clk->core->req_rate)
4353-
clk_core_set_rate_nolock(clk->core, clk->core->req_rate);
4367+
4368+
/* If we had any boundaries on that clock, let's drop them. */
4369+
if (clk->min_rate > 0 || clk->max_rate < ULONG_MAX)
4370+
clk_set_rate_range_nolock(clk, 0, ULONG_MAX);
43544371

43554372
owner = clk->core->owner;
43564373
kref_put(&clk->core->ref, __clk_release);

drivers/clk/clk_test.c

Lines changed: 110 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -793,9 +793,66 @@ static void clk_range_test_multiple_set_range_rate_maximized(struct kunit *test)
793793
clk_put(clk);
794794
}
795795

796+
/*
797+
* Test that if we have several subsequent calls to
798+
* clk_set_rate_range(), across multiple users, the core will reevaluate
799+
* whether a new rate is needed, including when a user drop its clock.
800+
*
801+
* With clk_dummy_maximize_rate_ops, this means that the rate will
802+
* trail along the maximum as it evolves.
803+
*/
804+
static void clk_range_test_multiple_set_range_rate_put_maximized(struct kunit *test)
805+
{
806+
struct clk_dummy_context *ctx = test->priv;
807+
struct clk_hw *hw = &ctx->hw;
808+
struct clk *clk = clk_hw_get_clk(hw, NULL);
809+
struct clk *user1, *user2;
810+
unsigned long rate;
811+
812+
user1 = clk_hw_get_clk(hw, NULL);
813+
KUNIT_ASSERT_NOT_ERR_OR_NULL(test, user1);
814+
815+
user2 = clk_hw_get_clk(hw, NULL);
816+
KUNIT_ASSERT_NOT_ERR_OR_NULL(test, user2);
817+
818+
KUNIT_ASSERT_EQ(test,
819+
clk_set_rate(clk, DUMMY_CLOCK_RATE_2 + 1000),
820+
0);
821+
822+
KUNIT_ASSERT_EQ(test,
823+
clk_set_rate_range(user1,
824+
0,
825+
DUMMY_CLOCK_RATE_2),
826+
0);
827+
828+
rate = clk_get_rate(clk);
829+
KUNIT_ASSERT_GT(test, rate, 0);
830+
KUNIT_EXPECT_EQ(test, rate, DUMMY_CLOCK_RATE_2);
831+
832+
KUNIT_ASSERT_EQ(test,
833+
clk_set_rate_range(user2,
834+
0,
835+
DUMMY_CLOCK_RATE_1),
836+
0);
837+
838+
rate = clk_get_rate(clk);
839+
KUNIT_ASSERT_GT(test, rate, 0);
840+
KUNIT_EXPECT_EQ(test, rate, DUMMY_CLOCK_RATE_1);
841+
842+
clk_put(user2);
843+
844+
rate = clk_get_rate(clk);
845+
KUNIT_ASSERT_GT(test, rate, 0);
846+
KUNIT_EXPECT_EQ(test, rate, DUMMY_CLOCK_RATE_2);
847+
848+
clk_put(user1);
849+
clk_put(clk);
850+
}
851+
796852
static struct kunit_case clk_range_maximize_test_cases[] = {
797853
KUNIT_CASE(clk_range_test_set_range_rate_maximized),
798854
KUNIT_CASE(clk_range_test_multiple_set_range_rate_maximized),
855+
KUNIT_CASE(clk_range_test_multiple_set_range_rate_put_maximized),
799856
{}
800857
};
801858

@@ -913,9 +970,62 @@ static void clk_range_test_multiple_set_range_rate_minimized(struct kunit *test)
913970
clk_put(clk);
914971
}
915972

973+
/*
974+
* Test that if we have several subsequent calls to
975+
* clk_set_rate_range(), across multiple users, the core will reevaluate
976+
* whether a new rate is needed, including when a user drop its clock.
977+
*
978+
* With clk_dummy_minimize_rate_ops, this means that the rate will
979+
* trail along the minimum as it evolves.
980+
*/
981+
static void clk_range_test_multiple_set_range_rate_put_minimized(struct kunit *test)
982+
{
983+
struct clk_dummy_context *ctx = test->priv;
984+
struct clk_hw *hw = &ctx->hw;
985+
struct clk *clk = clk_hw_get_clk(hw, NULL);
986+
struct clk *user1, *user2;
987+
unsigned long rate;
988+
989+
user1 = clk_hw_get_clk(hw, NULL);
990+
KUNIT_ASSERT_NOT_ERR_OR_NULL(test, user1);
991+
992+
user2 = clk_hw_get_clk(hw, NULL);
993+
KUNIT_ASSERT_NOT_ERR_OR_NULL(test, user2);
994+
995+
KUNIT_ASSERT_EQ(test,
996+
clk_set_rate_range(user1,
997+
DUMMY_CLOCK_RATE_1,
998+
ULONG_MAX),
999+
0);
1000+
1001+
rate = clk_get_rate(clk);
1002+
KUNIT_ASSERT_GT(test, rate, 0);
1003+
KUNIT_EXPECT_EQ(test, rate, DUMMY_CLOCK_RATE_1);
1004+
1005+
KUNIT_ASSERT_EQ(test,
1006+
clk_set_rate_range(user2,
1007+
DUMMY_CLOCK_RATE_2,
1008+
ULONG_MAX),
1009+
0);
1010+
1011+
rate = clk_get_rate(clk);
1012+
KUNIT_ASSERT_GT(test, rate, 0);
1013+
KUNIT_EXPECT_EQ(test, rate, DUMMY_CLOCK_RATE_2);
1014+
1015+
clk_put(user2);
1016+
1017+
rate = clk_get_rate(clk);
1018+
KUNIT_ASSERT_GT(test, rate, 0);
1019+
KUNIT_EXPECT_EQ(test, rate, DUMMY_CLOCK_RATE_1);
1020+
1021+
clk_put(user1);
1022+
clk_put(clk);
1023+
}
1024+
9161025
static struct kunit_case clk_range_minimize_test_cases[] = {
9171026
KUNIT_CASE(clk_range_test_set_range_rate_minimized),
9181027
KUNIT_CASE(clk_range_test_multiple_set_range_rate_minimized),
1028+
KUNIT_CASE(clk_range_test_multiple_set_range_rate_put_minimized),
9191029
{}
9201030
};
9211031

0 commit comments

Comments
 (0)