Commit fa31fc82 authored by Linus Torvalds's avatar Linus Torvalds
Browse files
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
parents 0153d8e6 57ea3ab2
Loading
Loading
Loading
Loading
+37 −22
Original line number Original line Diff line number Diff line
@@ -66,8 +66,9 @@ static struct cpuidle_driver intel_idle_driver = {
};
};
/* intel_idle.max_cstate=0 disables driver */
/* intel_idle.max_cstate=0 disables driver */
static int max_cstate = CPUIDLE_STATE_MAX - 1;
static int max_cstate = CPUIDLE_STATE_MAX - 1;
static unsigned int disabled_states_mask;
static unsigned int disabled_states_mask __read_mostly;
static unsigned int preferred_states_mask;
static unsigned int preferred_states_mask __read_mostly;
static bool force_irq_on __read_mostly;


static struct cpuidle_device __percpu *intel_idle_cpuidle_devices;
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;
	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)
static void __init intel_idle_init_cstates_icpu(struct cpuidle_driver *drv)
{
{
	int cstate;
	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) {
	for (cstate = 0; cstate < CPUIDLE_STATE_MAX; ++cstate) {
		struct cpuidle_state *state;
		unsigned int mwait_hint;
		unsigned int mwait_hint;


		if (intel_idle_max_cstate_reached(cstate))
		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. */
		/* Structure copy. */
		drv->states[drv->state_count] = cpuidle_state_table[cstate];
		drv->states[drv->state_count] = cpuidle_state_table[cstate];
		state = &drv->states[drv->state_count];


		if ((cpuidle_state_table[cstate].flags & CPUIDLE_FLAG_IRQ_ENABLE) || force_irq_on) {
		if (state->flags & CPUIDLE_FLAG_INIT_XSTATE) {
			printk("intel_idle: forced intel_idle_irq for state %d\n", cstate);
			/*
			drv->states[drv->state_count].enter = intel_idle_irq;
			 * Combining with XSTATE with IBRS or IRQ_ENABLE flags
		}
			 * is not currently supported but this driver.

			 */
		if (cpu_feature_enabled(X86_FEATURE_KERNEL_IBRS) &&
			WARN_ON_ONCE(state->flags & CPUIDLE_FLAG_IBRS);
		    cpuidle_state_table[cstate].flags & CPUIDLE_FLAG_IBRS) {
			WARN_ON_ONCE(state->flags & CPUIDLE_FLAG_IRQ_ENABLE);
			WARN_ON_ONCE(cpuidle_state_table[cstate].flags & CPUIDLE_FLAG_IRQ_ENABLE);
			state->enter = intel_idle_xstate;
			drv->states[drv->state_count].enter = intel_idle_ibrs;
		} 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)) ||
		if ((disabled_states_mask & BIT(drv->state_count)) ||
		    ((icpu->use_acpi || force_use_acpi) &&
		    ((icpu->use_acpi || force_use_acpi) &&
		     intel_idle_off_by_default(mwait_hint) &&
		     intel_idle_off_by_default(mwait_hint) &&
		     !(cpuidle_state_table[cstate].flags & CPUIDLE_FLAG_ALWAYS_ENABLE)))
		     !(state->flags & CPUIDLE_FLAG_ALWAYS_ENABLE)))
			drv->states[drv->state_count].flags |= CPUIDLE_FLAG_OFF;
			state->flags |= CPUIDLE_FLAG_OFF;


		if (intel_idle_state_needs_timer_stop(&drv->states[drv->state_count]))
		if (intel_idle_state_needs_timer_stop(state))
			drv->states[drv->state_count].flags |= CPUIDLE_FLAG_TIMER_STOP;
			state->flags |= CPUIDLE_FLAG_TIMER_STOP;


		drv->state_count++;
		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_param_named(preferred_cstates, preferred_states_mask, uint, 0444);
MODULE_PARM_DESC(preferred_cstates, "Mask of preferred idle states");
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);
+12 −3
Original line number Original line Diff line number Diff line
@@ -64,6 +64,7 @@ enum {
static int hibernation_mode = HIBERNATION_SHUTDOWN;
static int hibernation_mode = HIBERNATION_SHUTDOWN;


bool freezer_test_done;
bool freezer_test_done;
bool snapshot_test;


static const struct platform_hibernation_ops *hibernation_ops;
static const struct platform_hibernation_ops *hibernation_ops;


@@ -687,18 +688,22 @@ static int load_image_and_restore(void)
{
{
	int error;
	int error;
	unsigned int flags;
	unsigned int flags;
	fmode_t mode = FMODE_READ;

	if (snapshot_test)
		mode |= FMODE_EXCL;


	pm_pr_dbg("Loading hibernation image.\n");
	pm_pr_dbg("Loading hibernation image.\n");


	lock_device_hotplug();
	lock_device_hotplug();
	error = create_basic_memory_bitmaps();
	error = create_basic_memory_bitmaps();
	if (error) {
	if (error) {
		swsusp_close(FMODE_READ | FMODE_EXCL);
		swsusp_close(mode);
		goto Unlock;
		goto Unlock;
	}
	}


	error = swsusp_read(&flags);
	error = swsusp_read(&flags);
	swsusp_close(FMODE_READ | FMODE_EXCL);
	swsusp_close(mode);
	if (!error)
	if (!error)
		error = hibernation_restore(flags & SF_PLATFORM_MODE);
		error = hibernation_restore(flags & SF_PLATFORM_MODE);


@@ -716,7 +721,6 @@ static int load_image_and_restore(void)
 */
 */
int hibernate(void)
int hibernate(void)
{
{
	bool snapshot_test = false;
	unsigned int sleep_flags;
	unsigned int sleep_flags;
	int error;
	int error;


@@ -744,6 +748,9 @@ int hibernate(void)
	if (error)
	if (error)
		goto Exit;
		goto Exit;


	/* protected by system_transition_mutex */
	snapshot_test = false;

	lock_device_hotplug();
	lock_device_hotplug();
	/* Allocate memory management structures */
	/* Allocate memory management structures */
	error = create_basic_memory_bitmaps();
	error = create_basic_memory_bitmaps();
@@ -940,6 +947,8 @@ static int software_resume(void)
	 */
	 */
	mutex_lock_nested(&system_transition_mutex, SINGLE_DEPTH_NESTING);
	mutex_lock_nested(&system_transition_mutex, SINGLE_DEPTH_NESTING);


	snapshot_test = false;

	if (swsusp_resume_device)
	if (swsusp_resume_device)
		goto Check_image;
		goto Check_image;


+1 −0
Original line number Original line Diff line number Diff line
@@ -59,6 +59,7 @@ asmlinkage int swsusp_save(void);


/* kernel/power/hibernate.c */
/* kernel/power/hibernate.c */
extern bool freezer_test_done;
extern bool freezer_test_done;
extern bool snapshot_test;


extern int hibernation_snapshot(int platform_mode);
extern int hibernation_snapshot(int platform_mode);
extern int hibernation_restore(int platform_mode);
extern int hibernation_restore(int platform_mode);
+6 −2
Original line number Original line Diff line number Diff line
@@ -1518,9 +1518,13 @@ int swsusp_check(void)
{
{
	int error;
	int error;
	void *holder;
	void *holder;
	fmode_t mode = FMODE_READ;

	if (snapshot_test)
		mode |= FMODE_EXCL;


	hib_resume_bdev = blkdev_get_by_dev(swsusp_resume_device,
	hib_resume_bdev = blkdev_get_by_dev(swsusp_resume_device,
					    FMODE_READ | FMODE_EXCL, &holder);
					    mode, &holder);
	if (!IS_ERR(hib_resume_bdev)) {
	if (!IS_ERR(hib_resume_bdev)) {
		set_blocksize(hib_resume_bdev, PAGE_SIZE);
		set_blocksize(hib_resume_bdev, PAGE_SIZE);
		clear_page(swsusp_header);
		clear_page(swsusp_header);
@@ -1547,7 +1551,7 @@ int swsusp_check(void)


put:
put:
		if (error)
		if (error)
			blkdev_put(hib_resume_bdev, FMODE_READ | FMODE_EXCL);
			blkdev_put(hib_resume_bdev, mode);
		else
		else
			pr_debug("Image signature found, resuming\n");
			pr_debug("Image signature found, resuming\n");
	} else {
	} else {