summaryrefslogtreecommitdiff
path: root/kernel
diff options
context:
space:
mode:
authorLinus Torvalds <torvalds@linux-foundation.org>2026-08-18 08:47:09 -0700
committerLinus Torvalds <torvalds@linux-foundation.org>2026-08-18 08:47:09 -0700
commita5778046a02570fd23bdf0b48dce330237d1996c (patch)
tree4c9d59146cd9a292b63777f803cee958a05e3f59 /kernel
parent0d508f1745b57272d4d4a3d50dc35aa2a3682238 (diff)
parent7544a367adc1ce5e9cc62315b4c32dc72b509451 (diff)
Merge tag 'pm-7.3-rc1' of git://git.kernel.org/pub/scm/linux/kernel/git/rafael/linux-pm
Pull power management updates from Rafael Wysocki: "As has been the case for quite some time, this set of changes is dominated by cpufreq updates including intel-pstate and amd-pstate driver updates, minor fixes and cleanups of other assorted cpufreq drivers, schedutil governor updates, fixes of the Rust bindings, new hardware support (IPQ5210 in qcom-nvmem), and some updates of self tests related to cpufreq. The second largest group of changes are cpuidle updates consisting of intel_idle driver updates and ACPI processor idle driver updates, both mostly related to ACPI _LPI support. There are also updates related to system sleep, mostly in the hibernation core code, two operating performance points (OPP) updates, one runtime PM framework update, one power capping update, and some tools updates including the addition of ACPI CPPC support to cpupower. Specifics: - Minor fixes and cleanups in assorted cpufreq drivers (Dan Carpenter, Guru Das Srinagesh, Haoxiang Li, Karl Mehltretter, Sasha Finkelstein, and Pan Chuang) - Fix cpufreq table creation and bios_limits() callback in the Rust bindings (Priya Bala Govindasamy) - Add IPQ5210 support to qcom-nvmem driver (Varadarajan Narayanan) - Adjust the .adjust_perf() cpufreq driver callback to allow the maximum performance value to be passed to drivers and update the intel_pstate driver to use it (Rafael Wysocki) - Set policy->cur to the actual requested frequency in the intel_pstate driver when the performance policy is used (Rafael Wysocki) - Simplify HWP handling on Broadwell processors in intel_pstate (Rafael Wysocki) - Fix setting minimum P-state at init time in intel_pstate (Rafael Wysocki) - Consolidate frequency values computation in intel_pstate and clean up code in that driver (Rafael Wysocki) - Add missing kernel-doc descriptions for structure and union members in the amd-pstate driver (David Vernet) - Handle missing policy in dynamic EPP callbacks in the amd-pstate driver (EDAMAMEX) - Introduce EXPORT_SYMBOL_FOR_PSTATE_UT() to export amd-pstate driver symbols to the amd-pstate-ut subdriver (K Prateek Nayak) - Add dynamic EPP as an "energy_performance_preference" mode in amd-pstate, remove the "amd_dynamic_epp" kernel command line option and the "dynamic_epp" sysfs attribute, and update the dynamic_epp documentation accordingly (K Prateek Nayak) - Add unit tests for CPPC Performance Priority and the "dynamic" EPP mode in the amd-pstate driver (K Prateek Nayak) - Set min_limit_freq based on bios_min_perf in amd-pstate and remove the defensive check for bios_min_perf from it (K Prateek Nayak) - Fix EPP return type and handle errors in amd-pstate during initialization, toggle auto_sel in active mode on shared memory systems, and cache the firmware programmed EPP value (Marco Scardovi) - Skip tests in amd-pstate-ut if the amd-pstate driver is not in active use (Qianheng Peng) - Replace sprintf() with sysfs_emit() in sysfs show in the cpufreq schedutil governor and fix a self-contradictory comment in sugov_iowait_apply() (Zhongqiu Han) - Fix the usage example for the sampling_rate tunable of the ondemand cpufreq governor in admin-guide (wangxiaodong) - Avoid using deep idle states during initialization in the intel_idle driver to work around device handling issues (Rafael Wysocki) - Fix and refactor the ACPI processor driver code related to ACPI _LPI support and add ACPI _LPI support to intel_idle based on that ACPI processor driver update (Rafael Wysocki) - Backup and restore governor for cpufreq sptests (Yiwei Lin) - Remove unnecessary sudo from quick_shuffle() and remove unused local variables from switch_show_governor() in cpufreq selftests (Jinseok Kim) - Rename the PM core module parameter prefix to "pm" and allow the PM transition (DPM) watchdog to be disabled by default (Tzung-Bi Shih) - Fix off-by-one in wakelocks number limit check in the system sleep sysfs interface (Haowen Tu) - Remove kernel-doc markings from helper descriptions in the core hibernation code (Adi Nata) - Use %pe to print error pointer values in the hibernation core (Ronan Marchal) - Fix memory leak in snapshot_write_next() error path (Malaya Kumar Rout) - Delay allocating and linking the next swap_map_page in the hibernation image saving code until another image page actually needs to be recorded (Haesung Kim) - Fix cleanup ordering around scope-based pointers in OPP (Gregor Herburger). - Use clk_get_optional() for optional clocks in OPP (Praveen Talari). - Stop setting runtime_error on runtime resume callback failures to allow drivers to recover from resume issues (Praveen Talari) - Handle PMU registration failure during probe in the intel_rapl_tpmi driver (Sumeet Pawnikar) - Avoid optional imports in intel_pstate_tracer unless they are really needed (Yousef Alhouseen) - Add generic CPPC performance display to the cpupower utility, build and call CPPC information on non-AMD processors, make cpupower print kernel and hardware frequency information, and add libm to cpupower for generic CPPC view (Jeremy Linton) - Remove conditional return with no effect from cpupower (Sang-Heon Jeon)" * tag 'pm-7.3-rc1' of git://git.kernel.org/pub/scm/linux/kernel/git/rafael/linux-pm: (76 commits) cpufreq: imx6q: fix out-of-bounds write when probed more than once cpufreq: imx6q: fix devres accumulation across driver rebind rust: cpufreq: Fix temporary write in Registration::bios_limit_callback rust: cpufreq: Add CPUFREQ_TABLE_END as last table entry in TableBuilder::to_table opp: Use clk_get_optional() to avoid leaving opp_table->clk as an error pointer intel_idle: Avoid using deep idle states during initialization cpupower: remove conditional return with no effect cpufreq: intel_pstate: Adjust policy->cur in active mode to policy cpufreq/amd-pstate: Document missing kernel-doc members cpufreq/amd-pstate-ut: Add unit test for CPPC Performance Priority cpufreq/amd-pstate-ut: Add unit test for "dynamic" EPP mode cpufreq/amd-pstate: Reduce the scope of exported symbols Documentation/amd-pstate: Update dynamic_epp documentation with new behavior cpufreq/amd-pstate: Remove "amd_dynamic_epp" cmdline and "dynamic_epp" sysfs cpufreq/amd-pstate: Add dynamic EPP as an "energy_performance_preference" mode cpufreq/amd-pstate: Extract platform profile to EPP conversion into a helper cpufreq/amd-pstate: Remove the defensive check for bios_min_perf cpufreq/amd-pstate: Set min_limit_freq based on bios_min_perf powercap: intel_rapl_tpmi: Handle PMU registration failure during probe PM: sleep: Allow disabling DPM watchdog by default ...
Diffstat (limited to 'kernel')
-rw-r--r--kernel/power/Kconfig10
-rw-r--r--kernel/power/snapshot.c47
-rw-r--r--kernel/power/swap.c34
-rw-r--r--kernel/power/wakelock.c2
-rw-r--r--kernel/sched/cpufreq_schedutil.c8
5 files changed, 62 insertions, 39 deletions
diff --git a/kernel/power/Kconfig b/kernel/power/Kconfig
index 530c897311d4..71165e7f04f4 100644
--- a/kernel/power/Kconfig
+++ b/kernel/power/Kconfig
@@ -268,6 +268,16 @@ config DPM_WATCHDOG
captured in pstore device for inspection in subsequent
boot session.
+config DPM_WATCHDOG_ENABLED
+ bool "Enable DPM watchdog by default"
+ depends on DPM_WATCHDOG
+ default y
+ help
+ If you say Y here, the DPM watchdog will be enabled by default.
+ If you say N, it will be compiled in but disabled. It can be
+ enabled at boot time via the "pm.dpm_watchdog_enabled" kernel
+ parameter or at runtime via sysfs.
+
config DPM_WATCHDOG_TIMEOUT
int "Watchdog timeout to panic in seconds"
range 1 120
diff --git a/kernel/power/snapshot.c b/kernel/power/snapshot.c
index d933b5b2c05d..b209712cb2c3 100644
--- a/kernel/power/snapshot.c
+++ b/kernel/power/snapshot.c
@@ -458,7 +458,7 @@ static struct rtree_node *alloc_rtree_node(gfp_t gfp_mask, int safe_needed,
return node;
}
-/**
+/*
* add_rtree_block - Add a new leave node to the radix tree.
*
* The leave nodes need to be allocated in order to keep the leaves
@@ -528,7 +528,7 @@ static int add_rtree_block(struct mem_zone_bm_rtree *zone, gfp_t gfp_mask,
static void free_zone_bm_rtree(struct mem_zone_bm_rtree *zone,
int clear_nosave_free);
-/**
+/*
* create_zone_bm_rtree - Create a radix tree for one zone.
*
* Allocated the mem_zone_bm_rtree structure and initializes it.
@@ -566,7 +566,7 @@ static struct mem_zone_bm_rtree *create_zone_bm_rtree(gfp_t gfp_mask,
return zone;
}
-/**
+/*
* free_zone_bm_rtree - Free the memory of the radix tree.
*
* Free all node pages of the radix tree. The mem_zone_bm_rtree
@@ -678,7 +678,7 @@ static int create_mem_extents(struct list_head *list, gfp_t gfp_mask)
return 0;
}
-/**
+/*
* memory_bm_create - Allocate memory for a memory bitmap.
*/
static int memory_bm_create(struct memory_bitmap *bm, gfp_t gfp_mask,
@@ -720,7 +720,7 @@ static int memory_bm_create(struct memory_bitmap *bm, gfp_t gfp_mask,
goto Exit;
}
-/**
+/*
* memory_bm_free - Free memory occupied by the memory bitmap.
* @bm: Memory bitmap.
*/
@@ -736,7 +736,7 @@ static void memory_bm_free(struct memory_bitmap *bm, int clear_nosave_free)
INIT_LIST_HEAD(&bm->zones);
}
-/**
+/*
* memory_bm_find_bit - Find the bit for a given PFN in a memory bitmap.
*
* Find the bit in memory bitmap @bm that corresponds to the given PFN.
@@ -988,7 +988,7 @@ static void memory_bm_recycle(struct memory_bitmap *bm)
}
}
-/**
+/*
* register_nosave_region - Register a region of unsaveable memory.
*
* Register a range of page frames the contents of which should not be saved
@@ -1305,7 +1305,7 @@ static unsigned int count_free_highmem_pages(void)
return cnt;
}
-/**
+/*
* saveable_highmem_page - Check if a highmem page is saveable.
*
* Determine whether a highmem page should be included in a hibernation image.
@@ -1362,7 +1362,7 @@ static unsigned int count_highmem_pages(void)
}
#endif /* CONFIG_HIGHMEM */
-/**
+/*
* saveable_page - Check if the given page is saveable.
*
* Determine whether a non-highmem page should be included in a hibernation
@@ -1440,7 +1440,7 @@ static inline bool do_copy_page(long *dst, long *src)
return !z;
}
-/**
+/*
* safe_copy_page - Copy a page in a safe way.
*
* Check if the page we are going to copy is marked as present in the kernel
@@ -1687,7 +1687,7 @@ static unsigned long preallocate_image_highmem(unsigned long nr_pages)
return preallocate_image_pages(nr_pages, GFP_IMAGE | __GFP_HIGHMEM);
}
-/**
+/*
* __fraction - Compute (an approximation of) x * (multiplier / base).
*/
static unsigned long __fraction(u64 x, u64 multiplier, u64 base)
@@ -1982,7 +1982,7 @@ int hibernate_preallocate_memory(void)
}
#ifdef CONFIG_HIGHMEM
-/**
+/*
* count_pages_for_highmem - Count non-highmem pages needed for copying highmem.
*
* Compute the number of non-highmem pages that will be necessary for creating
@@ -2003,7 +2003,7 @@ static unsigned int count_pages_for_highmem(unsigned int nr_highmem)
static unsigned int count_pages_for_highmem(unsigned int nr_highmem) { return 0; }
#endif /* CONFIG_HIGHMEM */
-/**
+/*
* enough_free_mem - Check if there is enough free memory for the image.
*/
static int enough_free_mem(unsigned int nr_pages, unsigned int nr_highmem)
@@ -2023,7 +2023,7 @@ static int enough_free_mem(unsigned int nr_pages, unsigned int nr_highmem)
}
#ifdef CONFIG_HIGHMEM
-/**
+/*
* get_highmem_buffer - Allocate a buffer for highmem pages.
*
* If there are some highmem pages in the hibernation image, we may need a
@@ -2035,7 +2035,7 @@ static inline int get_highmem_buffer(int safe_needed)
return buffer ? 0 : -ENOMEM;
}
-/**
+/*
* alloc_highmem_pages - Allocate some highmem pages for the image.
*
* Try to allocate as many pages as needed, but if the number of free highmem
@@ -2065,7 +2065,7 @@ static inline unsigned int alloc_highmem_pages(struct memory_bitmap *bm,
unsigned int n) { return 0; }
#endif /* CONFIG_HIGHMEM */
-/**
+/*
* swsusp_alloc - Allocate memory for hibernation image.
*
* We first try to allocate as many highmem pages as there are
@@ -2292,7 +2292,7 @@ static void duplicate_memory_bitmap(struct memory_bitmap *dst,
}
}
-/**
+/*
* mark_unsafe_pages - Mark pages that were used before hibernation.
*
* Mark the pages that cannot be used for storing the image during restoration,
@@ -2330,7 +2330,7 @@ static int check_header(struct swsusp_info *info)
return 0;
}
-/**
+/*
* load_header - Check the image header and copy the data from it.
*/
static int load_header(struct swsusp_info *info)
@@ -2483,7 +2483,7 @@ static int prepare_highmem_image(struct memory_bitmap *bm,
static struct page *last_highmem_page;
-/**
+/*
* get_highmem_page_buffer - Prepare a buffer to store a highmem image page.
*
* For a given highmem image page get a buffer that suspend_write_next() should
@@ -2706,7 +2706,7 @@ static int prepare_image(struct memory_bitmap *new_bm, struct memory_bitmap *bm,
return error;
}
-/**
+/*
* get_buffer - Get the address to store the next image data page.
*
* Get the address that snapshot_write_next() should return to its caller to
@@ -2797,9 +2797,10 @@ next:
return error;
error = memory_bm_create(&zero_bm, GFP_ATOMIC, PG_ANY);
- if (error)
+ if (error) {
+ memory_bm_free(&copy_bm, PG_UNSAFE_CLEAR);
return error;
-
+ }
nr_zero_pages = 0;
hibernate_restore_protection_begin();
@@ -2843,7 +2844,7 @@ next:
return PAGE_SIZE;
}
-/**
+/*
* snapshot_write_finalize - Complete the loading of a hibernation image.
*
* Must be called after the last call to snapshot_write_next() in case the last
diff --git a/kernel/power/swap.c b/kernel/power/swap.c
index c626e9dc3c1c..c78f1593600b 100644
--- a/kernel/power/swap.c
+++ b/kernel/power/swap.c
@@ -430,19 +430,22 @@ static int swap_write_page(struct swap_map_handle *handle, void *buf,
if (!handle->cur)
return -EINVAL;
- offset = alloc_swapdev_block(root_swap);
- error = write_page(buf, offset, hb);
- if (error)
- return error;
- handle->cur->entries[handle->k++] = offset;
+
+ /*
+ * If the current map page is full, allocate and link next one first.
+ * Delaying this until here avoids writing an empty swap map page when
+ * the image size is an exact MAP_PAGE_ENTRIES multiple.
+ */
if (handle->k >= MAP_PAGE_ENTRIES) {
offset = alloc_swapdev_block(root_swap);
if (!offset)
return -ENOSPC;
+
handle->cur->next_swap = offset;
error = write_page(handle->cur, handle->cur_swap, hb);
if (error)
- goto out;
+ return error;
+
clear_page(handle->cur);
handle->cur_swap = offset;
handle->k = 0;
@@ -450,7 +453,7 @@ static int swap_write_page(struct swap_map_handle *handle, void *buf,
if (hb && low_free_pages() <= handle->reqd_free_pages) {
error = hib_wait_io(hb);
if (error)
- goto out;
+ return error;
/*
* Recalculate the number of required free pages, to
* make sure we never take more than half.
@@ -458,14 +461,21 @@ static int swap_write_page(struct swap_map_handle *handle, void *buf,
handle->reqd_free_pages = reqd_free_pages();
}
}
- out:
- return error;
+
+ offset = alloc_swapdev_block(root_swap);
+ error = write_page(buf, offset, hb);
+ if (error)
+ return error;
+ handle->cur->entries[handle->k++] = offset;
+ return 0;
}
static int flush_swap_writer(struct swap_map_handle *handle)
{
- if (handle->cur && handle->cur_swap)
+ if (handle->cur && handle->cur_swap && handle->k)
return write_page(handle->cur, handle->cur_swap, NULL);
+ else if (handle->cur && handle->cur_swap)
+ return 0;
else
return -EINVAL;
}
@@ -739,7 +749,7 @@ static int save_compressed_image(struct swap_map_handle *handle,
data[thr].cc = crypto_alloc_acomp(hib_comp_algo, 0, CRYPTO_ALG_ASYNC);
if (IS_ERR_OR_NULL(data[thr].cc)) {
- pr_err("Could not allocate comp stream %ld\n", PTR_ERR(data[thr].cc));
+ pr_err("Could not allocate comp stream %pe\n", data[thr].cc);
ret = -EFAULT;
goto out_clean;
}
@@ -1243,7 +1253,7 @@ static int load_compressed_image(struct swap_map_handle *handle,
data[thr].cc = crypto_alloc_acomp(hib_comp_algo, 0, CRYPTO_ALG_ASYNC);
if (IS_ERR_OR_NULL(data[thr].cc)) {
- pr_err("Could not allocate comp stream %ld\n", PTR_ERR(data[thr].cc));
+ pr_err("Could not allocate comp stream %pe\n", data[thr].cc);
ret = -EFAULT;
goto out_clean;
}
diff --git a/kernel/power/wakelock.c b/kernel/power/wakelock.c
index fd763da06a87..a8b6bd5ec46b 100644
--- a/kernel/power/wakelock.c
+++ b/kernel/power/wakelock.c
@@ -63,7 +63,7 @@ static unsigned int number_of_wakelocks;
static inline bool wakelocks_limit_exceeded(void)
{
- return number_of_wakelocks > CONFIG_PM_WAKELOCKS_LIMIT;
+ return number_of_wakelocks >= CONFIG_PM_WAKELOCKS_LIMIT;
}
static inline void increment_wakelocks_number(void)
diff --git a/kernel/sched/cpufreq_schedutil.c b/kernel/sched/cpufreq_schedutil.c
index dff4ee04694c..a1782755efcc 100644
--- a/kernel/sched/cpufreq_schedutil.c
+++ b/kernel/sched/cpufreq_schedutil.c
@@ -50,6 +50,7 @@ struct sugov_cpu {
unsigned long util;
unsigned long bw_min;
+ unsigned long bw_max;
/* The field below is for single-CPU policies only: */
#ifdef CONFIG_NO_HZ_COMMON
@@ -232,6 +233,7 @@ static void sugov_get_util(struct sugov_cpu *sg_cpu, unsigned long boost)
util = effective_cpu_util(sg_cpu->cpu, util, &min, &max);
util = max(util, boost);
sg_cpu->bw_min = min;
+ sg_cpu->bw_max = max;
sg_cpu->util = sugov_effective_cpu_perf(sg_cpu->cpu, util, min, max);
}
@@ -314,7 +316,7 @@ static void sugov_iowait_boost(struct sugov_cpu *sg_cpu, u64 time,
* A CPU running a task which woken up after an IO operation can have its
* utilization boosted to speed up the completion of those IO operations.
* The IO boost value is increased each time a task wakes up from IO, in
- * sugov_iowait_apply(), and it's instead decreased by this function,
+ * sugov_iowait_boost(), and it's instead decreased by this function,
* each time an increase has not been requested (!iowait_boost_pending).
*
* A CPU which also appears to have been idle for at least one tick has also
@@ -484,7 +486,7 @@ static void sugov_update_single_perf(struct update_util_data *hook, u64 time,
sg_cpu->util = prev_util;
cpufreq_driver_adjust_perf(sg_policy->policy, sg_cpu->bw_min,
- sg_cpu->util, max_cap);
+ sg_cpu->util, sg_cpu->bw_max, max_cap);
sg_policy->need_freq_update = false;
sg_policy->last_freq_update_time = time;
@@ -590,7 +592,7 @@ static ssize_t rate_limit_us_show(struct gov_attr_set *attr_set, char *buf)
{
struct sugov_tunables *tunables = to_sugov_tunables(attr_set);
- return sprintf(buf, "%u\n", tunables->rate_limit_us);
+ return sysfs_emit(buf, "%u\n", tunables->rate_limit_us);
}
static ssize_t