Commit 18e2befa authored by Linus Torvalds's avatar Linus Torvalds

Merge tag 'pm-5.16-rc2' of git://git.kernel.org/pub/scm/linux/kernel/git/rafael/linux-pm

Pull power management fixes from Rafael Wysocki:
 "These fix a system-wide suspend issue in the DTPM framework and
  improve the Energy Model documentation.

  Specifics:

   - Fix system suspend handling in DTPM when it is enabled, but not
     actually used (Daniel Lezcano)

   - Describe the new cpufreq callback for Energy Model registration and
     explain the "advanced" and "simple" EM variants in the EM
     documentation (Lukasz Luba)"

* tag 'pm-5.16-rc2' of git://git.kernel.org/pub/scm/linux/kernel/git/rafael/linux-pm:
  Documentation: power: Describe 'advanced' and 'simple' EM models
  Documentation: power: Add description about new callback for EM registration
  powercap: DTPM: Fix suspend failure and kernel warning
parents 17e10707 47b577ae
...@@ -84,6 +84,16 @@ CONFIG_ENERGY_MODEL must be enabled to use the EM framework. ...@@ -84,6 +84,16 @@ CONFIG_ENERGY_MODEL must be enabled to use the EM framework.
2.2 Registration of performance domains 2.2 Registration of performance domains
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
Registration of 'advanced' EM
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
The 'advanced' EM gets it's name due to the fact that the driver is allowed
to provide more precised power model. It's not limited to some implemented math
formula in the framework (like it's in 'simple' EM case). It can better reflect
the real power measurements performed for each performance state. Thus, this
registration method should be preferred in case considering EM static power
(leakage) is important.
Drivers are expected to register performance domains into the EM framework by Drivers are expected to register performance domains into the EM framework by
calling the following API:: calling the following API::
...@@ -103,6 +113,18 @@ to: return warning/error, stop working or panic. ...@@ -103,6 +113,18 @@ to: return warning/error, stop working or panic.
See Section 3. for an example of driver implementing this See Section 3. for an example of driver implementing this
callback, or Section 2.4 for further documentation on this API callback, or Section 2.4 for further documentation on this API
Registration of 'simple' EM
~~~~~~~~~~~~~~~~~~~~~~~~~~~
The 'simple' EM is registered using the framework helper function
cpufreq_register_em_with_opp(). It implements a power model which is tight to
math formula::
Power = C * V^2 * f
The EM which is registered using this method might not reflect correctly the
physics of a real device, e.g. when static power (leakage) is important.
2.3 Accessing performance domains 2.3 Accessing performance domains
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
...@@ -138,6 +160,10 @@ or in Section 2.4 ...@@ -138,6 +160,10 @@ or in Section 2.4
3. Example driver 3. Example driver
----------------- -----------------
The CPUFreq framework supports dedicated callback for registering
the EM for a given CPU(s) 'policy' object: cpufreq_driver::register_em().
That callback has to be implemented properly for a given driver,
because the framework would call it at the right time during setup.
This section provides a simple example of a CPUFreq driver registering a This section provides a simple example of a CPUFreq driver registering a
performance domain in the Energy Model framework using the (fake) 'foo' performance domain in the Energy Model framework using the (fake) 'foo'
protocol. The driver implements an est_power() function to be provided to the protocol. The driver implements an est_power() function to be provided to the
...@@ -167,25 +193,22 @@ EM framework:: ...@@ -167,25 +193,22 @@ EM framework::
20 return 0; 20 return 0;
21 } 21 }
22 22
23 static int foo_cpufreq_init(struct cpufreq_policy *policy) 23 static void foo_cpufreq_register_em(struct cpufreq_policy *policy)
24 { 24 {
25 struct em_data_callback em_cb = EM_DATA_CB(est_power); 25 struct em_data_callback em_cb = EM_DATA_CB(est_power);
26 struct device *cpu_dev; 26 struct device *cpu_dev;
27 int nr_opp, ret; 27 int nr_opp;
28 28
29 cpu_dev = get_cpu_device(cpumask_first(policy->cpus)); 29 cpu_dev = get_cpu_device(cpumask_first(policy->cpus));
30 30
31 /* Do the actual CPUFreq init work ... */ 31 /* Find the number of OPPs for this policy */
32 ret = do_foo_cpufreq_init(policy); 32 nr_opp = foo_get_nr_opp(policy);
33 if (ret) 33
34 return ret; 34 /* And register the new performance domain */
35 35 em_dev_register_perf_domain(cpu_dev, nr_opp, &em_cb, policy->cpus,
36 /* Find the number of OPPs for this policy */ 36 true);
37 nr_opp = foo_get_nr_opp(policy); 37 }
38 38
39 /* And register the new performance domain */ 39 static struct cpufreq_driver foo_cpufreq_driver = {
40 em_dev_register_perf_domain(cpu_dev, nr_opp, &em_cb, policy->cpus, 40 .register_em = foo_cpufreq_register_em,
41 true); 41 };
42
43 return 0;
44 }
...@@ -166,16 +166,13 @@ static struct dtpm_ops dtpm_ops = { ...@@ -166,16 +166,13 @@ static struct dtpm_ops dtpm_ops = {
static int cpuhp_dtpm_cpu_offline(unsigned int cpu) static int cpuhp_dtpm_cpu_offline(unsigned int cpu)
{ {
struct em_perf_domain *pd;
struct dtpm_cpu *dtpm_cpu; struct dtpm_cpu *dtpm_cpu;
pd = em_cpu_get(cpu);
if (!pd)
return -EINVAL;
dtpm_cpu = per_cpu(dtpm_per_cpu, cpu); dtpm_cpu = per_cpu(dtpm_per_cpu, cpu);
if (dtpm_cpu)
dtpm_update_power(&dtpm_cpu->dtpm);
return dtpm_update_power(&dtpm_cpu->dtpm); return 0;
} }
static int cpuhp_dtpm_cpu_online(unsigned int cpu) static int cpuhp_dtpm_cpu_online(unsigned int cpu)
......
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