diff mbox

[V3,01/14] cpufreq: Create for_each_{in}active_policy()

Message ID 79f880aba9ad5159e070f2ca172139cb2c254430.1431065963.git.viresh.kumar@linaro.org
State New
Headers show

Commit Message

Viresh Kumar May 8, 2015, 6:23 a.m. UTC
policy->cpus is cleared unconditionally now on hotplug-out of a CPU and
it can be checked to know if a policy is active or not. Create helper
routines to iterate over all active/inactive policies, based on
policy->cpus field.

Replace all instances of for_each_policy() with for_each_active_policy()
to make them iterate only for active policies. (We haven't made changes
yet to keep inactive policies in the same list, but that will be
followed in a later patch).

Signed-off-by: Viresh Kumar <viresh.kumar@linaro.org>
---
 drivers/cpufreq/cpufreq.c | 82 +++++++++++++++++++++++++++++++++++++++++------
 1 file changed, 73 insertions(+), 9 deletions(-)

Comments

Viresh Kumar May 9, 2015, 2:27 a.m. UTC | #1
Thanks for the really detailed review ..

On 9 May 2015 at 03:16, Rafael J. Wysocki <rjw@rjwysocki.net> wrote:
> On Friday, May 08, 2015 11:53:44 AM Viresh Kumar wrote:

>> +/*
>> + * Finds Next Acive/Inactive policy
>> + *
>> + * policy: Previous policy.
>> + * active: Looking for active policy (true) or Inactive policy (false).
>> + */
>
> A proper kerneldoc, please.

I thought its an internal function which we may not want to put into
kernel-doc and so did it this way. Will take care in future ..

