Skip to content

Commit c233403

Browse files
committed
Merge branch 'pm-sleep'
Merge updates related to system suspend and hibernation for 6.20-rc1/7.0-rc1: - Stop flagging the PM runtime workqueue as freezable to avoid system suspend and resume deadlocks in subsystems that assume asynchronous runtime PM to work during system-wide PM transitions (Rafael Wysocki) - Drop redundant NULL pointer checks before acomp_request_free() from the hibernation code handling image saving (Rafael Wysocki) - Update wakeup_sources_walk_start() to handle empty lists of wakeup sources as appropriate (Samuel Wu) - Make dev_pm_clear_wake_irq() check the power.wakeirq value under power.lock to avoid race conditions (Gui-Dong Han) - Avoid bit field races related to power.work_in_progress in the core device suspend code (Xuewen Yan) * pm-sleep: PM: sleep: core: Avoid bit field races related to work_in_progress PM: sleep: wakeirq: harden dev_pm_clear_wake_irq() against races PM: wakeup: Handle empty list in wakeup_sources_walk_start() PM: hibernate: Drop NULL pointer checks before acomp_request_free() PM: sleep: Do not flag runtime PM workqueue as freezable
2 parents 6d36714 + 0491f3f commit c233403

7 files changed

Lines changed: 20 additions & 19 deletions

File tree

Documentation/power/runtime_pm.rst

Lines changed: 3 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -712,10 +712,9 @@ out the following operations:
712712
* During system suspend pm_runtime_get_noresume() is called for every device
713713
right before executing the subsystem-level .prepare() callback for it and
714714
pm_runtime_barrier() is called for every device right before executing the
715-
subsystem-level .suspend() callback for it. In addition to that the PM core
716-
calls __pm_runtime_disable() with 'false' as the second argument for every
717-
device right before executing the subsystem-level .suspend_late() callback
718-
for it.
715+
subsystem-level .suspend() callback for it. In addition to that, the PM
716+
core disables runtime PM for every device right before executing the
717+
subsystem-level .suspend_late() callback for it.
719718

720719
* During system resume pm_runtime_enable() and pm_runtime_put() are called for
721720
every device right after executing the subsystem-level .resume_early()

drivers/base/power/main.c

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1647,10 +1647,11 @@ static void device_suspend_late(struct device *dev, pm_message_t state, bool asy
16471647
goto Complete;
16481648

16491649
/*
1650-
* Disable runtime PM for the device without checking if there is a
1651-
* pending resume request for it.
1650+
* After this point, any runtime PM operations targeting the device
1651+
* will fail until the corresponding pm_runtime_enable() call in
1652+
* device_resume_early().
16521653
*/
1653-
__pm_runtime_disable(dev, false);
1654+
pm_runtime_disable(dev);
16541655

16551656
if (dev->power.syscore)
16561657
goto Skip;

drivers/base/power/wakeirq.c

Lines changed: 6 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -83,13 +83,16 @@ EXPORT_SYMBOL_GPL(dev_pm_set_wake_irq);
8383
*/
8484
void dev_pm_clear_wake_irq(struct device *dev)
8585
{
86-
struct wake_irq *wirq = dev->power.wakeirq;
86+
struct wake_irq *wirq;
8787
unsigned long flags;
8888

89-
if (!wirq)
89+
spin_lock_irqsave(&dev->power.lock, flags);
90+
wirq = dev->power.wakeirq;
91+
if (!wirq) {
92+
spin_unlock_irqrestore(&dev->power.lock, flags);
9093
return;
94+
}
9195

92-
spin_lock_irqsave(&dev->power.lock, flags);
9396
device_wakeup_detach_irq(dev);
9497
dev->power.wakeirq = NULL;
9598
spin_unlock_irqrestore(&dev->power.lock, flags);

drivers/base/power/wakeup.c

Lines changed: 1 addition & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -275,9 +275,7 @@ EXPORT_SYMBOL_GPL(wakeup_sources_read_unlock);
275275
*/
276276
struct wakeup_source *wakeup_sources_walk_start(void)
277277
{
278-
struct list_head *ws_head = &wakeup_sources;
279-
280-
return list_entry_rcu(ws_head->next, struct wakeup_source, entry);
278+
return list_first_or_null_rcu(&wakeup_sources, struct wakeup_source, entry);
281279
}
282280
EXPORT_SYMBOL_GPL(wakeup_sources_walk_start);
283281

include/linux/pm.h

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -681,10 +681,10 @@ struct dev_pm_info {
681681
struct list_head entry;
682682
struct completion completion;
683683
struct wakeup_source *wakeup;
684+
bool work_in_progress; /* Owned by the PM core */
684685
bool wakeup_path:1;
685686
bool syscore:1;
686687
bool no_pm_callbacks:1; /* Owned by the PM core */
687-
bool work_in_progress:1; /* Owned by the PM core */
688688
bool smart_suspend:1; /* Owned by the PM core */
689689
bool must_resume:1; /* Owned by the PM core */
690690
bool may_skip_resume:1; /* Set by subsystems */

kernel/power/main.c

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1125,7 +1125,7 @@ EXPORT_SYMBOL_GPL(pm_wq);
11251125

11261126
static int __init pm_start_workqueues(void)
11271127
{
1128-
pm_wq = alloc_workqueue("pm", WQ_FREEZABLE | WQ_UNBOUND, 0);
1128+
pm_wq = alloc_workqueue("pm", WQ_UNBOUND, 0);
11291129
if (!pm_wq)
11301130
return -ENOMEM;
11311131

kernel/power/swap.c

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -902,8 +902,8 @@ static int save_compressed_image(struct swap_map_handle *handle,
902902
for (thr = 0; thr < nr_threads; thr++) {
903903
if (data[thr].thr)
904904
kthread_stop(data[thr].thr);
905-
if (data[thr].cr)
906-
acomp_request_free(data[thr].cr);
905+
906+
acomp_request_free(data[thr].cr);
907907

908908
if (!IS_ERR_OR_NULL(data[thr].cc))
909909
crypto_free_acomp(data[thr].cc);
@@ -1502,8 +1502,8 @@ static int load_compressed_image(struct swap_map_handle *handle,
15021502
for (thr = 0; thr < nr_threads; thr++) {
15031503
if (data[thr].thr)
15041504
kthread_stop(data[thr].thr);
1505-
if (data[thr].cr)
1506-
acomp_request_free(data[thr].cr);
1505+
1506+
acomp_request_free(data[thr].cr);
15071507

15081508
if (!IS_ERR_OR_NULL(data[thr].cc))
15091509
crypto_free_acomp(data[thr].cc);

0 commit comments

Comments
 (0)