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

Pull power management fixes from Rafael Wysocki:
 "These fix three regressions, two recent ones and one introduced during
  the 6.17 development cycle:

   - Add an exit latency check to the menu cpuidle governor in the case
     when it considers using a real idle state instead of a polling one
     to address a performance regression (Rafael Wysocki)

   - Revert an attempted cleanup of a system suspend code path that
     introduced a regression elsewhere (Samuel Wu)

   - Allow pm_restrict_gfp_mask() to be called multiple times in a row
     and adjust pm_restore_gfp_mask() accordingly to avoid having to
     play nasty games with these calls during hibernation (Rafael
     Wysocki)"

* tag 'pm-6.18-rc4' of git://git.kernel.org/pub/scm/linux/kernel/git/rafael/linux-pm:
  PM: sleep: Allow pm_restrict_gfp_mask() stacking
  cpuidle: governors: menu: Select polling state in some more cases
  Revert "PM: sleep: Make pm_wakeup_clear() call more clear"
This commit is contained in:
Linus Torvalds
2025-10-30 19:02:16 -07:00
5 changed files with 23 additions and 12 deletions

View File

@@ -318,10 +318,13 @@ static int menu_select(struct cpuidle_driver *drv, struct cpuidle_device *dev,
/*
* Use a physical idle state, not busy polling, unless a timer
* is going to trigger soon enough.
* is going to trigger soon enough or the exit latency of the
* idle state in question is greater than the predicted idle
* duration.
*/
if ((drv->states[idx].flags & CPUIDLE_FLAG_POLLING) &&
s->target_residency_ns <= data->next_timer_ns) {
s->target_residency_ns <= data->next_timer_ns &&
s->exit_latency_ns <= predicted_ns) {
predicted_ns = s->target_residency_ns;
idx = i;
break;

View File

@@ -706,7 +706,6 @@ static void power_down(void)
#ifdef CONFIG_SUSPEND
if (hibernation_mode == HIBERNATION_SUSPEND) {
pm_restore_gfp_mask();
error = suspend_devices_and_enter(mem_sleep_current);
if (!error)
goto exit;
@@ -746,9 +745,6 @@ static void power_down(void)
cpu_relax();
exit:
/* Match the pm_restore_gfp_mask() call in hibernate(). */
pm_restrict_gfp_mask();
/* Restore swap signature. */
error = swsusp_unmark();
if (error)

View File

@@ -31,23 +31,35 @@
* held, unless the suspend/hibernate code is guaranteed not to run in parallel
* with that modification).
*/
static unsigned int saved_gfp_count;
static gfp_t saved_gfp_mask;
void pm_restore_gfp_mask(void)
{
WARN_ON(!mutex_is_locked(&system_transition_mutex));
if (saved_gfp_mask) {
gfp_allowed_mask = saved_gfp_mask;
saved_gfp_mask = 0;
}
if (WARN_ON(!saved_gfp_count) || --saved_gfp_count)
return;
gfp_allowed_mask = saved_gfp_mask;
saved_gfp_mask = 0;
pm_pr_dbg("GFP mask restored\n");
}
void pm_restrict_gfp_mask(void)
{
WARN_ON(!mutex_is_locked(&system_transition_mutex));
WARN_ON(saved_gfp_mask);
if (saved_gfp_count++) {
WARN_ON((saved_gfp_mask & ~(__GFP_IO | __GFP_FS)) != gfp_allowed_mask);
return;
}
saved_gfp_mask = gfp_allowed_mask;
gfp_allowed_mask &= ~(__GFP_IO | __GFP_FS);
pm_pr_dbg("GFP mask restricted\n");
}
unsigned int lock_system_sleep(void)

View File

@@ -132,6 +132,7 @@ int freeze_processes(void)
if (!pm_freezing)
static_branch_inc(&freezer_active);
pm_wakeup_clear(0);
pm_freezing = true;
error = try_to_freeze_tasks(true);
if (!error)

View File

@@ -595,7 +595,6 @@ static int enter_state(suspend_state_t state)
}
pm_pr_dbg("Preparing system for sleep (%s)\n", mem_sleep_labels[state]);
pm_wakeup_clear(0);
pm_suspend_clear_flags();
error = suspend_prepare(state);
if (error)