>> +static struct cpufreq_policy *next_policy(struct cpufreq_policy *policy,
>> +                                       bool active)
>> +{
>> +     do {
>> +             if (likely(policy))
>
> The likely() thing looks like an attempted overoptimization.  I wouldn't use it.

ok

>> +                     policy = list_next_entry(policy, policy_list);
>> +             else
>> +                     policy = list_first_entry(&cpufreq_policy_list,
>> +                                               typeof(*policy), policy_list);
>> +
>> +             /* No more policies */
>> +             if (&policy->policy_list == &cpufreq_policy_list)
>
> Why does this ignore the 'active' arg?

Because what we are checking here is that the list is finished or not.
The 'policy' we are returning here is not a real policy, but a
not-to-be-used structure over the list HEAD.

>> + * Iterate over online CPUs policies
>
> "CPU policies" would look better IMO.

Sure.

>> + * Explanation:
>> + * - expr1: marks __temp NULL and gets the first __active policy.
>> + * - expr2: checks if list is finished, if yes then it sets __policy to the last
>> + *       __active policy and returns 0 to end the loop.
>> + * - expr3: preserves last __active policy and gets the next one.
>
> I'd expect this to describe the arguments rather.  Also the code is rather
> difficult to follow.
>
> The XOR thing is rather an unnecessary trick (it acts on bools but quite
> directly assumes them to be integers with the lowest bit representing the
> value) and you can do "active == !policy_is_inactive(policy)" instead.
>
> So if you separate the last check as
>
> static bool suitable_policy(struct cpufreq_policy *policy, bool active)
> {
>         return active == !policy_is_inactive(policy);
> }
>
> then you can introduce
>
> static struct cpufreq_policy *first_policy(bool active)
> {
>         struct cpufreq_policy *policy;
>
>         policy = list_first_entry(&cpufreq_policy_list, typeof(*policy), policy_list);
>         if (!suitable_policy(policy, active))
>                 policy = next_policy(policy, active);
>
>         return policy;
> }
>
> and then next_policy() becomes much simpler and, moreover, this:
>
>> + */
>> +#define __for_each_active_policy(__policy, __temp, __active)         \
>> +     for (__temp = NULL, __policy = next_policy(NULL, __active);     \
>> +          &__policy->policy_list != &cpufreq_policy_list ||          \
>> +          ((__policy = __temp) && 0);                                \
>> +          __temp = __policy, __policy = next_policy(__policy, __active))
>
> can be rewritten as:
>
> #define __for_each_active_policy(__policy, __active)            \
>         for (__policy = first_policy(__active); __policy;       \
>              __policy = next_policy(__policy, __active))
>
> and you don't need to explain what it does even.  Of course, next_policy()
> has to return 'false' when it can't find anything suitable, but that shouldn't
> be too difficult to arrange I suppose?
>
> Or if you need __temp because the object pointed to by __policy can go away,
> you can follow the design of list_for_each_entry_safe() here.
>
>> +
>>  #define for_each_policy(__policy)                            \
>>       list_for_each_entry(__policy, &cpufreq_policy_list, policy_list)
>>
>> +/*
>> + * Routines to iterate over active or inactive policies
>> + * __policy: next active/inactive policy will be returned in this.
>> + * __temp: for internal purpose, not to be used by caller.
>> + */
>> +#define for_each_active_policy(__policy, __temp) __for_each_active_policy(__policy, __temp, true)
>> +#define for_each_inactive_policy(__policy, __temp) __for_each_active_policy(__policy, __temp, false)
>
> I must admit to having a problem with this definition.
>
>         #define for_each_inactive_something(X)  __for_each_active_something(X)
>
> looks really confusing.
>
> Maybe rename __for_each_active_policy() to __for_each_suitable_policy()?
>
>> +
>>  /* Iterate over governors */
>>  static LIST_HEAD(cpufreq_governor_list);
>>  #define for_each_governor(__governor)                                \
>> @@ -1142,7 +1206,7 @@ static int cpufreq_add_dev(struct device *dev, struct subsys_interface *sif)
>>  {
>>       unsigned int j, cpu = dev->id;
>>       int ret = -ENOMEM;
>> -     struct cpufreq_policy *policy;
>> +     struct cpufreq_policy *policy, *tpolicy;
>
> I'd just use "tmp" or "aux" instead of "tpolicy".

All accepted..
--
To unsubscribe from this list: send the line "unsubscribe linux-pm" in
the body of a message to majordomo@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html
Viresh Kumar May 12, 2015, 6:04 a.m. UTC | #2
On 08-05-15, 23:46, Rafael J. Wysocki wrote:
> On Friday, May 08, 2015 11:53:44 AM Viresh Kumar wrote:

> > +#define __for_each_active_policy(__policy, __temp, __active)		\
> > +	for (__temp = NULL, __policy = next_policy(NULL, __active);	\
> > +	     &__policy->policy_list != &cpufreq_policy_list ||		\
> > +	     ((__policy = __temp) && 0);				\
> > +	     __temp = __policy, __policy = next_policy(__policy, __active))
> 
> can be rewritten as:
> 
> #define __for_each_active_policy(__policy, __active)		\
> 	for (__policy = first_policy(__active);	__policy;	\
> 	     __policy = next_policy(__policy, __active))
> 
> and you don't need to explain what it does even.  Of course, next_policy()
> has to return 'false' when it can't find anything suitable, but that shouldn't
> be too difficult to arrange I suppose?
> 
> Or if you need __temp because the object pointed to by __policy can go away,
> you can follow the design of list_for_each_entry_safe() here.

I wasn't using __temp to be safe, but to make sure that the loop
points to a 'active' policy at the end. But that isn't required
anymore as the only call site that required this, is fixed in a better
way:

c75de0ac0756 ("cpufreq: Schedule work for the first-online CPU on resume")
--
To unsubscribe from this list: send the line "unsubscribe linux-pm" in
the body of a message to majordomo@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html
diff mbox

Patch

diff --git a/drivers/cpufreq/cpufreq.c b/drivers/cpufreq/cpufreq.c
index 8cf0c0e7aea8..9229e7f81673 100644
--- a/drivers/cpufreq/cpufreq.c
+++ b/drivers/cpufreq/cpufreq.c
@@ -32,11 +32,75 @@ 
 #include <trace/events/power.h>
 
 /* Macros to iterate over lists */
-/* Iterate over online CPUs policies */
 static LIST_HEAD(cpufreq_policy_list);
+
+static inline bool policy_is_inactive(struct cpufreq_policy *policy)
+{
+	return cpumask_empty(policy->cpus);
+}
+
+/*
+ * Finds Next Acive/Inactive policy
+ *
+ * policy: Previous policy.
+ * active: Looking for active policy (true) or Inactive policy (false).
+ */
+static struct cpufreq_policy *next_policy(struct cpufreq_policy *policy,
+					  bool active)
+{
+	do {
+		if (likely(policy))
+			policy = list_next_entry(policy, policy_list);
+		else
+			policy = list_first_entry(&cpufreq_policy_list,
+						  typeof(*policy), policy_list);
+
+		/* No more policies */
+		if (&policy->policy_list == &cpufreq_policy_list)
+			return policy;
+
+		/*
+		 * Table to explains logic behind following expression:
+		 *
+		 *	Active		policy_is_inactive	Result
+		 *						(policy or next)
+		 *
+		 *	0		0			next
+		 *	0		1			policy
+		 *	1		0			policy
+		 *	1		1			next
+		 */
+	} while (!(active ^ policy_is_inactive(policy)));
+
+	return policy;
+}
+
+/*
+ * Iterate over online CPUs policies
+ *
+ * Explanation:
+ * - expr1: marks __temp NULL and gets the first __active policy.
+ * - expr2: checks if list is finished, if yes then it sets __policy to the last
+ *	    __active policy and returns 0 to end the loop.
+ * - expr3: preserves last __active policy and gets the next one.
+ */
+#define __for_each_active_policy(__policy, __temp, __active)		\
+	for (__temp = NULL, __policy = next_policy(NULL, __active);	\
+	     &__policy->policy_list != &cpufreq_policy_list ||		\
+	     ((__policy = __temp) && 0);				\
+	     __temp = __policy, __policy = next_policy(__policy, __active))
+
 #define for_each_policy(__policy)				\
 	list_for_each_entry(__policy, &cpufreq_policy_list, policy_list)
 
+/*
+ * Routines to iterate over active or inactive policies
+ * __policy: next active/inactive policy will be returned in this.
+ * __temp: for internal purpose, not to be used by caller.
+ */
+#define for_each_active_policy(__policy, __temp) __for_each_active_policy(__policy, __temp, true)
+#define for_each_inactive_policy(__policy, __temp) __for_each_active_policy(__policy, __temp, false)
+
 /* Iterate over governors */
 static LIST_HEAD(cpufreq_governor_list);
 #define for_each_governor(__governor)				\
@@ -1142,7 +1206,7 @@  static int cpufreq_add_dev(struct device *dev, struct subsys_interface *sif)
 {
 	unsigned int j, cpu = dev->id;
 	int ret = -ENOMEM;
-	struct cpufreq_policy *policy;
+	struct cpufreq_policy *policy, *tpolicy;
 	unsigned long flags;
 	bool recover_policy = cpufreq_suspended;
 
@@ -1156,7 +1220,7 @@  static int cpufreq_add_dev(struct device *dev, struct subsys_interface *sif)
 
 	/* Check if this CPU already has a policy to manage it */
 	read_lock_irqsave(&cpufreq_driver_lock, flags);
-	for_each_policy(policy) {
+	for_each_active_policy(policy, tpolicy) {
 		if (cpumask_test_cpu(cpu, policy->related_cpus)) {
 			read_unlock_irqrestore(&cpufreq_driver_lock, flags);
 			ret = cpufreq_add_policy_cpu(policy, cpu, dev);
@@ -1664,7 +1728,7 @@  EXPORT_SYMBOL(cpufreq_generic_suspend);
  */
 void cpufreq_suspend(void)
 {
-	struct cpufreq_policy *policy;
+	struct cpufreq_policy *policy, *tpolicy;
 
 	if (!cpufreq_driver)
 		return;
@@ -1674,7 +1738,7 @@  void cpufreq_suspend(void)
 
 	pr_debug("%s: Suspending Governors\n", __func__);
 
-	for_each_policy(policy) {
+	for_each_active_policy(policy, tpolicy) {
 		if (__cpufreq_governor(policy, CPUFREQ_GOV_STOP))
 			pr_err("%s: Failed to stop governor for policy: %p\n",
 				__func__, policy);
@@ -1696,7 +1760,7 @@  void cpufreq_suspend(void)
  */
 void cpufreq_resume(void)
 {
-	struct cpufreq_policy *policy;
+	struct cpufreq_policy *policy, *tpolicy;
 
 	if (!cpufreq_driver)
 		return;
@@ -1708,7 +1772,7 @@  void cpufreq_resume(void)
 
 	pr_debug("%s: Resuming Governors\n", __func__);
 
-	for_each_policy(policy) {
+	for_each_active_policy(policy, tpolicy) {
 		if (cpufreq_driver->resume && cpufreq_driver->resume(policy))
 			pr_err("%s: Failed to resume driver: %p\n", __func__,
 				policy);
@@ -2351,10 +2415,10 @@  static struct notifier_block __refdata cpufreq_cpu_notifier = {
 static int cpufreq_boost_set_sw(int state)
 {
 	struct cpufreq_frequency_table *freq_table;
-	struct cpufreq_policy *policy;
+	struct cpufreq_policy *policy, *tpolicy;
 	int ret = -EINVAL;
 
-	for_each_policy(policy) {
+	for_each_active_policy(policy, tpolicy) {
 		freq_table = cpufreq_frequency_get_table(policy->cpu);
 		if (freq_table) {
 			ret = cpufreq_frequency_table_cpuinfo(policy,