diff options
| author | Linus Torvalds <torvalds@linux-foundation.org> | 2026-08-18 08:47:09 -0700 |
|---|---|---|
| committer | Linus Torvalds <torvalds@linux-foundation.org> | 2026-08-18 08:47:09 -0700 |
| commit | a5778046a02570fd23bdf0b48dce330237d1996c (patch) | |
| tree | 4c9d59146cd9a292b63777f803cee958a05e3f59 /kernel | |
| parent | 0d508f1745b57272d4d4a3d50dc35aa2a3682238 (diff) | |
| parent | 7544a367adc1ce5e9cc62315b4c32dc72b509451 (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/Kconfig | 10 | ||||
| -rw-r--r-- | kernel/power/snapshot.c | 47 | ||||
| -rw-r--r-- | kernel/power/swap.c | 34 | ||||
| -rw-r--r-- | kernel/power/wakelock.c | 2 | ||||
| -rw-r--r-- | kernel/sched/cpufreq_schedutil.c | 8 |
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(©_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 |
