diff mbox series

[v5,5/8] cpufreq: Add an interface to mark inefficient frequencies

Message ID 1629966944-439570-6-git-send-email-vincent.donnefort@arm.com
State New
Headers show
Series inefficient OPPs | expand

Commit Message

Vincent Donnefort Aug. 26, 2021, 8:35 a.m. UTC
Some SoCs such as the sd855 have OPPs within the same policy whose cost is
higher than others with a higher frequency. Those OPPs are inefficients
and it might be interesting for a governor to not use them.

Adding a flag, CPUFREQ_INEFFICIENT_FREQ, to mark such OPPs into the
frequency table, as well as a new cpufreq_frequency_table member
"efficient". This new member allows CPUFreq to resolve an inefficient
frequency to an efficient one.

Efficient frequencies point to themselves. The efficiency resolution must
check it doesn't break the policy maximum.

Signed-off-by: Vincent Donnefort <vincent.donnefort@arm.com>

Comments

kernel test robot Aug. 26, 2021, 5:20 p.m. UTC | #1
Hi Vincent,

Thank you for the patch! Yet something to improve:

[auto build test ERROR on next-20210825]
[cannot apply to pm/linux-next linus/master v5.14-rc7 v5.14-rc6 v5.14-rc5 v5.14-rc7]
[If your patch is applied to the wrong git tree, kindly drop us a note.
And when submitting patch, we suggest to use '--base' as documented in
https://git-scm.com/docs/git-format-patch]

url:    https://github.com/0day-ci/linux/commits/Vincent-Donnefort/inefficient-OPPs/20210826-163705
base:    7636510f976d75b860848884169ba985c8f844d8
config: i386-randconfig-r025-20210826 (attached as .config)
compiler: clang version 14.0.0 (https://github.com/llvm/llvm-project ea08c4cd1c0869ec5024a8bb3f5cdf06ab03ae83)
reproduce (this is a W=1 build):
        wget https://raw.githubusercontent.com/intel/lkp-tests/master/sbin/make.cross -O ~/bin/make.cross
        chmod +x ~/bin/make.cross
        # https://github.com/0day-ci/linux/commit/ed31a82b6d4abef95e8c50df33f826175cb6b6de
        git remote add linux-review https://github.com/0day-ci/linux
        git fetch --no-tags linux-review Vincent-Donnefort/inefficient-OPPs/20210826-163705
        git checkout ed31a82b6d4abef95e8c50df33f826175cb6b6de
        # save the attached .config to linux build tree
        COMPILER_INSTALL_PATH=$HOME/0day COMPILER=clang make.cross ARCH=i386 

If you fix the issue, kindly add following tag as appropriate
Reported-by: kernel test robot <lkp@intel.com>

All errors (new ones prefixed by >>):

   In file included from kernel/time/tick-common.c:19:
   In file included from include/trace/events/power.h:8:
>> include/linux/cpufreq.h:1044:35: error: non-void function does not return a value [-Werror,-Wreturn-type]
                                 unsigned int frequency) {}
                                                          ^
   1 error generated.
--
   In file included from drivers/acpi/processor_idle.c:23:
   In file included from include/acpi/processor.h:7:
>> include/linux/cpufreq.h:1044:35: error: non-void function does not return a value [-Werror,-Wreturn-type]
                                 unsigned int frequency) {}
                                                          ^
   drivers/acpi/processor_idle.c:1137:12: warning: no previous prototype for function 'acpi_processor_ffh_lpi_probe' [-Wmissing-prototypes]
   int __weak acpi_processor_ffh_lpi_probe(unsigned int cpu)
              ^
   drivers/acpi/processor_idle.c:1137:1: note: declare 'static' if the function is not intended to be used outside of this translation unit
   int __weak acpi_processor_ffh_lpi_probe(unsigned int cpu)
   ^
   static 
   drivers/acpi/processor_idle.c:1142:12: warning: no previous prototype for function 'acpi_processor_ffh_lpi_enter' [-Wmissing-prototypes]
   int __weak acpi_processor_ffh_lpi_enter(struct acpi_lpi_state *lpi)
              ^
   drivers/acpi/processor_idle.c:1142:1: note: declare 'static' if the function is not intended to be used outside of this translation unit
   int __weak acpi_processor_ffh_lpi_enter(struct acpi_lpi_state *lpi)
   ^
   static 
   2 warnings and 1 error generated.
