Skip to content

Commit f688b59

Browse files
committed
Merge tag 'pm-6.16-rc2' of git://git.kernel.org/pub/scm/linux/kernel/git/rafael/linux-pm
Pull power management fixes from Rafael Wysocki: "These fix the cpupower utility installation, fix up the recently added Rust abstractions for cpufreq and OPP, restore the x86 update eliminating mwait_play_dead_cpuid_hint() that has been reverted during the 6.16 merge window along with preventing the failure caused by it from happening, and clean up mwait_idle_with_hints() usage in intel_idle: - Implement CpuId Rust abstraction and use it to fix doctest failure related to the recently introduced cpumask abstraction (Viresh Kumar) - Do minor cleanups in the `# Safety` sections for cpufreq abstractions added recently (Viresh Kumar) - Unbreak cpupower systemd service units installation on some systems by adding a unitdir variable for specifying the location to install them (Francesco Poli) - Eliminate mwait_play_dead_cpuid_hint() again after reverting its elimination during the 6.16 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) - Update data types of variables passed as arguments to mwait_idle_with_hints() to match the function definition after recent changes (Uros Bizjak)" * tag 'pm-6.16-rc2' of git://git.kernel.org/pub/scm/linux/kernel/git/rafael/linux-pm: rust: cpu: Add CpuId::current() to retrieve current CPU ID rust: Use CpuId in place of raw CPU numbers rust: cpu: Introduce CpuId abstraction intel_idle: Update arguments of mwait_idle_with_hints() cpufreq: Convert `/// SAFETY` lines to `# Safety` sections cpupower: split unitdir from libdir in Makefile 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
2 parents 02adc14 + dd35818 commit f688b59

File tree

16 files changed

+368
-133
lines changed

16 files changed

+368
-133
lines changed

MAINTAINERS

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -6255,6 +6255,7 @@ F: include/linux/cpuhotplug.h
62556255
F: include/linux/smpboot.h
62566256
F: kernel/cpu.c
62576257
F: kernel/smpboot.*
6258+
F: rust/helper/cpu.c
62586259
F: rust/kernel/cpu.rs
62596260

62606261
CPU IDLE TIME MANAGEMENT FRAMEWORK

arch/x86/kernel/smp.c

Lines changed: 24 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -299,3 +299,27 @@ struct smp_ops smp_ops = {
299299
.send_call_func_single_ipi = native_send_call_func_single_ipi,
300300
};
301301
EXPORT_SYMBOL_GPL(smp_ops);
302+
303+
int arch_cpu_rescan_dead_smt_siblings(void)
304+
{
305+
enum cpuhp_smt_control old = cpu_smt_control;
306+
int ret;
307+
308+
/*
309+
* If SMT has been disabled and SMT siblings are in HLT, bring them back
310+
* online and offline them again so that they end up in MWAIT proper.
311+
*
312+
* Called with hotplug enabled.
313+
*/
314+
if (old != CPU_SMT_DISABLED && old != CPU_SMT_FORCE_DISABLED)
315+
return 0;
316+
317+
ret = cpuhp_smt_enable();
318+
if (ret)
319+
return ret;
320+
321+
ret = cpuhp_smt_disable(old);
322+
323+
return ret;
324+
}
325+
EXPORT_SYMBOL_GPL(arch_cpu_rescan_dead_smt_siblings);

arch/x86/kernel/smpboot.c

Lines changed: 7 additions & 47 deletions
Original file line numberDiff line numberDiff line change
@@ -1244,6 +1244,10 @@ void play_dead_common(void)
12441244
local_irq_disable();
12451245
}
12461246

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

