Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux
1
fork

Configure Feed

Select the types of activity you want to include in your feed.

Merge branches 'pm-core', 'pm-runtime' and 'pm-sleep'

Merge changes related to system sleep and runtime PM framework for
6.18-rc1:

- Annotate loops walking device links in the power management core
code as _srcu and add macros for walking device links to reduce the
likelihood of coding mistakes related to them (Rafael Wysocki)

- Document time units for *_time functions in the runtime PM API (Brian
Norris)

- Clear power.must_resume in noirq suspend error path to avoid resuming
a dependant device under a suspended parent or supplier (Rafael
Wysocki)

- Fix GFP mask handling during hybrid suspend and make the amdgpu
driver handle hybrid suspend correctly (Mario Limonciello, Rafael
Wysocki)

- Fix GFP mask handling after aborted hibernation in platform mode and
combine exit paths in power_down() to avoid code duplication (Rafael
Wysocki)

- Use vmalloc_array() and vcalloc() in the hibernation core to avoid
open-coded size computations (Qianfeng Rong)

- Fix typo in hibernation core code comment (Li Jun)

- Call pm_wakeup_clear() in the same place where other functions that do
bookkeeping prior to suspend_prepare() are called (Samuel Wu)

* pm-core:
PM: core: Add two macros for walking device links
PM: core: Annotate loops walking device links as _srcu

* pm-runtime:
PM: runtime: Documentation: ABI: Document time units for *_time

* pm-sleep:
PM: hibernate: Combine return paths in power_down()
PM: hibernate: Restrict GFP mask in power_down()
PM: hibernate: Fix pm_hibernation_mode_is_suspend() build breakage
drm/amd: Fix hybrid sleep
PM: hibernate: Add pm_hibernation_mode_is_suspend()
PM: hibernate: Fix hybrid-sleep
PM: sleep: core: Clear power.must_resume in noirq suspend error path
PM: sleep: Make pm_wakeup_clear() call more clear
PM: hibernate: Fix typo in memory bitmaps description comment
PM: hibernate: Use vmalloc_array() and vcalloc() to improve code

