summary refs log tree commit diff
diff options
context:
space:
mode:
authorLinus Torvalds <torvalds@linux-foundation.org>2022-04-03 12:21:14 -0700
committerLinus Torvalds <torvalds@linux-foundation.org>2022-04-03 12:21:14 -0700
commit34a53ff911eb30629baad788fbed892f711bdd3e (patch)
treea6345810457d933d4dfa9cb4871e5c4bd5aa5854
parent8b5656bc4e3707da642cb4a9126f4849fb518423 (diff)
parent859c2c7b1d0623a6f523f970043db85ce0e5aa60 (diff)
downloadlinux-34a53ff911eb30629baad788fbed892f711bdd3e.tar.gz
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.c42
-rw-r--r--drivers/clk/clk_test.c108
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),
 	{}
 };