Skip to content

Commit 7431d90

Browse files
committed
Merge branches 'pm-cpuidle', 'pm-opp' and 'pm-sleep'
Merge cpuidle updates, OPP (operating performance points) library updates, and updates related to system suspend and hibernation for 7.1-rc1: - Refine stopped tick handling in the menu cpuidle governor and rearrange stopped tick handling in the teo cpuidle governor (Rafael Wysocki) - Add Panther Lake C-states table to the intel_idle driver (Artem Bityutskiy) - Clean up dead dependencies on CPU_IDLE in Kconfig (Julian Braha) - Simplify cpuidle_register_device() with guard() (Huisong Li) - Use performance level if available to distinguish between rates in OPP debugfs (Manivannan Sadhasivam) - Fix scoped_guard in dev_pm_opp_xlate_required_opp() (Viresh Kumar) - Return -ENODATA if the snapshot image is not loaded (Alberto Garcia) - Remove inclusion of crypto/hash.h from hibernate_64.c on x86 (Eric Biggers) * pm-cpuidle: cpuidle: Simplify cpuidle_register_device() with guard() cpuidle: clean up dead dependencies on CPU_IDLE in Kconfig intel_idle: Add Panther Lake C-states table cpuidle: governors: teo: Rearrange stopped tick handling cpuidle: governors: menu: Refine stopped tick handling * pm-opp: OPP: Move break out of scoped_guard in dev_pm_opp_xlate_required_opp() OPP: debugfs: Use performance level if available to distinguish between rates * pm-sleep: PM: hibernate: return -ENODATA if the snapshot image is not loaded PM: hibernate: x86: Remove inclusion of crypto/hash.h
4 parents 83e9903 + 629be87 + e810f1f + 949a5ed commit 7431d90

12 files changed

Lines changed: 114 additions & 78 deletions

File tree

arch/x86/power/hibernate_64.c

Lines changed: 0 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -14,8 +14,6 @@
1414
#include <linux/kdebug.h>
1515
#include <linux/pgtable.h>
1616

17-
#include <crypto/hash.h>
18-
1917
#include <asm/e820/api.h>
2018
#include <asm/init.h>
2119
#include <asm/proto.h>

drivers/cpuidle/Kconfig

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -81,7 +81,7 @@ config HALTPOLL_CPUIDLE
8181
before halting in the guest (more efficient than polling in the
8282
host via halt_poll_ns for some scenarios).
8383

84-
endif
84+
endif # CPU_IDLE
8585

8686
config ARCH_NEEDS_CPU_IDLE_COUPLED
8787
def_bool n

drivers/cpuidle/Kconfig.mips

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,7 @@
44
#
55
config MIPS_CPS_CPUIDLE
66
bool "CPU Idle driver for MIPS CPS platforms"
7-
depends on CPU_IDLE && MIPS_CPS
7+
depends on MIPS_CPS
88
depends on SYS_SUPPORTS_MIPS_CPS
99
select ARCH_NEEDS_CPU_IDLE_COUPLED if MIPS_MT || CPU_MIPSR6
1010
select GENERIC_CLOCKEVENTS_BROADCAST if SMP

drivers/cpuidle/Kconfig.powerpc

Lines changed: 0 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,6 @@
44
#
55
config PSERIES_CPUIDLE
66
bool "Cpuidle driver for pSeries platforms"
7-
depends on CPU_IDLE
87
depends on PPC_PSERIES
98
default y
109
help
@@ -13,7 +12,6 @@ config PSERIES_CPUIDLE
1312

1413
config POWERNV_CPUIDLE
1514
bool "Cpuidle driver for powernv platforms"
16-
depends on CPU_IDLE
1715
depends on PPC_POWERNV
1816
default y
1917
help

drivers/cpuidle/cpuidle.c

Lines changed: 5 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -679,16 +679,16 @@ int cpuidle_register_device(struct cpuidle_device *dev)
679679
if (!dev)
680680
return -EINVAL;
681681

682-
mutex_lock(&cpuidle_lock);
682+
guard(mutex)(&cpuidle_lock);
683683

