Power management fixes for 7.4-rc1

- Fix potential out-of-bounds access in deferred reset in the cpufreq
    statistics code (Zhongqiu Han)
 
  - Cancel HWP notify work in the intel_pstate driver cleanup to prevent
    possible use-after-free from occurring (Tristan Madani)
 
  - Adjust state names and descriptions for ACPI _LPI idle states in the
    intel_idle driver to make them follow the driver's idle state naming
    convention (Rafael Wysocki)
 
  - Document the new pm_runtime_use_autosuspend() undo mechanism that
    triggers automatically on driver exit (Joshua Crofts)
 
  - Do not call suspend_ops->begin()/end() for suspend-to-idle to avoid
    driver confusion (Ovidiu Panait)
 
  - Make the energy model management code allocate the cpumask for
    non-CPU perf domains to prevent out-of-bounds reads from occurring
    in the EM netlink interface (Karl Mehltretter)
 -----BEGIN PGP SIGNATURE-----
 
 iQFGBAABCAAwFiEEcM8Aw/RY0dgsiRUR7l+9nS/U47UFAmrk+YcSHHJqd0Byand5
 c29ja2kubmV0AAoJEO5fvZ0v1OO1e7YH/j9Iyv9QT6PyjyCqayOCcorSdX2y+URY
 oG2Bog7zr6IjjS3rTNf2tbMkLxhXa5ROY6oAU/z+glszdJ1Jt9eqvwTtrUMHcLO+
 K11XCq6wP0dmRErzUg5Wb1b5B6rkapJ/7CVFodpxRiWOYRLyG2i9OAULsaMmnvck
 8epgxQ2z0HPwOz3aFTOcgt0YcbIrmesL9E+m+0P2/XW3fbge9CWB+sn04zyFiaqZ
 tT6qZO3WZPhOMy2rhabmfW4kDAJ0QI7g5rdenvGxhyh0BgrgtYyMxyJPoaWPvywZ
 MPVucda6ozbLamgJBWv6BH18joFkCzX/+hRmsgs77+NdLYBzmkqoOf4=
 =gV71
 -----END PGP SIGNATURE-----

Merge tag 'pm-7.4-rc1-2' of git://git.kernel.org/pub/scm/linux/kernel/git/rafael/linux-pm

Pull power management fixes from Rafael Wysocki:
 "These address assorted issues in the power management code and update
  documentation:

   - Fix potential out-of-bounds access in deferred reset in the cpufreq
     statistics code (Zhongqiu Han)

   - Cancel HWP notify work in the intel_pstate driver cleanup to
     prevent possible use-after-free from occurring (Tristan Madani)

   - Adjust state names and descriptions for ACPI _LPI idle states in
     the intel_idle driver to make them follow the driver's idle state
     naming convention (Rafael Wysocki)

   - Document the new pm_runtime_use_autosuspend() undo mechanism that
     triggers automatically on driver exit (Joshua Crofts)

   - Do not call suspend_ops->begin()/end() for suspend-to-idle to avoid
     driver confusion (Ovidiu Panait)

   - Make the energy model management code allocate the cpumask for
     non-CPU perf domains to prevent out-of-bounds reads from occurring
     in the EM netlink interface (Karl Mehltretter)"

* tag 'pm-7.4-rc1-2' of git://git.kernel.org/pub/scm/linux/kernel/git/rafael/linux-pm:
  PM: runtime: clarify pm_runtime_use_autosuspend() undo mechanism
  cpufreq: stats: Fix potential out-of-bounds access in deferred reset
  PM: suspend: Do not call suspend_ops->begin()/end() for s2idle
  intel_idle: Adjust state names and descriptions for _LPI states
  PM: EM: allocate the cpumask for every perf domain
  cpufreq: intel_pstate: cancel HWP notify work in driver cleanup
This commit is contained in:
Linus Torvalds 2026-10-30 13:22:02 -10:00
commit 7306ea08c0
8 changed files with 43 additions and 24 deletions

View File

@ -145,11 +145,13 @@ for the other idle state types (C2 and C3) the target residency value is 3 times
the exit latency (again, that is because it reflects the target residency to
exit latency ratio in the majority of cases for the processor models recognized
by ``intel_idle``). The name of the idle state (to be returned by the ``name``
idle state attribute in ``sysfs``) is either "Cx_LPI" (if it comes from ``_LPI``
processing) or "Cx_ACPI", where x is the index of that idle state in the final
list (note that the minimum value of x is 1, because 0 is reserved for the
"polling" state), and its target residency is based on the exit latency value.
All of the idle states in the final list are enabled by default in this case.
idle state attribute in ``sysfs``) either is equal to the state name value that
comes from ``_LPI`` processing (with the possible fallback to "Cx_LPI" if the
state name is not provided) or it is "Cx_ACPI", where x is the index of that
idle state in the final list (note that the minimum value of x is 1, because 0
is reserved for the "polling" state), and its target residency is based on the
exit latency value. All of the idle states in the final list are enabled by
default in this case.
.. _intel-idle-initialization:

