Commit 859c2c7b authored by Stephen Boyd's avatar Stephen Boyd

Revert "clk: Drop the rate range on clk_put()"

This reverts commit 7dabfa2b. There are
multiple reports that this breaks boot on various systems. The common
theme is that orphan clks are having rates set on them when that isn't
expected. Let's revert it out for now so that -rc1 boots.
Reported-by: default avatarMarek Szyprowski <m.szyprowski@samsung.com>
Reported-by: default avatarTony Lindgren <tony@atomide.com>
Reported-by: default avatarAlexander Stein <alexander.stein@ew.tq-group.com>
Reported-by: default avatarNaresh Kamboju <naresh.kamboju@linaro.org>
Link: https://lore.kernel.org/r/366a0232-bb4a-c357-6aa8-636e398e05eb@samsung.com
Cc: Maxime Ripard <maxime@cerno.tech>
Signed-off-by: default avatarStephen Boyd <sboyd@kernel.org>
Link: https://lore.kernel.org/r/20220403022818.39572-1-sboyd@kernel.org
parent cf683abd
...@@ -2332,15 +2332,19 @@ int clk_set_rate_exclusive(struct clk *clk, unsigned long rate) ...@@ -2332,15 +2332,19 @@ int clk_set_rate_exclusive(struct clk *clk, unsigned long rate)
} }
EXPORT_SYMBOL_GPL(clk_set_rate_exclusive); EXPORT_SYMBOL_GPL(clk_set_rate_exclusive);
static int clk_set_rate_range_nolock(struct clk *clk, /**
unsigned long min, * clk_set_rate_range - set a rate range for a clock source
unsigned long max) * @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; int ret = 0;
unsigned long old_min, old_max, rate; unsigned long old_min, old_max, rate;
lockdep_assert_held(&prepare_lock);
if (!clk) if (!clk)
return 0; return 0;
...@@ -2353,6 +2357,8 @@ static int clk_set_rate_range_nolock(struct clk *clk, ...@@ -2353,6 +2357,8 @@ static int clk_set_rate_range_nolock(struct clk *clk,
return -EINVAL; return -EINVAL;
} }
clk_prepare_lock();
if (clk->exclusive_count) if (clk->exclusive_count)
clk_core_rate_unprotect(clk->core); clk_core_rate_unprotect(clk->core);
...@@ -2396,28 +2402,6 @@ static int clk_set_rate_range_nolock(struct clk *clk, ...@@ -2396,28 +2402,6 @@ static int clk_set_rate_range_nolock(struct clk *clk,
if (clk->exclusive_count) if (clk->exclusive_count)
clk_core_rate_protect(clk->core); 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(); clk_prepare_unlock();
return ret; return ret;
...@@ -4419,7 +4403,9 @@ void __clk_put(struct clk *clk) ...@@ -4419,7 +4403,9 @@ void __clk_put(struct clk *clk)
} }
hlist_del(&clk->clks_node); 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; owner = clk->core->owner;
kref_put(&clk->core->ref, __clk_release); kref_put(&clk->core->ref, __clk_release);
......
...@@ -760,65 +760,9 @@ static void clk_range_test_multiple_set_range_rate_maximized(struct kunit *test) ...@@ -760,65 +760,9 @@ static void clk_range_test_multiple_set_range_rate_maximized(struct kunit *test)
clk_put(user1); 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[] = { static struct kunit_case clk_range_maximize_test_cases[] = {
KUNIT_CASE(clk_range_test_set_range_rate_maximized), 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_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) ...@@ -933,61 +877,9 @@ static void clk_range_test_multiple_set_range_rate_minimized(struct kunit *test)
clk_put(user1); 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[] = { static struct kunit_case clk_range_minimize_test_cases[] = {
KUNIT_CASE(clk_range_test_set_range_rate_minimized), 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_minimized),
KUNIT_CASE(clk_range_test_multiple_set_range_rate_put_minimized),
{} {}
}; };
......
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