684684
if (dev->registered)
685-
goto out_unlock;
685+
return ret;
686686

687687
__cpuidle_device_init(dev);
688688

689689
ret = __cpuidle_register_device(dev);
690690
if (ret)
691-
goto out_unlock;
691+
return ret;
692692

693693
ret = cpuidle_add_sysfs(dev);
694694
if (ret)
@@ -700,16 +700,14 @@ int cpuidle_register_device(struct cpuidle_device *dev)
700700

701701
cpuidle_install_idle_handler();
702702

703-
out_unlock:
704-
mutex_unlock(&cpuidle_lock);
705-
706703
return ret;
707704

708705
out_sysfs:
709706
cpuidle_remove_sysfs(dev);
710707
out_unregister:
711708
__cpuidle_unregister_device(dev);
712-
goto out_unlock;
709+
710+
return ret;
713711
}
714712

715713
EXPORT_SYMBOL_GPL(cpuidle_register_device);

drivers/cpuidle/governors/gov.h

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -10,5 +10,10 @@
1010
* check the time till the closest expected timer event.
1111
*/
1212
#define RESIDENCY_THRESHOLD_NS (15 * NSEC_PER_USEC)
13+
/*
14+
* If the closest timer is in this range, the governor idle state selection need
15+
* not be adjusted after the scheduler tick has been stopped.
16+
*/
17+
#define SAFE_TIMER_RANGE_NS (2 * TICK_NSEC)
1318

1419
#endif /* __CPUIDLE_GOVERNOR_H */

drivers/cpuidle/governors/menu.c

