diff options
author | Linus Torvalds <torvalds@linux-foundation.org> | 2023-05-03 12:01:05 -0700 |
---|---|---|
committer | Linus Torvalds <torvalds@linux-foundation.org> | 2023-05-03 12:01:05 -0700 |
commit | fa31fc82fb775445c176e576304c4098222f47f2 (patch) | |
tree | f92690bfaaf4b939b6f73e26e182e5f20facfc8e | |
parent | 0153d8e695255cdf3faa5cfa9f18b57158dc2764 (diff) | |
parent | 57ea3ab21c14e6f04db2b0878e8a5be644fa3769 (diff) | |
download | linux-stable-fa31fc82fb775445c176e576304c4098222f47f2.tar.gz linux-stable-fa31fc82fb775445c176e576304c4098222f47f2.tar.bz2 linux-stable-fa31fc82fb775445c176e576304c4098222f47f2.zip |
Merge tag 'pm-6.4-rc1-2' of git://git.kernel.org/pub/scm/linux/kernel/git/rafael/linux-pm
Pull more power management updates from Rafael Wysocki:
"These fix a hibernation test mode regression and clean up the
intel_idle driver.
Specifics:
- Make test_resume work again after the changes that made hibernation
open the snapshot device in exclusive mode (Chen Yu)
- Clean up code in several places in intel_idle (Artem Bityutskiy)"
* tag 'pm-6.4-rc1-2' of git://git.kernel.org/pub/scm/linux/kernel/git/rafael/linux-pm:
intel_idle: mark few variables as __read_mostly
intel_idle: do not sprinkle module parameter definitions around
intel_idle: fix confusing message
intel_idle: improve C-state flags handling robustness
intel_idle: further intel_idle_init_cstates_icpu() cleanup
intel_idle: clean up intel_idle_init_cstates_icpu()
intel_idle: use pr_info() instead of printk()
PM: hibernate: Do not get block device exclusively in test_resume mode
PM: hibernate: Turn snapshot_test into global variable
-rw-r--r-- | drivers/idle/intel_idle.c | 59 | ||||
-rw-r--r-- | kernel/power/hibernate.c | 15 | ||||
-rw-r--r-- | kernel/power/power.h | 1 | ||||
-rw-r--r-- | kernel/power/swap.c | 8 |
4 files changed, 56 insertions, 27 deletions
diff --git a/drivers/idle/intel_idle.c b/drivers/idle/intel_idle.c index 938c17f25d94..aa2d19db2b1d 100644 --- a/drivers/idle/intel_idle.c +++ b/drivers/idle/intel_idle.c @@ -66,8 +66,9 @@ static struct cpuidle_driver intel_idle_driver = { }; /* intel_idle.max_cstate=0 disables driver */ static int max_cstate = CPUIDLE_STATE_MAX - 1; -static unsigned int disabled_states_mask; -static unsigned int preferred_states_mask; +static unsigned int disabled_states_mask __read_mostly; +static unsigned int preferred_states_mask __read_mostly; +static bool force_irq_on __read_mostly; static struct cpuidle_device __percpu *intel_idle_cpuidle_devices; @@ -1838,9 +1839,6 @@ static bool __init intel_idle_verify_cstate(unsigned int mwait_hint) return true; } -static bool force_irq_on __read_mostly; -module_param(force_irq_on, bool, 0444); - static void __init intel_idle_init_cstates_icpu(struct cpuidle_driver *drv) { int cstate; @@ -1871,6 +1869,7 @@ static void __init intel_idle_init_cstates_icpu(struct cpuidle_driver *drv) } for (cstate = 0; cstate < CPUIDLE_STATE_MAX; ++cstate) { + struct cpuidle_state *state; unsigned int mwait_hint; if (intel_idle_max_cstate_reached(cstate)) @@ -1893,29 +1892,39 @@ static void __init intel_idle_init_cstates_icpu(struct cpuidle_driver *drv) /* Structure copy. */ drv->states[drv->state_count] = cpuidle_state_table[cstate]; - - if ((cpuidle_state_table[cstate].flags & CPUIDLE_FLAG_IRQ_ENABLE) || force_irq_on) { - printk("intel_idle: forced intel_idle_irq for state %d\n", cstate); - drv->states[drv->state_count].enter = intel_idle_irq; - } - - if (cpu_feature_enabled(X86_FEATURE_KERNEL_IBRS) && - cpuidle_state_table[cstate].flags & CPUIDLE_FLAG_IBRS) { - WARN_ON_ONCE(cpuidle_state_table[cstate].flags & CPUIDLE_FLAG_IRQ_ENABLE); - drv->states[drv->state_count].enter = intel_idle_ibrs; + state = &drv->states[drv->state_count]; + + if (state->flags & CPUIDLE_FLAG_INIT_XSTATE) { + /* + * Combining with XSTATE with IBRS or IRQ_ENABLE flags + * is not currently supported but this driver. + */ + WARN_ON_ONCE(state->flags & CPUIDLE_FLAG_IBRS); + WARN_ON_ONCE(state->flags & CPUIDLE_FLAG_IRQ_ENABLE); + state->enter = intel_idle_xstate; + } else if (cpu_feature_enabled(X86_FEATURE_KERNEL_IBRS) && + state->flags & CPUIDLE_FLAG_IBRS) { + /* + * IBRS mitigation requires that C-states are entered + * with interrupts disabled. + */ + WARN_ON_ONCE(state->flags & CPUIDLE_FLAG_IRQ_ENABLE); + state->enter = intel_idle_ibrs; + } else if (state->flags & CPUIDLE_FLAG_IRQ_ENABLE) { + state->enter = intel_idle_irq; + } else if (force_irq_on) { + pr_info("forced intel_idle_irq for state %d\n", cstate); + state->enter = intel_idle_irq; } - if (cpuidle_state_table[cstate].flags & CPUIDLE_FLAG_INIT_XSTATE) - drv->states[drv->state_count].enter = intel_idle_xstate; - if ((disabled_states_mask & BIT(drv->state_count)) || ((icpu->use_acpi || force_use_acpi) && intel_idle_off_by_default(mwait_hint) && - !(cpuidle_state_table[cstate].flags & CPUIDLE_FLAG_ALWAYS_ENABLE))) - drv->states[drv->state_count].flags |= CPUIDLE_FLAG_OFF; + !(state->flags & CPUIDLE_FLAG_ALWAYS_ENABLE))) + state->flags |= CPUIDLE_FLAG_OFF; - if (intel_idle_state_needs_timer_stop(&drv->states[drv->state_count])) - drv->states[drv->state_count].flags |= CPUIDLE_FLAG_TIMER_STOP; + if (intel_idle_state_needs_timer_stop(state)) + state->flags |= CPUIDLE_FLAG_TIMER_STOP; drv->state_count++; } @@ -2146,3 +2155,9 @@ MODULE_PARM_DESC(states_off, "Mask of disabled idle states"); */ module_param_named(preferred_cstates, preferred_states_mask, uint, 0444); MODULE_PARM_DESC(preferred_cstates, "Mask of preferred idle states"); +/* + * Debugging option that forces the driver to enter all C-states with + * interrupts enabled. Does not apply to C-states with + * 'CPUIDLE_FLAG_INIT_XSTATE' and 'CPUIDLE_FLAG_IBRS' flags. + */ +module_param(force_irq_on, bool, 0444); diff --git a/kernel/power/hibernate.c b/kernel/power/hibernate.c index 793c55a2becb..30d1274f03f6 100644 --- a/kernel/power/hibernate.c +++ b/kernel/power/hibernate.c @@ -64,6 +64,7 @@ enum { static int hibernation_mode = HIBERNATION_SHUTDOWN; bool freezer_test_done; +bool snapshot_test; static const struct platform_hibernation_ops *hibernation_ops; @@ -687,18 +688,22 @@ static int load_image_and_restore(void) { int error; unsigned int flags; + fmode_t mode = FMODE_READ; + + if (snapshot_test) + mode |= FMODE_EXCL; pm_pr_dbg("Loading hibernation image.\n"); lock_device_hotplug(); error = create_basic_memory_bitmaps(); if (error) { - swsusp_close(FMODE_READ | FMODE_EXCL); + swsusp_close(mode); goto Unlock; } error = swsusp_read(&flags); - swsusp_close(FMODE_READ | FMODE_EXCL); + swsusp_close(mode); if (!error) error = hibernation_restore(flags & SF_PLATFORM_MODE); @@ -716,7 +721,6 @@ static int load_image_and_restore(void) */ int hibernate(void) { - bool snapshot_test = false; unsigned int sleep_flags; int error; @@ -744,6 +748,9 @@ int hibernate(void) if (error) goto Exit; + /* protected by system_transition_mutex */ + snapshot_test = false; + lock_device_hotplug(); /* Allocate memory management structures */ error = create_basic_memory_bitmaps(); @@ -940,6 +947,8 @@ static int software_resume(void) */ mutex_lock_nested(&system_transition_mutex, SINGLE_DEPTH_NESTING); + snapshot_test = false; + if (swsusp_resume_device) goto Check_image; diff --git a/kernel/power/power.h b/kernel/power/power.h index b4f433943209..b83c8d5e188d 100644 --- a/kernel/power/power.h +++ b/kernel/power/power.h @@ -59,6 +59,7 @@ asmlinkage int swsusp_save(void); /* kernel/power/hibernate.c */ extern bool freezer_test_done; +extern bool snapshot_test; extern int hibernation_snapshot(int platform_mode); extern int hibernation_restore(int platform_mode); diff --git a/kernel/power/swap.c b/kernel/power/swap.c index 36a1df48280c..92e41ed292ad 100644 --- a/kernel/power/swap.c +++ b/kernel/power/swap.c @@ -1518,9 +1518,13 @@ int swsusp_check(void) { int error; void *holder; + fmode_t mode = FMODE_READ; + + if (snapshot_test) + mode |= FMODE_EXCL; hib_resume_bdev = blkdev_get_by_dev(swsusp_resume_device, - FMODE_READ | FMODE_EXCL, &holder); + mode, &holder); if (!IS_ERR(hib_resume_bdev)) { set_blocksize(hib_resume_bdev, PAGE_SIZE); clear_page(swsusp_header); @@ -1547,7 +1551,7 @@ int swsusp_check(void) put: if (error) - blkdev_put(hib_resume_bdev, FMODE_READ | FMODE_EXCL); + blkdev_put(hib_resume_bdev, mode); else pr_debug("Image signature found, resuming\n"); } else { |