mirror of
git://git.yoctoproject.org/linux-yocto.git
synced 2025-10-22 23:13:01 +02:00
Merge branch 'pm-cpuidle'
Fix an issue in the PSCI cpuidle driver introduced recently and a nasty x86 power regression introduced in 6.15: - Prevent freeing an uninitialized pointer in error path of dt_idle_state_present() in the PSCI cpuidle driver (Dan Carpenter). - Revert an x86 commit that went into 6.15 and caused idle power, including power in suspend-to-idle, to rise rather dramatically on systems booting with "nosmt" in the kernel command line (Rafael Wysocki). * pm-cpuidle: Revert "x86/smp: Eliminate mwait_play_dead_cpuid_hint()" cpuidle: psci: Fix uninitialized variable in dt_idle_state_present()
This commit is contained in:
commit
3d031d0d8d
|
@ -1244,10 +1244,6 @@ 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);
|
||||
|
@ -1293,6 +1289,50 @@ 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().
|
||||
|
@ -1343,9 +1383,9 @@ void native_play_dead(void)
|
|||
play_dead_common();
|
||||
tboot_shutdown(TB_SHUTDOWN_WFS);
|
||||
|
||||
/* Below returns only on error. */
|
||||
cpuidle_play_dead();
|
||||
hlt_play_dead();
|
||||
mwait_play_dead_cpuid_hint();
|
||||
if (cpuidle_play_dead())
|
||||
hlt_play_dead();
|
||||
}
|
||||
|
||||
#else /* ... !CONFIG_HOTPLUG_CPU */
|
||||
|
|
|
@ -456,14 +456,13 @@ static struct faux_device_ops psci_cpuidle_ops = {
|
|||
|
||||
static bool __init dt_idle_state_present(void)
|
||||
{
|
||||
struct device_node *cpu_node __free(device_node);
|
||||
struct device_node *state_node __free(device_node);
|
||||
|
||||
cpu_node = of_cpu_device_node_get(cpumask_first(cpu_possible_mask));
|
||||
struct device_node *cpu_node __free(device_node) =
|
||||
of_cpu_device_node_get(cpumask_first(cpu_possible_mask));
|
||||
if (!cpu_node)
|
||||
return false;
|
||||
|
||||
state_node = of_get_cpu_state_node(cpu_node, 0);
|
||||
struct device_node *state_node __free(device_node) =
|
||||
of_get_cpu_state_node(cpu_node, 0);
|
||||
if (!state_node)
|
||||
return false;
|
||||
|
||||
|
|
Loading…
Reference in New Issue
Block a user