--
   In file included from kernel/sched/topology.c:5:
   In file included from kernel/sched/sched.h:43:
>> include/linux/cpufreq.h:1044:35: error: non-void function does not return a value [-Werror,-Wreturn-type]
                                 unsigned int frequency) {}
                                                          ^
   kernel/sched/topology.c:691:6: warning: variable 'numa_distance' set but not used [-Wunused-but-set-variable]
           int numa_distance = 0;
               ^
   1 warning and 1 error generated.
--
   In file included from kernel/sched/core.c:13:
   In file included from kernel/sched/sched.h:43:
>> include/linux/cpufreq.h:1044:35: error: non-void function does not return a value [-Werror,-Wreturn-type]
                                 unsigned int frequency) {}
                                                          ^
   kernel/sched/core.c:3217:6: warning: no previous prototype for function 'sched_set_stop_task' [-Wmissing-prototypes]
   void sched_set_stop_task(int cpu, struct task_struct *stop)
        ^
   kernel/sched/core.c:3217:1: note: declare 'static' if the function is not intended to be used outside of this translation unit
   void sched_set_stop_task(int cpu, struct task_struct *stop)
   ^
   static 
   1 warning and 1 error generated.
--
   In file included from kernel/sched/fair.c:23:
   In file included from kernel/sched/sched.h:43:
>> include/linux/cpufreq.h:1044:35: error: non-void function does not return a value [-Werror,-Wreturn-type]
                                 unsigned int frequency) {}
                                                          ^
   kernel/sched/fair.c:10924:6: warning: no previous prototype for function 'task_vruntime_update' [-Wmissing-prototypes]
   void task_vruntime_update(struct rq *rq, struct task_struct *p, bool in_fi)
        ^
   kernel/sched/fair.c:10924:1: note: declare 'static' if the function is not intended to be used outside of this translation unit
   void task_vruntime_update(struct rq *rq, struct task_struct *p, bool in_fi)
   ^
   static 
   1 warning and 1 error generated.
--
   In file included from kernel/sched/rt.c:6:
   In file included from kernel/sched/sched.h:43:
>> include/linux/cpufreq.h:1044:35: error: non-void function does not return a value [-Werror,-Wreturn-type]
                                 unsigned int frequency) {}
                                                          ^
   kernel/sched/rt.c:669:6: warning: no previous prototype for function 'sched_rt_bandwidth_account' [-Wmissing-prototypes]
   bool sched_rt_bandwidth_account(struct rt_rq *rt_rq)
        ^
   kernel/sched/rt.c:669:1: note: declare 'static' if the function is not intended to be used outside of this translation unit
   bool sched_rt_bandwidth_account(struct rt_rq *rt_rq)
   ^
   static 
   1 warning and 1 error generated.


vim +1044 include/linux/cpufreq.h

  1041	
  1042	static inline int
  1043	cpufreq_table_set_inefficient(const struct cpufreq_policy *policy,
> 1044				      unsigned int frequency) {}
  1045	#endif
  1046	

---
0-DAY CI Kernel Test Service, Intel Corporation
https://lists.01.org/hyperkitty/list/kbuild-all@lists.01.org
diff mbox series

Patch

diff --git a/drivers/cpufreq/cpufreq.c b/drivers/cpufreq/cpufreq.c
index 7d5f170ecad1..64ff3836955d 100644
--- a/drivers/cpufreq/cpufreq.c
+++ b/drivers/cpufreq/cpufreq.c
@@ -1504,6 +1504,8 @@  static int cpufreq_online(unsigned int cpu)
 		 */
 		if (cpufreq_driver->register_em)
 			cpufreq_driver->register_em(policy);
+
+		cpufreq_table_update_efficiencies(policy);
 	}
 
 	ret = cpufreq_init_policy(policy);
diff --git a/drivers/cpufreq/freq_table.c b/drivers/cpufreq/freq_table.c
index 67e56cf638ef..c43320c57067 100644
--- a/drivers/cpufreq/freq_table.c
+++ b/drivers/cpufreq/freq_table.c
@@ -365,6 +365,52 @@  int cpufreq_table_validate_and_sort(struct cpufreq_policy *policy)
 	return set_freq_table_sorted(policy);
 }
 
