clk: test: Test clk_set_rate_range on orphan mux

A bug recently affected the Tegra30 where calling clk_set_rate_range()
on a clock would make it change its rate to the minimum.

This was due to the clock in question being a mux that was orphan at
registration, which lead to the clk_core req_rate being 0, and the
clk_set_rate_range() function then calling clk_set_rate() with req_rate,
effectively making that clock running at the minimum rate allowed, even
though the initial rate was within that range.

Make a test suite to create a mux initially orphan, and then make sure
that if our clock rate was initially within a given range, then
enforcing that range won't affect it.

Signed-off-by: Maxime Ripard <maxime@cerno.tech>
Link: https://lore.kernel.org/r/20220325161144.1901695-3-maxime@cerno.tech
Signed-off-by: Stephen Boyd <sboyd@kernel.org>

authored by Maxime Ripard and committed by Stephen Boyd 481f541c 5f7e2af0

+105
+105
drivers/clk/clk_test.c
··· 72 72 return 0; 73 73 } 74 74 75 + static int clk_dummy_single_set_parent(struct clk_hw *hw, u8 index) 76 + { 77 + if (index >= clk_hw_get_num_parents(hw)) 78 + return -EINVAL; 79 + 80 + return 0; 81 + } 82 + 83 + static u8 clk_dummy_single_get_parent(struct clk_hw *hw) 84 + { 85 + return 0; 86 + } 87 + 75 88 static const struct clk_ops clk_dummy_rate_ops = { 76 89 .recalc_rate = clk_dummy_recalc_rate, 77 90 .determine_rate = clk_dummy_determine_rate, ··· 101 88 .recalc_rate = clk_dummy_recalc_rate, 102 89 .determine_rate = clk_dummy_minimize_rate, 103 90 .set_rate = clk_dummy_set_rate, 91 + }; 92 + 93 + static const struct clk_ops clk_dummy_single_parent_ops = { 94 + .set_parent = clk_dummy_single_set_parent, 95 + .get_parent = clk_dummy_single_get_parent, 104 96 }; 105 97 106 98 static int clk_test_init_with_ops(struct kunit *test, const struct clk_ops *ops) ··· 255 237 .init = clk_test_init, 256 238 .exit = clk_test_exit, 257 239 .test_cases = clk_test_cases, 240 + }; 241 + 242 + struct clk_single_parent_ctx { 243 + struct clk_dummy_context parent_ctx; 244 + struct clk_hw hw; 245 + }; 246 + 247 + static int clk_orphan_transparent_single_parent_mux_test_init(struct kunit *test) 248 + { 249 + struct clk_single_parent_ctx *ctx; 250 + struct clk_init_data init = { }; 251 + const char * const parents[] = { "orphan_parent" }; 252 + int ret; 253 + 254 + ctx = kunit_kzalloc(test, sizeof(*ctx), GFP_KERNEL); 255 + if (!ctx) 256 + return -ENOMEM; 257 + test->priv = ctx; 258 + 259 + init.name = "test_orphan_dummy_parent"; 260 + init.ops = &clk_dummy_single_parent_ops; 261 + init.parent_names = parents; 262 + init.num_parents = ARRAY_SIZE(parents); 263 + init.flags = CLK_SET_RATE_PARENT; 264 + ctx->hw.init = &init; 265 + 266 + ret = clk_hw_register(NULL, &ctx->hw); 267 + if (ret) 268 + return ret; 269 + 270 + memset(&init, 0, sizeof(init)); 271 + init.name = "orphan_parent"; 272 + init.ops = &clk_dummy_rate_ops; 273 + ctx->parent_ctx.hw.init = &init; 274 + ctx->parent_ctx.rate = DUMMY_CLOCK_INIT_RATE; 275 + 276 + ret = clk_hw_register(NULL, &ctx->parent_ctx.hw); 277 + if (ret) 278 + return ret; 279 + 280 + return 0; 281 + } 282 + 283 + static void clk_orphan_transparent_single_parent_mux_test_exit(struct kunit *test) 284 + { 285 + struct clk_single_parent_ctx *ctx = test->priv; 286 + 287 + clk_hw_unregister(&ctx->hw); 288 + clk_hw_unregister(&ctx->parent_ctx.hw); 289 + } 290 + 291 + /* 292 + * Test that a mux-only clock, with an initial rate within a range, 293 + * will still have the same rate after the range has been enforced. 294 + */ 295 + static void clk_test_orphan_transparent_parent_mux_set_range(struct kunit *test) 296 + { 297 + struct clk_single_parent_ctx *ctx = test->priv; 298 + struct clk_hw *hw = &ctx->hw; 299 + struct clk *clk = hw->clk; 300 + unsigned long rate, new_rate; 301 + 302 + rate = clk_get_rate(clk); 303 + KUNIT_ASSERT_GT(test, rate, 0); 304 + 305 + KUNIT_ASSERT_EQ(test, 306 + clk_set_rate_range(clk, 307 + ctx->parent_ctx.rate - 1000, 308 + ctx->parent_ctx.rate + 1000), 309 + 0); 310 + 311 + new_rate = clk_get_rate(clk); 312 + KUNIT_ASSERT_GT(test, new_rate, 0); 313 + KUNIT_EXPECT_EQ(test, rate, new_rate); 314 + } 315 + 316 + static struct kunit_case clk_orphan_transparent_single_parent_mux_test_cases[] = { 317 + KUNIT_CASE(clk_test_orphan_transparent_parent_mux_set_range), 318 + {} 319 + }; 320 + 321 + static struct kunit_suite clk_orphan_transparent_single_parent_test_suite = { 322 + .name = "clk-orphan-transparent-single-parent-test", 323 + .init = clk_orphan_transparent_single_parent_mux_test_init, 324 + .exit = clk_orphan_transparent_single_parent_mux_test_exit, 325 + .test_cases = clk_orphan_transparent_single_parent_mux_test_cases, 258 326 }; 259 327 260 328 /* ··· 892 788 893 789 kunit_test_suites( 894 790 &clk_test_suite, 791 + &clk_orphan_transparent_single_parent_test_suite, 895 792 &clk_range_test_suite, 896 793 &clk_range_maximize_test_suite, 897 794 &clk_range_minimize_test_suite