Power management fixes for 5.16-rc2
- 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). -----BEGIN PGP SIGNATURE----- iQJGBAABCAAwFiEE4fcc61cGeeHD/fCwgsRv/nhiVHEFAmGWrY8SHHJqd0Byand5 c29ja2kubmV0AAoJEILEb/54YlRxKvQP/AxYRH0APEoHn99kGeWWbFWcGz2ZXmuH BSdqu6zo/RUBvBkLjBxCKXq28Ns6lL2tOuAU8/zCnARiZm2Ojt/7OrdaY7FwPvqI cM5z1Tzas9/bfzNlPOjfyeQhbBlx7fR4CPo+8mrMSDflN8kHVXMJl2g/5N0pgl1V YmnMvHwx44Zqz3L6hUc5PPDyAaX2aUNBpmL7FZXTGT20g4E2jdNXr+m8LW6Yytd8 kU1Zg2yhT7PWnSuyY47Gosojl6Pe3c1bPCVjiy9MH7Kf/r6l0dVHI8rz27fO0rNZ kMigOMJGtGZxy9wER92KNZA0ZQXJv24XjNL3aOYfoOUJB4FOyDummAw6+y9dk2DY SoyT7vidwgBpEXit5bIDD/VOBx7GRU3gLT7Fdj1fzRd1ecypFVZdvQZPfySJf7BB 3PZciecND5EQ7ADWP5yjotvJHJZdQ+DR5BuQ3t+okAmTFUROKrx+E+4dgdA3c9aM ITqzYPn2yPmT6vq57ttXR61EhfB0Q/cLUYhYkdZQwzg1OFyJgiuRdfwggxO/e8aq mR2YHfjAAhSqIKyqNzZOnm1sdTFTLd93/O9c+RaJyKOK7mDSYeVupfphuIVgj4G8 9GylOwkCnm/MJRiE+cb2xXhf8ucAUTS3bjmQau5XdBNEsb1PATES1QoGE7wNYpnc enFRHiYbJttM =zSux -----END PGP SIGNATURE----- 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
This commit is contained in:
Коммит
18e2befaf6
|
@ -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.
|
||||||
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
|
||||||
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::
|
||||||
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 = {
|
||||||
|
|
||||||
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)
|
||||||
|
|
Загрузка…
Ссылка в новой задаче