]> git.ipfire.org Git - thirdparty/linux.git/commitdiff
cpufreq: Add cpufreq_cpu_acquire() and cpufreq_cpu_release()
authorRafael J. Wysocki <rafael.j.wysocki@intel.com>
Tue, 26 Mar 2019 11:16:58 +0000 (12:16 +0100)
committerRafael J. Wysocki <rafael.j.wysocki@intel.com>
Mon, 1 Apr 2019 21:43:05 +0000 (23:43 +0200)
It sometimes is necessary to find a cpufreq policy for a given CPU
and acquire its rwsem (for writing) immediately after that, so
introduce cpufreq_cpu_acquire() as a helper for that and the
complementary cpufreq_cpu_release().

Make cpufreq_update_policy() use the new functions.

Signed-off-by: Rafael J. Wysocki <rafael.j.wysocki@intel.com>
Acked-by: Viresh Kumar <viresh.kumar@linaro.org>
drivers/cpufreq/cpufreq.c

index bb63347f6af14b37bb17b274566a9dcec102eb98..d8fc395af7737af030a4043b9025f25d9539092c 100644 (file)
@@ -250,6 +250,51 @@ void cpufreq_cpu_put(struct cpufreq_policy *policy)
 }
 EXPORT_SYMBOL_GPL(cpufreq_cpu_put);
 
+/**
+ * cpufreq_cpu_release - Unlock a policy and decrement its usage counter.
+ * @policy: cpufreq policy returned by cpufreq_cpu_acquire().
+ */
+static void cpufreq_cpu_release(struct cpufreq_policy *policy)
+{
+       if (WARN_ON(!policy))
+               return;
+
+       lockdep_assert_held(&policy->rwsem);
+
+       up_write(&policy->rwsem);
+
+       cpufreq_cpu_put(policy);
+}
+
+/**
+ * cpufreq_cpu_acquire - Find policy for a CPU, mark it as busy and lock it.
+ * @cpu: CPU to find the policy for.
+ *
+ * Call cpufreq_cpu_get() to get a reference on the cpufreq policy for @cpu and
+ * if the policy returned by it is not NULL, acquire its rwsem for writing.
+ * Return the policy if it is active or release it and return NULL otherwise.
+ *
+ * The policy returned by this function has to be released with the help of
+ * cpufreq_cpu_release() in order to release its rwsem and balance its usage
+ * counter properly.
+ */
+static struct cpufreq_policy *cpufreq_cpu_acquire(unsigned int cpu)
+{
+       struct cpufreq_policy *policy = cpufreq_cpu_get(cpu);
+
+       if (!policy)
+               return NULL;
+
+       down_write(&policy->rwsem);
+
+       if (policy_is_inactive(policy)) {
+               cpufreq_cpu_release(policy);
+               return NULL;
+       }
+
+       return policy;
+}
+
 /*********************************************************************
  *            EXTERNALLY AFFECTING FREQUENCY CHANGES                 *
  *********************************************************************/
@@ -2337,17 +2382,12 @@ static int cpufreq_set_policy(struct cpufreq_policy *policy,
  */
 void cpufreq_update_policy(unsigned int cpu)
 {
-       struct cpufreq_policy *policy = cpufreq_cpu_get(cpu);
+       struct cpufreq_policy *policy = cpufreq_cpu_acquire(cpu);
        struct cpufreq_policy new_policy;
 
        if (!policy)
                return;
 
-       down_write(&policy->rwsem);
-
-       if (policy_is_inactive(policy))
-               goto unlock;
-
        /*
         * BIOS might change freq behind our back
         * -> ask driver for current freq and notify governors about a change
@@ -2364,9 +2404,7 @@ void cpufreq_update_policy(unsigned int cpu)
        cpufreq_set_policy(policy, &new_policy);
 
 unlock:
-       up_write(&policy->rwsem);
-
-       cpufreq_cpu_put(policy);
+       cpufreq_cpu_release(policy);
 }
 EXPORT_SYMBOL(cpufreq_update_policy);