1292-
/*
1293-
* We need to flush the caches before going to sleep, lest we have
1294-
* dirty data in our caches when we come back up.
1295-
*/
1296-
static inline void mwait_play_dead_cpuid_hint(void)
1297-
{
1298-
unsigned int eax, ebx, ecx, edx;
1299-
unsigned int highest_cstate = 0;
1300-
unsigned int highest_subcstate = 0;
1301-
int i;
1302-
1303-
if (boot_cpu_data.x86_vendor == X86_VENDOR_AMD ||
1304-
boot_cpu_data.x86_vendor == X86_VENDOR_HYGON)
1305-
return;
1306-
if (!this_cpu_has(X86_FEATURE_MWAIT))
1307-
return;
1308-
if (!this_cpu_has(X86_FEATURE_CLFLUSH))
1309-
return;
1310-
1311-
eax = CPUID_LEAF_MWAIT;
1312-
ecx = 0;
1313-
native_cpuid(&eax, &ebx, &ecx, &edx);
1314-
1315-
/*
1316-
* eax will be 0 if EDX enumeration is not valid.
1317-
* Initialized below to cstate, sub_cstate value when EDX is valid.
1318-
*/
1319-
if (!(ecx & CPUID5_ECX_EXTENSIONS_SUPPORTED)) {
1320-
eax = 0;
1321-
} else {
1322-
edx >>= MWAIT_SUBSTATE_SIZE;
1323-
for (i = 0; i < 7 && edx; i++, edx >>= MWAIT_SUBSTATE_SIZE) {
1324-
if (edx & MWAIT_SUBSTATE_MASK) {
1325-
highest_cstate = i;
1326-
highest_subcstate = edx & MWAIT_SUBSTATE_MASK;
1327-
}
1328-
}
1329-
eax = (highest_cstate << MWAIT_SUBSTATE_SIZE) |
1330-
(highest_subcstate - 1);
1331-
}
1332-
1333-
mwait_play_dead(eax);
1334-
}
1335-
13361296
/*
13371297
* Kick all "offline" CPUs out of mwait on kexec(). See comment in
13381298
* mwait_play_dead().
@@ -1383,9 +1343,9 @@ void native_play_dead(void)
13831343
play_dead_common();
13841344
tboot_shutdown(TB_SHUTDOWN_WFS);
13851345

1386-
mwait_play_dead_cpuid_hint();
1387-
if (cpuidle_play_dead())
1388-
hlt_play_dead();
1346+
/* Below returns only on error. */
1347+
cpuidle_play_dead();
1348+
hlt_play_dead();
13891349
}
13901350

13911351
#else /* ... !CONFIG_HOTPLUG_CPU */

arch/x86/power/hibernate.c

Lines changed: 6 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -192,7 +192,8 @@ int relocate_restore_code(void)
192192

193193
int arch_resume_nosmt(void)
194194
{
195-
int ret = 0;
195+
int ret;
196+
196197
/*
197198
* We reached this while coming out of hibernation. This means
198199
* that SMT siblings are sleeping in hlt, as mwait is not safe
@@ -206,18 +207,10 @@ int arch_resume_nosmt(void)
206207
* Called with hotplug disabled.
207208
*/
208209
cpu_hotplug_enable();
209-
if (cpu_smt_control == CPU_SMT_DISABLED ||
210-
cpu_smt_control == CPU_SMT_FORCE_DISABLED) {
211-
enum cpuhp_smt_control old = cpu_smt_control;
212-
213-
ret = cpuhp_smt_enable();
214-
if (ret)
215-
goto out;
216-
ret = cpuhp_smt_disable(old);
217-
if (ret)
218-
goto out;
219-
}
220-
out:
210+
211+
ret = arch_cpu_rescan_dead_smt_siblings();
212+
221213
cpu_hotplug_disable();
214+
222215
return ret;
223216
}

drivers/acpi/internal.h

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -175,6 +175,12 @@ bool processor_physically_present(acpi_handle handle);
175175
static inline void acpi_early_processor_control_setup(void) {}
176176
#endif
177177

178+
#ifdef CONFIG_ACPI_PROCESSOR_CSTATE
179+
void acpi_idle_rescan_dead_smt_siblings(void);
180+
#else
181+
static inline void acpi_idle_rescan_dead_smt_siblings(void) {}
182+
#endif
183+
178184
/* --------------------------------------------------------------------------
179185
Embedded Controller
180186
-------------------------------------------------------------------------- */

drivers/acpi/processor_driver.c

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -279,6 +279,9 @@ static int __init acpi_processor_driver_init(void)
279279
* after acpi_cppc_processor_probe() has been called for all online CPUs
280280
*/
281281
acpi_processor_init_invariance_cppc();
282+
283+
acpi_idle_rescan_dead_smt_siblings();
284+
282285
return 0;
283286
err:
284287
driver_unregister(&acpi_processor_driver);

drivers/acpi/processor_idle.c

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -24,6 +24,8 @@
2424
#include <acpi/processor.h>
2525
#include <linux/context_tracking.h>
2626

