From 6fd32ea389155c998e4ffe201e7a553ae953e2be Mon Sep 17 00:00:00 2001 From: DevomB Date: Thu, 29 Oct 2026 07:41:38 -0700 Subject: [PATCH] Build the P-state drivers, so a laptop's clock scales Neither X86_INTEL_PSTATE nor X86_AMD_PSTATE has a Kconfig default, and x86_64_defconfig names neither, so every machine ran acpi-cpufreq under defconfig's userspace governor, which holds the clock where the firmware left it, and power.sh found no energy_performance_preference to set. Both are built in. amd-pstate starts in active mode with its dynamic EPP off, so the kernel does not override what power.sh sets from the charger. A processor neither takes falls back to acpi-cpufreq under schedutil. Both drivers join the critical options, so a fragment that loses one fails. --- build/config/kernel/boot.fragment | 14 ++++++++++++++ build/lib/kconfig-check.sh | 6 ++++-- docs/design/laptop.md | 4 ++++ tools/tests/kconfig-critical.sh | 2 +- 4 files changed, 23 insertions(+), 3 deletions(-) diff --git a/build/config/kernel/boot.fragment b/build/config/kernel/boot.fragment index 9a2e3afd..4292510b 100644 --- a/build/config/kernel/boot.fragment +++ b/build/config/kernel/boot.fragment @@ -233,6 +233,20 @@ CONFIG_PM_DEBUG=y CONFIG_INTEL_VSEC=m CONFIG_INTEL_PMT_TELEMETRY=m CONFIG_INTEL_PMC_CORE=m +# The processor's own clock control from the firmware's CPPC table: intel_pstate +# from Sandy Bridge on, amd-pstate from Zen 2 on. Neither has a Kconfig default +# and defconfig names neither, so without them every machine ran acpi-cpufreq +# under defconfig's userspace governor, which holds the clock where the firmware +# left it and gives power.sh no energy preference to set. amd-pstate starts in +# active mode, with the hint; its dynamic EPP stays off, as power.sh sets the +# hint from the charger. A processor neither takes (no _CPC, or CPPC turned off +# in the firmware's setup) falls back to acpi-cpufreq, scaled by schedutil. +CONFIG_X86_INTEL_PSTATE=y +CONFIG_X86_AMD_PSTATE=y +CONFIG_X86_AMD_PSTATE_DEFAULT_MODE=3 +# CONFIG_X86_AMD_PSTATE_DYNAMIC_EPP is not set +CONFIG_CPU_FREQ_DEFAULT_GOV_SCHEDUTIL=y +# CONFIG_CPU_FREQ_DEFAULT_GOV_USERSPACE is not set # The power key on Intel laptops whose firmware sends it, and the wake from # s2idle by it, to the HID event filter (INT33D5, INTC1051 and later) or the # virtual button device (INT33D6) instead of ACPI's power button: without these diff --git a/build/lib/kconfig-check.sh b/build/lib/kconfig-check.sh index 67ffa80b..bc840fd3 100644 --- a/build/lib/kconfig-check.sh +++ b/build/lib/kconfig-check.sh @@ -18,7 +18,8 @@ _kconfig_load() { # <.config> # and HID over I2C behind Intel's LPSS or AMD's DesignWare controller, with the pin controllers its # interrupt comes through. SERIO_I8042, I2C_HID_CORE, PINCTRL_INTEL and USB_XHCI_PCI are not # boot.fragment lines: ATKBD, I2C_HID_ACPI and the pin controllers select the first three, and -# xHCI brings the last by default. +# xHCI brings the last by default. The two P-state drivers are bool only and default off: losing +# one leaves that maker's processors at a fixed clock with no energy preference. KCONFIG_CRITICAL="CONFIG_SECURITY_LANDLOCK CONFIG_SECCOMP_FILTER CONFIG_USER_NS CONFIG_NET_NS CONFIG_EFI_STUB CONFIG_CMDLINE_BOOL CONFIG_CMDLINE_OVERRIDE CONFIG_DM_INIT CONFIG_EFIVAR_FS CONFIG_OVERLAY_FS CONFIG_DRM_VIRTIO_GPU @@ -34,7 +35,8 @@ CONFIG_MFD_INTEL_LPSS_PCI=y CONFIG_MFD_INTEL_LPSS_ACPI=y CONFIG_PINCTRL_INTEL=y CONFIG_PINCTRL_SUNRISEPOINT=y CONFIG_PINCTRL_CANNONLAKE=y CONFIG_PINCTRL_ICELAKE=y CONFIG_PINCTRL_JASPERLAKE=y CONFIG_PINCTRL_ELKHARTLAKE=y CONFIG_PINCTRL_LAKEFIELD=y CONFIG_PINCTRL_TIGERLAKE=y CONFIG_PINCTRL_ALDERLAKE=y CONFIG_PINCTRL_METEORLAKE=y -CONFIG_PINCTRL_METEORPOINT=y CONFIG_PINCTRL_INTEL_PLATFORM=y" +CONFIG_PINCTRL_METEORPOINT=y CONFIG_PINCTRL_INTEL_PLATFORM=y +CONFIG_X86_INTEL_PSTATE=y CONFIG_X86_AMD_PSTATE=y" # kconfig_critical_check <.config>: 0 when every bare entry is =y or =m and every OPTION=y one =y. kconfig_critical_check() { diff --git a/docs/design/laptop.md b/docs/design/laptop.md index bda079e5..738fde7f 100644 --- a/docs/design/laptop.md +++ b/docs/design/laptop.md @@ -502,6 +502,10 @@ and the power key, idle and inhibitors, suspend, and runtime directories rather than the battery's running down, so a machine that outdraws its charger under load does not swing between the two, on each processor policy that offers it (amd-pstate and intel_pstate both do). + Both are built in (`boot.fragment`), amd-pstate in active mode with its + dynamic EPP off, so the kernel does not override what this service sets. + A processor neither takes falls back to acpi-cpufreq, scaled by + schedutil, and offers no preference. PCIe link power and NVMe power states keep the kernel's defaults, and no rule turns on USB autosuspend for input devices, which too often misbehave with it. diff --git a/tools/tests/kconfig-critical.sh b/tools/tests/kconfig-critical.sh index 2d26c7e8..06d8778f 100755 --- a/tools/tests/kconfig-critical.sh +++ b/tools/tests/kconfig-critical.sh @@ -1,7 +1,7 @@ #!/usr/bin/env bash # kconfig_critical_check against a stand-in .config: a bare entry takes =y or =m, one written # OPTION=y only =y, and either fails an option not set. Then the shipped list against -# boot.fragment: each keyboard link it holds built in is a =y line there, but the four that are +# boot.fragment: each entry it holds built in is a =y line there, but the four that are # not boot.fragment lines (kconfig-check.sh says what brings them). Offline. set -uo pipefail ROOT="$(cd "$(dirname "${BASH_SOURCE[0]}")/../.." && pwd)"