+void cpufreq_table_update_efficiencies(struct cpufreq_policy *policy)
+{
+	struct cpufreq_frequency_table *pos, *table = policy->freq_table;
+	enum cpufreq_table_sorting sort = policy->freq_table_sorted;
+	int efficient, idx;
+
+	/* Not supported */
+	if (sort == CPUFREQ_TABLE_UNSORTED) {
+		cpufreq_for_each_entry_idx(pos, table, idx)
+			pos->efficient = idx;
+		return;
+	}
+
+	/* The highest frequency is always efficient */
+	cpufreq_for_each_entry_idx(pos, table, idx) {
+		if (pos->frequency == CPUFREQ_ENTRY_INVALID)
+			continue;
+
+		efficient = idx;
+
+		if (sort == CPUFREQ_TABLE_SORTED_DESCENDING)
+			break;
+	}
+
+	for (;;) {
+		pos = &table[idx];
+
+		if (pos->frequency != CPUFREQ_ENTRY_INVALID) {
+			if (pos->flags & CPUFREQ_INEFFICIENT_FREQ) {
+				pos->efficient = efficient;
+			} else {
+				pos->efficient = idx;
+				efficient = idx;
+			}
+		}
+
+		if (sort == CPUFREQ_TABLE_SORTED_ASCENDING) {
+			if (--idx < 0)
+				break;
+		} else {
+			if (table[++idx].frequency == CPUFREQ_TABLE_END)
+				break;
+		}
+	}
+}
+
 MODULE_AUTHOR("Dominik Brodowski <linux@brodo.de>");
 MODULE_DESCRIPTION("CPUfreq frequency table helpers");
 MODULE_LICENSE("GPL");
diff --git a/include/linux/cpufreq.h b/include/linux/cpufreq.h
index c65a1d7385f8..4659921173f7 100644
--- a/include/linux/cpufreq.h
+++ b/include/linux/cpufreq.h
@@ -664,13 +664,15 @@  struct governor_attr {
 #define CPUFREQ_ENTRY_INVALID	~0u
 #define CPUFREQ_TABLE_END	~1u
 /* Special Values of .flags field */
-#define CPUFREQ_BOOST_FREQ	(1 << 0)
+#define CPUFREQ_BOOST_FREQ	 (1 << 0)
+#define CPUFREQ_INEFFICIENT_FREQ (1 << 1)
 
 struct cpufreq_frequency_table {
 	unsigned int	flags;
 	unsigned int	driver_data; /* driver specific data, not used by core */
 	unsigned int	frequency; /* kHz - doesn't need to be in ascending
 				    * order */
+	unsigned int	efficient; /* idx of an efficient frequency */
 };
 
 #if defined(CONFIG_CPU_FREQ) && defined(CONFIG_PM_OPP)
@@ -1003,6 +1005,20 @@  static inline int cpufreq_table_count_valid_entries(const struct cpufreq_policy
 
 	return count;
 }
+
+static inline void
+cpufreq_table_set_inefficient(const struct cpufreq_policy *policy,
+			      unsigned int frequency)
+{
+	struct cpufreq_frequency_table *pos;
+
+	cpufreq_for_each_valid_entry(pos, policy->freq_table) {
+		if (pos->frequency == frequency) {
+			pos->flags |= CPUFREQ_INEFFICIENT_FREQ;
+			break;
+		}
+	}
+}
 #else
 static inline int cpufreq_boost_trigger_state(int state)
 {
@@ -1022,6 +1038,10 @@  static inline bool policy_has_boost_freq(struct cpufreq_policy *policy)
 {
 	return false;
 }
+
+static inline int
+cpufreq_table_set_inefficient(const struct cpufreq_policy *policy,
+			      unsigned int frequency) {}
 #endif
 
 #if defined(CONFIG_ENERGY_MODEL) && defined(CONFIG_CPU_FREQ_GOV_SCHEDUTIL)
@@ -1049,6 +1069,7 @@  extern struct freq_attr cpufreq_freq_attr_scaling_available_freqs;
 extern struct freq_attr cpufreq_freq_attr_scaling_boost_freqs;
 extern struct freq_attr *cpufreq_generic_attr[];
 int cpufreq_table_validate_and_sort(struct cpufreq_policy *policy);
+void cpufreq_table_update_efficiencies(struct cpufreq_policy *policy);
 
 unsigned int cpufreq_generic_get(unsigned int cpu);
 void cpufreq_generic_init(struct cpufreq_policy *policy,