27+
#include "internal.h"
28+
2729
/*
2830
* Include the apic definitions for x86 to have the APIC timer related defines
2931
* available also for UP (on SMP it gets magically included via linux/smp.h).
@@ -55,6 +57,12 @@ struct cpuidle_driver acpi_idle_driver = {
5557
};
5658

5759
#ifdef CONFIG_ACPI_PROCESSOR_CSTATE
60+
void acpi_idle_rescan_dead_smt_siblings(void)
61+
{
62+
if (cpuidle_get_driver() == &acpi_idle_driver)
63+
arch_cpu_rescan_dead_smt_siblings();
64+
}
65+
5866
static
5967
DEFINE_PER_CPU(struct acpi_processor_cx * [CPUIDLE_STATE_MAX], acpi_cstate);
6068

drivers/cpufreq/rcpufreq_dt.rs

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -26,9 +26,9 @@ fn find_supply_name_exact(dev: &Device, name: &str) -> Option<CString> {
2626
}
2727

2828
/// Finds supply name for the CPU from DT.
29-
fn find_supply_names(dev: &Device, cpu: u32) -> Option<KVec<CString>> {
29+
fn find_supply_names(dev: &Device, cpu: cpu::CpuId) -> Option<KVec<CString>> {
3030
// Try "cpu0" for older DTs, fallback to "cpu".
31-
let name = (cpu == 0)
31+
let name = (cpu.as_u32() == 0)
3232
.then(|| find_supply_name_exact(dev, "cpu0"))
3333
.flatten()
3434
.or_else(|| find_supply_name_exact(dev, "cpu"))?;

drivers/idle/intel_idle.c

Lines changed: 7 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -152,8 +152,8 @@ static __always_inline int __intel_idle(struct cpuidle_device *dev,
152152
int index, bool irqoff)
153153
{
154154
struct cpuidle_state *state = &drv->states[index];
155-
unsigned long eax = flg2MWAIT(state->flags);
156-
unsigned long ecx = 1*irqoff; /* break on interrupt flag */
155+
unsigned int eax = flg2MWAIT(state->flags);
156+
unsigned int ecx = 1*irqoff; /* break on interrupt flag */
157157

158158
mwait_idle_with_hints(eax, ecx);
159159

@@ -226,9 +226,9 @@ static __cpuidle int intel_idle_xstate(struct cpuidle_device *dev,
226226
static __cpuidle int intel_idle_s2idle(struct cpuidle_device *dev,
227227
struct cpuidle_driver *drv, int index)
228228
{
229-
unsigned long ecx = 1; /* break on interrupt flag */
230229
struct cpuidle_state *state = &drv->states[index];
231-
unsigned long eax = flg2MWAIT(state->flags);
230+
unsigned int eax = flg2MWAIT(state->flags);
231+
unsigned int ecx = 1; /* break on interrupt flag */
232232

233233
if (state->flags & CPUIDLE_FLAG_INIT_XSTATE)
234234
fpu_idle_fpregs();
@@ -2507,6 +2507,8 @@ static int __init intel_idle_init(void)
25072507
pr_debug("Local APIC timer is reliable in %s\n",
25082508
boot_cpu_has(X86_FEATURE_ARAT) ? "all C-states" : "C1");
25092509

2510+
arch_cpu_rescan_dead_smt_siblings();
2511+
25102512
return 0;
25112513

25122514
hp_setup_fail:
@@ -2518,7 +2520,7 @@ static int __init intel_idle_init(void)
25182520
return retval;
25192521

25202522
}
2521-
device_initcall(intel_idle_init);
2523+
subsys_initcall_sync(intel_idle_init);
25222524

25232525
/*
25242526
* We are not really modular, but we used to support that. Meaning we also

include/linux/cpu.h

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -120,6 +120,7 @@ extern void cpu_maps_update_begin(void);
120120
extern void cpu_maps_update_done(void);
121121
int bringup_hibernate_cpu(unsigned int sleep_cpu);
122122
void bringup_nonboot_cpus(unsigned int max_cpus);
123+
int arch_cpu_rescan_dead_smt_siblings(void);
123124

124125
#else /* CONFIG_SMP */
125126
#define cpuhp_tasks_frozen 0
@@ -134,6 +135,8 @@ static inline void cpu_maps_update_done(void)
134135

135136
static inline int add_cpu(unsigned int cpu) { return 0;}
136137

138+
static inline int arch_cpu_rescan_dead_smt_siblings(void) { return 0; }
139+
137140
#endif /* CONFIG_SMP */
138141
extern const struct bus_type cpu_subsys;
139142

rust/helpers/cpu.c

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,8 @@
1+
// SPDX-License-Identifier: GPL-2.0
2+
3+
#include <linux/smp.h>
4+
5+
unsigned int rust_helper_raw_smp_processor_id(void)
6+
{
7+
return raw_smp_processor_id();
8+
}

rust/helpers/helpers.c

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,7 @@
1313
#include "build_assert.c"
1414
#include "build_bug.c"
1515
#include "clk.c"
16+
#include "cpu.c"
1617
#include "cpufreq.c"
1718
#include "cpumask.c"
1819
#include "cred.c"

0 commit comments

Comments
 (0)