Skip to content

Commit 948fb09

Browse files
mripardbebarino
authored andcommitted
clk: Always clamp the rounded rate
The current core while setting the min and max rate properly in the clk_request structure will not make sure that the requested rate is within these boundaries, leaving it to each and every driver to make sure it is. It's not clear if this was on purpose or not, but this introduces some inconsistencies within the API. For example, a user setting a range and then calling clk_round_rate() with a value outside of that range will get the same value back (ignoring any driver adjustements), effectively ignoring the range that was just set. Another one, arguably worse, is that it also makes clk_round_rate() and clk_set_rate() behave differently if there's a range and the rate being used for both is outside that range. As we have seen, the rate will be returned unchanged by clk_round_rate(), but clk_set_rate() will error out returning -EINVAL. Let's make sure the framework will always clamp the rate to the current range found on the clock, which will fix both these inconsistencies. Signed-off-by: Maxime Ripard <[email protected]> Link: https://lore.kernel.org/r/[email protected] Signed-off-by: Stephen Boyd <[email protected]>
1 parent 10c46f2 commit 948fb09

File tree

2 files changed

+34
-18
lines changed

2 files changed

+34
-18
lines changed

drivers/clk/clk.c

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1348,6 +1348,8 @@ static int clk_core_determine_round_nolock(struct clk_core *core,
13481348
if (!core)
13491349
return 0;
13501350

1351+
req->rate = clamp(req->rate, req->min_rate, req->max_rate);
1352+
13511353
/*
13521354
* At this point, core protection will be disabled
13531355
* - if the provider is not protected at all

drivers/clk/clk_test.c

Lines changed: 32 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -310,8 +310,7 @@ static void clk_range_test_multiple_disjoints_range(struct kunit *test)
310310

311311
/*
312312
* Test that if our clock has some boundaries and we try to round a rate
313-
* lower than the minimum, the returned rate won't be affected by the
314-
* boundaries.
313+
* lower than the minimum, the returned rate will be within range.
315314
*/
316315
static void clk_range_test_set_range_round_rate_lower(struct kunit *test)
317316
{
@@ -328,34 +327,42 @@ static void clk_range_test_set_range_round_rate_lower(struct kunit *test)
328327

329328
rate = clk_round_rate(clk, DUMMY_CLOCK_RATE_1 - 1000);
330329
KUNIT_ASSERT_GT(test, rate, 0);
331-
KUNIT_EXPECT_EQ(test, rate, DUMMY_CLOCK_RATE_1 - 1000);
330+
KUNIT_EXPECT_GE(test, rate, DUMMY_CLOCK_RATE_1);
331+
KUNIT_EXPECT_LE(test, rate, DUMMY_CLOCK_RATE_2);
332332
}
333333

334334
/*
335335
* Test that if our clock has some boundaries and we try to set a rate
336-
* lower than the minimum, we'll get an error.
336+
* higher than the maximum, the new rate will be within range.
337337
*/
338338
static void clk_range_test_set_range_set_rate_lower(struct kunit *test)
339339
{
340340
struct clk_dummy_context *ctx = test->priv;
341341
struct clk_hw *hw = &ctx->hw;
342342
struct clk *clk = hw->clk;
343+
unsigned long rate;
343344

344345
KUNIT_ASSERT_EQ(test,
345346
clk_set_rate_range(clk,
346347
DUMMY_CLOCK_RATE_1,
347348
DUMMY_CLOCK_RATE_2),
348349
0);
349350

350-
KUNIT_ASSERT_LT(test,
351+
KUNIT_ASSERT_EQ(test,
351352
clk_set_rate(clk, DUMMY_CLOCK_RATE_1 - 1000),
352353
0);
354+
355+
rate = clk_get_rate(clk);
356+
KUNIT_ASSERT_GT(test, rate, 0);
357+
KUNIT_EXPECT_GE(test, rate, DUMMY_CLOCK_RATE_1);
358+
KUNIT_EXPECT_LE(test, rate, DUMMY_CLOCK_RATE_2);
353359
}
354360

355361
/*
356362
* Test that if our clock has some boundaries and we try to round and
357-
* set a rate lower than the minimum, the values won't be consistent
358-
* between clk_round_rate() and clk_set_rate().
363+
* set a rate lower than the minimum, the rate returned by
364+
* clk_round_rate() will be consistent with the new rate set by
365+
* clk_set_rate().
359366
*/
360367
static void clk_range_test_set_range_set_round_rate_consistent_lower(struct kunit *test)
361368
{
@@ -373,17 +380,16 @@ static void clk_range_test_set_range_set_round_rate_consistent_lower(struct kuni
373380
rounded = clk_round_rate(clk, DUMMY_CLOCK_RATE_1 - 1000);
374381
KUNIT_ASSERT_GT(test, rounded, 0);
375382

376-
KUNIT_EXPECT_LT(test,
383+
KUNIT_ASSERT_EQ(test,
377384
clk_set_rate(clk, DUMMY_CLOCK_RATE_1 - 1000),
378385
0);
379386

380-
KUNIT_EXPECT_NE(test, rounded, clk_get_rate(clk));
387+
KUNIT_EXPECT_EQ(test, rounded, clk_get_rate(clk));
381388
}
382389

383390
/*
384391
* Test that if our clock has some boundaries and we try to round a rate
385-
* higher than the maximum, the returned rate won't be affected by the
386-
* boundaries.
392+
* higher than the maximum, the returned rate will be within range.
387393
*/
388394
static void clk_range_test_set_range_round_rate_higher(struct kunit *test)
389395
{
@@ -400,34 +406,42 @@ static void clk_range_test_set_range_round_rate_higher(struct kunit *test)
400406

401407
rate = clk_round_rate(clk, DUMMY_CLOCK_RATE_2 + 1000);
402408
KUNIT_ASSERT_GT(test, rate, 0);
403-
KUNIT_EXPECT_EQ(test, rate, DUMMY_CLOCK_RATE_2 + 1000);
409+
KUNIT_EXPECT_GE(test, rate, DUMMY_CLOCK_RATE_1);
410+
KUNIT_EXPECT_LE(test, rate, DUMMY_CLOCK_RATE_2);
404411
}
405412

406413
/*
407414
* Test that if our clock has some boundaries and we try to set a rate
408-
* lower than the maximum, we'll get an error.
415+
* higher than the maximum, the new rate will be within range.
409416
*/
410417
static void clk_range_test_set_range_set_rate_higher(struct kunit *test)
411418
{
412419
struct clk_dummy_context *ctx = test->priv;
413420
struct clk_hw *hw = &ctx->hw;
414421
struct clk *clk = hw->clk;
422+
unsigned long rate;
415423

416424
KUNIT_ASSERT_EQ(test,
417425
clk_set_rate_range(clk,
418426
DUMMY_CLOCK_RATE_1,
419427
DUMMY_CLOCK_RATE_2),
420428
0);
421429

422-
KUNIT_ASSERT_LT(test,
430+
KUNIT_ASSERT_EQ(test,
423431
clk_set_rate(clk, DUMMY_CLOCK_RATE_2 + 1000),
424432
0);
433+
434+
rate = clk_get_rate(clk);
435+
KUNIT_ASSERT_GT(test, rate, 0);
436+
KUNIT_EXPECT_GE(test, rate, DUMMY_CLOCK_RATE_1);
437+
KUNIT_EXPECT_LE(test, rate, DUMMY_CLOCK_RATE_2);
425438
}
426439

427440
/*
428441
* Test that if our clock has some boundaries and we try to round and
429-
* set a rate higher than the maximum, the values won't be consistent
430-
* between clk_round_rate() and clk_set_rate().
442+
* set a rate higher than the maximum, the rate returned by
443+
* clk_round_rate() will be consistent with the new rate set by
444+
* clk_set_rate().
431445
*/
432446
static void clk_range_test_set_range_set_round_rate_consistent_higher(struct kunit *test)
433447
{
@@ -445,11 +459,11 @@ static void clk_range_test_set_range_set_round_rate_consistent_higher(struct kun
445459
rounded = clk_round_rate(clk, DUMMY_CLOCK_RATE_2 + 1000);
446460
KUNIT_ASSERT_GT(test, rounded, 0);
447461

448-
KUNIT_EXPECT_LT(test,
462+
KUNIT_ASSERT_EQ(test,
449463
clk_set_rate(clk, DUMMY_CLOCK_RATE_2 + 1000),
450464
0);
451465

452-
KUNIT_EXPECT_NE(test, rounded, clk_get_rate(clk));
466+
KUNIT_EXPECT_EQ(test, rounded, clk_get_rate(clk));
453467
}
454468

455469
/*

0 commit comments

Comments
 (0)