Lines changed: 9 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -261,13 +261,16 @@ static int menu_select(struct cpuidle_driver *drv, struct cpuidle_device *dev,
261261
predicted_ns = min((u64)timer_us * NSEC_PER_USEC, predicted_ns);
262262
/*
263263
* If the tick is already stopped, the cost of possible short
264-
* idle duration misprediction is much higher, because the CPU
265-
* may be stuck in a shallow idle state for a long time as a
266-
* result of it. In that case, say we might mispredict and use
267-
* the known time till the closest timer event for the idle
268-
* state selection.
264+
* idle duration misprediction is higher because the CPU may get
265+
* stuck in a shallow idle state then. To avoid that, if
266+
* predicted_ns is small enough, say it might be mispredicted
267+
* and use the known time till the closest timer for idle state
268+
* selection unless that timer is going to trigger within
269+
* SAFE_TIMER_RANGE_NS in which case it can be regarded as a
270+
* sufficient safety net.
269271
*/
270-
if (tick_nohz_tick_stopped() && predicted_ns < TICK_NSEC)
272+
if (tick_nohz_tick_stopped() && predicted_ns < TICK_NSEC &&
273+
data->next_timer_ns > SAFE_TIMER_RANGE_NS)
271274
predicted_ns = data->next_timer_ns;
272275
} else {
273276
/*

drivers/cpuidle/governors/teo.c

Lines changed: 34 additions & 47 deletions
Original file line numberDiff line numberDiff line change
@@ -407,50 +407,13 @@ static int teo_select(struct cpuidle_driver *drv, struct cpuidle_device *dev,
407407
* better choice.
408408
*/
409409
if (2 * idx_intercept_sum > cpu_data->total - idx_hit_sum) {
410-
int min_idx = idx0;
411-
412-
if (tick_nohz_tick_stopped()) {
413-
/*
414-
* Look for the shallowest idle state below the current
415-
* candidate one whose target residency is at least
416-
* equal to the tick period length.
417-
*/
418-
while (min_idx < idx &&
419-
drv->states[min_idx].target_residency_ns < TICK_NSEC)
420-
min_idx++;
421-
422-
/*
423-
* Avoid selecting a state with a lower index, but with
424-
* the same target residency as the current candidate
425-
* one.
426-
*/
427-
if (drv->states[min_idx].target_residency_ns ==
428-
drv->states[idx].target_residency_ns)
429-
goto constraint;
430-
}
431-
432-
/*
433-
* If the minimum state index is greater than or equal to the
434-
* index of the state with the maximum intercepts metric and
435-
* the corresponding state is enabled, there is no need to look
436-
* at the deeper states.
437-
*/
438-
if (min_idx >= intercept_max_idx &&
439-
!dev->states_usage[min_idx].disable) {
440-
idx = min_idx;
441-
goto constraint;
442-
}
443-
444410
/*
445411
* Look for the deepest enabled idle state, at most as deep as
446412
* the one with the maximum intercepts metric, whose target
447413
* residency had not been greater than the idle duration in over
448414
* a half of the relevant cases in the past.
449-
*
450-
* Take the possible duration limitation present if the tick
451-
* has been stopped already into account.
452415
*/
453-
for (i = idx - 1, intercept_sum = 0; i >= min_idx; i--) {
416+
for (i = idx - 1, intercept_sum = 0; i >= idx0; i--) {
454417
intercept_sum += cpu_data->state_bins[i].intercepts;
455418

456419
if (dev->states_usage[i].disable)
@@ -463,7 +426,6 @@ static int teo_select(struct cpuidle_driver *drv, struct cpuidle_device *dev,
463426
}
464427
}
465428

466-
constraint:
467429
/*
468430
* If there is a latency constraint, it may be necessary to select an
469431
* idle state shallower than the current candidate one.
@@ -472,13 +434,13 @@ static int teo_select(struct cpuidle_driver *drv, struct cpuidle_device *dev,
472434
idx = constraint_idx;
473435

474436
/*
475-
* If either the candidate state is state 0 or its target residency is
476-
* low enough, there is basically nothing more to do, but if the sleep
477-
* length is not updated, the subsequent wakeup will be counted as an
478-
* "intercept" which may be problematic in the cases when timer wakeups
479-
* are dominant. Namely, it may effectively prevent deeper idle states
480-
* from being selected at one point even if no imminent timers are
481-
* scheduled.
437+
* If the tick has not been stopped and either the candidate state is
438+
* state 0 or its target residency is low enough, there is basically
439+
* nothing more to do, but if the sleep length is not updated, the
440+
* subsequent wakeup will be counted as an "intercept". That may be
441+
* problematic in the cases when timer wakeups are dominant because it
442+
* may effectively prevent deeper idle states from being selected at one
443+
* point even if no imminent timers are scheduled.
482444
*
483445
* However, frequent timers in the RESIDENCY_THRESHOLD_NS range on one
484446
* CPU are unlikely (user space has a default 50 us slack value for
@@ -494,14 +456,39 @@ static int teo_select(struct cpuidle_driver *drv, struct cpuidle_device *dev,
494456
* shallow idle states regardless of the wakeup type, so the sleep
495457
* length need not be known in that case.
496458
*/
497-
if ((!idx || drv->states[idx].target_residency_ns < RESIDENCY_THRESHOLD_NS) &&
459+
if (!tick_nohz_tick_stopped() && (!idx ||
460+
drv->states[idx].target_residency_ns < RESIDENCY_THRESHOLD_NS) &&
498461
(2 * cpu_data->short_idles >= cpu_data->total ||
499462
latency_req < LATENCY_THRESHOLD_NS))
500463
goto out_tick;
501464

502465
duration_ns = tick_nohz_get_sleep_length(&delta_tick);
503466
cpu_data->sleep_length_ns = duration_ns;
504467

468+
/*
469+
* If the tick has been stopped and the closest timer is too far away,
470+
* update the selection to prevent the CPU from getting stuck in a
471+
* shallow idle state for too long.
472+
*/
473+
if (tick_nohz_tick_stopped() && duration_ns > SAFE_TIMER_RANGE_NS &&
474+
drv->states[idx].target_residency_ns < TICK_NSEC) {
475+
/*
476+
* Look for the deepest enabled idle state with exit latency
477+
* within the PM QoS limit and with target residency within
478+
* duration_ns.
479+
*/
480+
for (i = constraint_idx; i > idx; i--) {
481+
if (dev->states_usage[i].disable)
482+
continue;
483+
484+
if (drv->states[i].target_residency_ns <= duration_ns) {
485+
idx = i;
486+
break;
487+
}
488+
}
489+
return idx;
490+
}
491+
505492
if (!idx)
506493
goto out_tick;
507494

drivers/idle/intel_idle.c

Lines changed: 42 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -983,6 +983,43 @@ static struct cpuidle_state mtl_l_cstates[] __initdata = {
983983
.enter = NULL }
984984
};
985985

986+
static struct cpuidle_state ptl_cstates[] __initdata = {
987+
{
988+
.name = "C1",
989+
.desc = "MWAIT 0x00",
990+
.flags = MWAIT2flg(0x00),
991+
.exit_latency = 1,
992+
.target_residency = 1,
993+
.enter = &intel_idle,
994+
.enter_s2idle = intel_idle_s2idle, },
995+
{
996+
.name = "C1E",
997+
.desc = "MWAIT 0x01",
998+
.flags = MWAIT2flg(0x01) | CPUIDLE_FLAG_ALWAYS_ENABLE,
999+
.exit_latency = 10,
1000+
.target_residency = 10,
1001+
.enter = &intel_idle,
1002+
.enter_s2idle = intel_idle_s2idle, },
1003+
{
1004+
.name = "C6S",
1005+
.desc = "MWAIT 0x21",
1006+
.flags = MWAIT2flg(0x21) | CPUIDLE_FLAG_TLB_FLUSHED,
1007+
.exit_latency = 300,
1008+
.target_residency = 300,
1009+
.enter = &intel_idle,
1010+
.enter_s2idle = intel_idle_s2idle, },
1011+
{
1012+
.name = "C10",
1013+
.desc = "MWAIT 0x60",
1014+
.flags = MWAIT2flg(0x60) | CPUIDLE_FLAG_TLB_FLUSHED,
1015+
.exit_latency = 370,
1016+
.target_residency = 2500,
1017+
.enter = &intel_idle,
1018+
.enter_s2idle = intel_idle_s2idle, },
1019+
{
1020+
.enter = NULL }
1021+
};
1022+
9861023
static struct cpuidle_state gmt_cstates[] __initdata = {
9871024
{
9881025
.name = "C1",
@@ -1561,6 +1598,10 @@ static const struct idle_cpu idle_cpu_mtl_l __initconst = {
15611598
.state_table = mtl_l_cstates,
15621599
};
15631600

1601+
static const struct idle_cpu idle_cpu_ptl __initconst = {
1602+
.state_table = ptl_cstates,
1603+
};
1604+
15641605
static const struct idle_cpu idle_cpu_gmt __initconst = {
15651606
.state_table = gmt_cstates,
15661607
};
@@ -1669,6 +1710,7 @@ static const struct x86_cpu_id intel_idle_ids[] __initconst = {
16691710
X86_MATCH_VFM(INTEL_ALDERLAKE, &idle_cpu_adl),
16701711
X86_MATCH_VFM(INTEL_ALDERLAKE_L, &idle_cpu_adl_l),
16711712
X86_MATCH_VFM(INTEL_METEORLAKE_L, &idle_cpu_mtl_l),
1713+
X86_MATCH_VFM(INTEL_PANTHERLAKE_L, &idle_cpu_ptl),
16721714
X86_MATCH_VFM(INTEL_ATOM_GRACEMONT, &idle_cpu_gmt),
16731715
X86_MATCH_VFM(INTEL_SAPPHIRERAPIDS_X, &idle_cpu_spr),
16741716
X86_MATCH_VFM(INTEL_EMERALDRAPIDS_X, &idle_cpu_spr),

drivers/opp/core.c

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2742,8 +2742,8 @@ struct dev_pm_opp *dev_pm_opp_xlate_required_opp(struct opp_table *src_table,
27422742
break;
27432743
}
27442744
}
2745-
break;
27462745
}
2746+
break;
27472747
}
27482748

27492749
if (IS_ERR(dest_opp)) {

0 commit comments

Comments
 (0)