+71 -37
+4 -4
Documentation/ABI/testing/sysfs-devices-power
··· 274 274 Date: Jul 2010 275 275 Contact: Arjan van de Ven <arjan@linux.intel.com> 276 276 Description: 277 - Reports the total time that the device has been active. 278 - Used for runtime PM statistics. 277 + Reports the total time that the device has been active, in 278 + milliseconds. Used for runtime PM statistics. 279 279 280 280 What: /sys/devices/.../power/runtime_suspended_time 281 281 Date: Jul 2010 282 282 Contact: Arjan van de Ven <arjan@linux.intel.com> 283 283 Description: 284 - Reports total time that the device has been suspended. 285 - Used for runtime PM statistics. 284 + Reports total time that the device has been suspended, in 285 + milliseconds. Used for runtime PM statistics. 286 286 287 287 What: /sys/devices/.../power/runtime_usage 288 288 Date: Apr 2010
+8
drivers/base/base.h
··· 251 251 void fw_devlink_drivers_done(void); 252 252 void fw_devlink_probing_done(void); 253 253 254 + #define dev_for_each_link_to_supplier(__link, __dev) \ 255 + list_for_each_entry_srcu(__link, &(__dev)->links.suppliers, c_node, \ 256 + device_links_read_lock_held()) 257 + 258 + #define dev_for_each_link_to_consumer(__link, __dev) \ 259 + list_for_each_entry_srcu(__link, &(__dev)->links.consumers, s_node, \ 260 + device_links_read_lock_held()) 261 + 254 262 /* device pm support */ 255 263 void device_pm_move_to_tail(struct device *dev); 256 264
+20 -12
drivers/base/power/main.c
··· 40 40 41 41 typedef int (*pm_callback_t)(struct device *); 42 42 43 - #define list_for_each_entry_rcu_locked(pos, head, member) \ 44 - list_for_each_entry_rcu(pos, head, member, \ 45 - device_links_read_lock_held()) 46 - 47 43 /* 48 44 * The entries in the dpm_list list are in a depth first order, simply 49 45 * because children are guaranteed to be discovered after parents, and ··· 277 281 * callbacks freeing the link objects for the links in the list we're 278 282 * walking. 279 283 */ 280 - list_for_each_entry_rcu_locked(link, &dev->links.suppliers, c_node) 284 + dev_for_each_link_to_supplier(link, dev) 281 285 if (READ_ONCE(link->status) != DL_STATE_DORMANT) 282 286 dpm_wait(link->supplier, async); 283 287 ··· 334 338 * continue instead of trying to continue in parallel with its 335 339 * unregistration). 336 340 */ 337 - list_for_each_entry_rcu_locked(link, &dev->links.consumers, s_node) 341 + dev_for_each_link_to_consumer(link, dev) 338 342 if (READ_ONCE(link->status) != DL_STATE_DORMANT) 339 343 dpm_wait(link->consumer, async); 340 344 ··· 671 675 idx = device_links_read_lock(); 672 676 673 677 /* Start processing the device's "async" consumers. */ 674 - list_for_each_entry_rcu_locked(link, &dev->links.consumers, s_node) 678 + dev_for_each_link_to_consumer(link, dev) 675 679 if (READ_ONCE(link->status) != DL_STATE_DORMANT) 676 680 dpm_async_with_cleanup(link->consumer, func); 677 681 ··· 720 724 if (dev->power.syscore || dev->power.direct_complete) 721 725 goto Out; 722 726 723 - if (!dev->power.is_noirq_suspended) 727 + if (!dev->power.is_noirq_suspended) { 728 + /* 729 + * This means that system suspend has been aborted in the noirq 730 + * phase before invoking the noirq suspend callback for the 731 + * device, so if device_suspend_late() has left it in suspend, 732 + * device_resume_early() should leave it in suspend either in 733 + * case the early resume of it depends on the noirq resume that 734 + * has not run. 735 + */ 736 + if (dev_pm_skip_suspend(dev)) 737 + dev->power.must_resume = false; 738 + 724 739 goto Out; 740 + } 725 741 726 742 if (!dpm_wait_for_superior(dev, async)) 727 743 goto Out; ··· 1338 1330 idx = device_links_read_lock(); 1339 1331 1340 1332 /* Start processing the device's "async" suppliers. */ 1341 - list_for_each_entry_rcu_locked(link, &dev->links.suppliers, c_node) 1333 + dev_for_each_link_to_supplier(link, dev) 1342 1334 if (READ_ONCE(link->status) != DL_STATE_DORMANT) 1343 1335 dpm_async_with_cleanup(link->supplier, func); 1344 1336 ··· 1392 1384 1393 1385 idx = device_links_read_lock(); 1394 1386 1395 - list_for_each_entry_rcu_locked(link, &dev->links.suppliers, c_node) 1387 + dev_for_each_link_to_supplier(link, dev) 1396 1388 link->supplier->power.must_resume = true; 1397 1389 1398 1390 device_links_read_unlock(idx); ··· 1821 1813 1822 1814 idx = device_links_read_lock(); 1823 1815 1824 - list_for_each_entry_rcu_locked(link, &dev->links.suppliers, c_node) { 1816 + dev_for_each_link_to_supplier(link, dev) { 1825 1817 spin_lock_irq(&link->supplier->power.lock); 1826 1818 link->supplier->power.direct_complete = false; 1827 1819 spin_unlock_irq(&link->supplier->power.lock); ··· 2073 2065 2074 2066 idx = device_links_read_lock(); 2075 2067 2076 - list_for_each_entry_rcu_locked(link, &dev->links.suppliers, c_node) { 2068 + dev_for_each_link_to_supplier(link, dev) { 2077 2069 if (!device_link_test(link, DL_FLAG_PM_RUNTIME)) 2078 2070 continue; 2079 2071
+1 -2
drivers/base/power/runtime.c
··· 1903 1903 1904 1904 idx = device_links_read_lock(); 1905 1905 1906 - list_for_each_entry_rcu(link, &dev->links.suppliers, c_node, 1907 - device_links_read_lock_held()) 1906 + dev_for_each_link_to_supplier(link, dev) 1908 1907 if (device_link_test(link, DL_FLAG_PM_RUNTIME)) { 1909 1908 link->supplier_preactivated = true; 1910 1909 pm_runtime_get_sync(link->supplier);
+1 -1
drivers/gpu/drm/amd/amdgpu/amdgpu_drv.c
··· 2665 2665 struct drm_device *drm_dev = dev_get_drvdata(dev); 2666 2666 2667 2667 /* do not resume device if it's normal hibernation */ 2668 - if (!pm_hibernate_is_recovering()) 2668 + if (!pm_hibernate_is_recovering() && !pm_hibernation_mode_is_suspend()) 2669 2669 return 0; 2670 2670 2671 2671 return amdgpu_device_resume(drm_dev, true);
+6
include/linux/suspend.h
··· 418 418 } 419 419 #endif /* CONFIG_HIBERNATION */ 420 420 421 + #if defined(CONFIG_HIBERNATION) && defined(CONFIG_SUSPEND) 422 + bool pm_hibernation_mode_is_suspend(void); 423 + #else 424 + static inline bool pm_hibernation_mode_is_suspend(void) { return false; } 425 + #endif 426 + 421 427 int arch_resume_nosmt(void); 422 428 423 429 #ifdef CONFIG_HIBERNATION_SNAPSHOT_DEV
+26 -13
kernel/power/hibernate.c
··· 80 80 81 81 static atomic_t hibernate_atomic = ATOMIC_INIT(1); 82 82 83 + #ifdef CONFIG_SUSPEND 84 + /** 85 + * pm_hibernation_mode_is_suspend - Check if hibernation has been set to suspend 86 + */ 87 + bool pm_hibernation_mode_is_suspend(void) 88 + { 89 + return hibernation_mode == HIBERNATION_SUSPEND; 90 + } 91 + EXPORT_SYMBOL_GPL(pm_hibernation_mode_is_suspend); 92 + #endif 93 + 83 94 bool hibernate_acquire(void) 84 95 { 85 96 return atomic_add_unless(&hibernate_atomic, -1, 0); ··· 706 695 707 696 #ifdef CONFIG_SUSPEND 708 697 if (hibernation_mode == HIBERNATION_SUSPEND) { 698 + pm_restore_gfp_mask(); 709 699 error = suspend_devices_and_enter(mem_sleep_current); 710 - if (error) { 711 - hibernation_mode = hibernation_ops ? 712 - HIBERNATION_PLATFORM : 713 - HIBERNATION_SHUTDOWN; 714 - } else { 715 - /* Restore swap signature. */ 716 - error = swsusp_unmark(); 717 - if (error) 718 - pr_err("Swap will be unusable! Try swapon -a.\n"); 700 + if (!error) 701 + goto exit; 719 702 720 - return; 721 - } 703 + hibernation_mode = hibernation_ops ? HIBERNATION_PLATFORM : 704 + HIBERNATION_SHUTDOWN; 722 705 } 723 706 #endif 724 707 ··· 723 718 case HIBERNATION_PLATFORM: 724 719 error = hibernation_platform_enter(); 725 720 if (error == -EAGAIN || error == -EBUSY) { 726 - swsusp_unmark(); 727 721 events_check_enabled = false; 728 722 pr_info("Wakeup event detected during hibernation, rolling back.\n"); 729 - return; 723 + goto exit; 730 724 } 731 725 fallthrough; 732 726 case HIBERNATION_SHUTDOWN: ··· 744 740 pr_crit("Power down manually\n"); 745 741 while (1) 746 742 cpu_relax(); 743 + 744 + exit: 745 + /* Match the pm_restore_gfp_mask() call in hibernate(). */ 746 + pm_restrict_gfp_mask(); 747 + 748 + /* Restore swap signature. */ 749 + error = swsusp_unmark(); 750 + if (error) 751 + pr_err("Swap will be unusable! Try swapon -a.\n"); 747 752 } 748 753 749 754 static int load_image_and_restore(void)
-1
kernel/power/process.c
··· 132 132 if (!pm_freezing) 133 133 static_branch_inc(&freezer_active); 134 134 135 - pm_wakeup_clear(0); 136 135 pm_freezing = true; 137 136 error = try_to_freeze_tasks(true); 138 137 if (!error)
+1 -1
kernel/power/snapshot.c
··· 363 363 * 364 364 * One radix tree is represented by one struct mem_zone_bm_rtree. There are 365 365 * two linked lists for the nodes of the tree, one for the inner nodes and 366 - * one for the leave nodes. The linked leave nodes are used for fast linear 366 + * one for the leaf nodes. The linked leaf nodes are used for fast linear 367 367 * access of the memory bitmap. 368 368 * 369 369 * The struct rtree_node represents one node of the radix tree.
+1
kernel/power/suspend.c
··· 595 595 } 596 596 597 597 pm_pr_dbg("Preparing system for sleep (%s)\n", mem_sleep_labels[state]); 598 + pm_wakeup_clear(0); 598 599 pm_suspend_clear_flags(); 599 600 error = suspend_prepare(state); 600 601 if (error)
+3 -3
kernel/power/swap.c
··· 712 712 goto out_clean; 713 713 } 714 714 715 - data = vzalloc(array_size(nr_threads, sizeof(*data))); 715 + data = vcalloc(nr_threads, sizeof(*data)); 716 716 if (!data) { 717 717 pr_err("Failed to allocate %s data\n", hib_comp_algo); 718 718 ret = -ENOMEM; ··· 1225 1225 nr_threads = num_online_cpus() - 1; 1226 1226 nr_threads = clamp_val(nr_threads, 1, CMP_THREADS); 1227 1227 1228 - page = vmalloc(array_size(CMP_MAX_RD_PAGES, sizeof(*page))); 1228 + page = vmalloc_array(CMP_MAX_RD_PAGES, sizeof(*page)); 1229 1229 if (!page) { 1230 1230 pr_err("Failed to allocate %s page\n", hib_comp_algo); 1231 1231 ret = -ENOMEM; 1232 1232 goto out_clean; 1233 1233 } 1234 1234 1235 - data = vzalloc(array_size(nr_threads, sizeof(*data))); 1235 + data = vcalloc(nr_threads, sizeof(*data)); 1236 1236 if (!data) { 1237 1237 pr_err("Failed to allocate %s data\n", hib_comp_algo); 1238 1238 ret = -ENOMEM;