View File

@ -425,11 +425,11 @@ but it also allows more flexibility in the handling of devices during the
removal of their drivers.
Drivers in ->remove() callback should undo the runtime PM changes done
in ->probe(). Usually this means calling pm_runtime_disable(),
pm_runtime_dont_use_autosuspend() etc. Alternatively, drivers can use
devm_pm_runtime_enable() during probe, which automatically takes care of
calling pm_runtime_disable() and pm_runtime_dont_use_autosuspend() upon driver
detachment.
in ->probe(). Usually this means calling pm_runtime_disable() etc.
Alternatively, drivers can use devm_pm_runtime_enable() during probe, which
automatically takes care of calling pm_runtime_disable() upon driver detachment.
Any pm_runtime_use_autosuspend() calls in a driver will be automatically undone
on driver exit.
The user space can effectively disallow the driver of the device to power manage
it at run time by changing the value of its /sys/devices/.../power/control

View File

@ -52,6 +52,10 @@ static void cpufreq_stats_reset_table(struct cpufreq_stats *stats)
* reset_pending accesses in cpufreq_stats_record_transition().
*/
smp_rmb();
if (stats->last_index == -1)
return;
cpufreq_stats_update(stats, READ_ONCE(stats->reset_time));
}

View File

@ -3436,6 +3436,8 @@ static void intel_pstate_driver_cleanup(void)
if (intel_pstate_driver == &intel_pstate)
intel_pstate_clear_update_util_hook(cpu);
intel_pstate_disable_hwp_interrupt(all_cpu_data[cpu]);
kfree(all_cpu_data[cpu]);
WRITE_ONCE(all_cpu_data[cpu], NULL);
}

View File

@ -1903,8 +1903,13 @@ static void __init intel_idle_init_cstates_acpi_lpi(struct cpuidle_driver *drv)
state = &drv->states[drv->state_count++];
scnprintf(state->name, CPUIDLE_NAME_LEN, "C%d_LPI", index + 1);
strscpy(state->desc, lpi_state->desc);
if (strlen(lpi_state->desc) > 0)
strscpy(state->name, lpi_state->desc);
else
scnprintf(state->name, CPUIDLE_NAME_LEN, "C%d_LPI", index + 1);
scnprintf(state->desc, CPUIDLE_DESC_LEN, "ACPI LPI MWAIT 0x%02llx",
lpi_state->address);
state->exit_latency = lpi_state->wake_latency;
state->target_residency = lpi_state->min_residency;
state->flags = MWAIT2flg(lpi_state->address);

View File

@ -855,9 +855,9 @@ static inline void pm_runtime_disable(struct device *dev)
* requested (or "autosuspend" will be handled as direct runtime-suspend for
* it).
*
* NOTE: It's important to undo this with pm_runtime_dont_use_autosuspend()
* at driver exit time unless your driver initially enabled pm_runtime
* with devm_pm_runtime_enable() (which handles it for you).
* NOTE: This is undone automatically with pm_runtime_dont_use_autosuspend() on
* driver exit regardless of whether a driver uses managed devm_* functions or
* not.
*/
static inline void pm_runtime_use_autosuspend(struct device *dev)
{

View File

@ -439,7 +439,9 @@ static int em_create_pd(struct device *dev, int nr_states,
cpumask_copy(em_span_cpus(pd), cpus);
} else {
pd = kzalloc_obj(*pd);
/* Readers expect pd->cpus to exist and remain empty. */
pd = kzalloc_flex(*pd, cpus,
BITS_TO_LONGS(large_cpumask_bits));
if (!pd)
return -ENOMEM;
}

View File

@ -306,20 +306,24 @@ static void platform_resume_finish(suspend_state_t state)
static int platform_suspend_begin(suspend_state_t state)
{
if (state == PM_SUSPEND_TO_IDLE && s2idle_ops && s2idle_ops->begin)
return s2idle_ops->begin();
else if (suspend_ops && suspend_ops->begin)
if (state == PM_SUSPEND_TO_IDLE) {
if (s2idle_ops && s2idle_ops->begin)
return s2idle_ops->begin();
} else if (suspend_ops && suspend_ops->begin) {
return suspend_ops->begin(state);
else
return 0;
}
return 0;
}
static void platform_resume_end(suspend_state_t state)
{
if (state == PM_SUSPEND_TO_IDLE && s2idle_ops && s2idle_ops->end)
s2idle_ops->end();
else if (suspend_ops && suspend_ops->end)
if (state == PM_SUSPEND_TO_IDLE) {
if (s2idle_ops && s2idle_ops->end)
s2idle_ops->end();
} else if (suspend_ops && suspend_ops->end) {
suspend_ops->end();
}
}
static void platform_recover(suspend_state_t state)