Commit dd358185 authored by Rafael J. Wysocki's avatar Rafael J. Wysocki
Browse files

Merge branch 'pm-cpuidle'

Merge cpuidle updates for 6.16-rc2:

 - Update data types of variables passed as arguments to
   mwait_idle_with_hints() to match the function definition
   after recent changes (Uros Bizjak).

 - Eliminate mwait_play_dead_cpuid_hint() again after reverting its
   elimination during the merge window due to a problem with handling
   "dead" SMT siblings, but this time prevent leaving them in C1 after
   initialization by taking them online and back offline when a proper
   cpuidle driver for the platform has been registered (Rafael Wysocki).

* pm-cpuidle:
  intel_idle: Update arguments of mwait_idle_with_hints()
  Reapply "x86/smp: Eliminate mwait_play_dead_cpuid_hint()"
  ACPI: processor: Rescan "dead" SMT siblings during initialization
  intel_idle: Rescan "dead" SMT siblings during initialization
  x86/smp: PM/hibernate: Split arch_resume_nosmt()
  intel_idle: Use subsys_initcall_sync() for initialization
parents ea286760 72840238
Loading
Loading
Loading
Loading
+24 −0
Original line number Diff line number Diff line
@@ -299,3 +299,27 @@ struct smp_ops smp_ops = {
	.send_call_func_single_ipi = native_send_call_func_single_ipi,
};
EXPORT_SYMBOL_GPL(smp_ops);

int arch_cpu_rescan_dead_smt_siblings(void)
{
	enum cpuhp_smt_control old = cpu_smt_control;
	int ret;

	/*
	 * If SMT has been disabled and SMT siblings are in HLT, bring them back
	 * online and offline them again so that they end up in MWAIT proper.
	 *
	 * Called with hotplug enabled.
	 */
	if (old != CPU_SMT_DISABLED && old != CPU_SMT_FORCE_DISABLED)
		return 0;

	ret = cpuhp_smt_enable();
	if (ret)
		return ret;

	ret = cpuhp_smt_disable(old);

	return ret;
}
EXPORT_SYMBOL_GPL(arch_cpu_rescan_dead_smt_siblings);
+7 −47
Original line number Diff line number Diff line
@@ -1244,6 +1244,10 @@ void play_dead_common(void)
	local_irq_disable();
}

/*
 * We need to flush the caches before going to sleep, lest we have
 * dirty data in our caches when we come back up.
 */
void __noreturn mwait_play_dead(unsigned int eax_hint)
{
	struct mwait_cpu_dead *md = this_cpu_ptr(&mwait_cpu_dead);
@@ -1289,50 +1293,6 @@ void __noreturn mwait_play_dead(unsigned int eax_hint)
	}
}

/*
 * We need to flush the caches before going to sleep, lest we have
 * dirty data in our caches when we come back up.
 */
static inline void mwait_play_dead_cpuid_hint(void)
{
	unsigned int eax, ebx, ecx, edx;
	unsigned int highest_cstate = 0;
	unsigned int highest_subcstate = 0;
	int i;

	if (boot_cpu_data.x86_vendor == X86_VENDOR_AMD ||
	    boot_cpu_data.x86_vendor == X86_VENDOR_HYGON)
		return;
	if (!this_cpu_has(X86_FEATURE_MWAIT))
		return;
	if (!this_cpu_has(X86_FEATURE_CLFLUSH))
		return;

	eax = CPUID_LEAF_MWAIT;
	ecx = 0;
	native_cpuid(&eax, &ebx, &ecx, &edx);

	/*
	 * eax will be 0 if EDX enumeration is not valid.
	 * Initialized below to cstate, sub_cstate value when EDX is valid.
	 */
	if (!(ecx & CPUID5_ECX_EXTENSIONS_SUPPORTED)) {
		eax = 0;
	} else {
		edx >>= MWAIT_SUBSTATE_SIZE;
		for (i = 0; i < 7 && edx; i++, edx >>= MWAIT_SUBSTATE_SIZE) {
			if (edx & MWAIT_SUBSTATE_MASK) {
				highest_cstate = i;
				highest_subcstate = edx & MWAIT_SUBSTATE_MASK;
			}
		}
		eax = (highest_cstate << MWAIT_SUBSTATE_SIZE) |
			(highest_subcstate - 1);
	}

	mwait_play_dead(eax);
}

/*
 * Kick all "offline" CPUs out of mwait on kexec(). See comment in
 * mwait_play_dead().
@@ -1383,8 +1343,8 @@ void native_play_dead(void)
	play_dead_common();
	tboot_shutdown(TB_SHUTDOWN_WFS);

	mwait_play_dead_cpuid_hint();
	if (cpuidle_play_dead())
	/* Below returns only on error. */
	cpuidle_play_dead();
	hlt_play_dead();
}

+6 −13
Original line number Diff line number Diff line
@@ -192,7 +192,8 @@ int relocate_restore_code(void)

int arch_resume_nosmt(void)
{
	int ret = 0;
	int ret;

	/*
	 * We reached this while coming out of hibernation. This means
	 * that SMT siblings are sleeping in hlt, as mwait is not safe
@@ -206,18 +207,10 @@ int arch_resume_nosmt(void)
	 * Called with hotplug disabled.
	 */
	cpu_hotplug_enable();
	if (cpu_smt_control == CPU_SMT_DISABLED ||
			cpu_smt_control == CPU_SMT_FORCE_DISABLED) {
		enum cpuhp_smt_control old = cpu_smt_control;

		ret = cpuhp_smt_enable();
		if (ret)
			goto out;
		ret = cpuhp_smt_disable(old);
		if (ret)
			goto out;
	}
out:
	ret = arch_cpu_rescan_dead_smt_siblings();

	cpu_hotplug_disable();

	return ret;
}
+6 −0
Original line number Diff line number Diff line
@@ -175,6 +175,12 @@ bool processor_physically_present(acpi_handle handle);
static inline void acpi_early_processor_control_setup(void) {}
#endif

#ifdef CONFIG_ACPI_PROCESSOR_CSTATE
void acpi_idle_rescan_dead_smt_siblings(void);
#else
static inline void acpi_idle_rescan_dead_smt_siblings(void) {}
#endif

/* --------------------------------------------------------------------------
                                  Embedded Controller
   -------------------------------------------------------------------------- */
+3 −0
Original line number Diff line number Diff line
@@ -279,6 +279,9 @@ static int __init acpi_processor_driver_init(void)
	 * after acpi_cppc_processor_probe() has been called for all online CPUs
	 */
	acpi_processor_init_invariance_cppc();

	acpi_idle_rescan_dead_smt_siblings();

	return 0;
err:
	driver_unregister(&acpi_processor_driver);
Loading