Skip to content

Commit 88d2613

Browse files
AlanSternrjwysocki
authored andcommitted
PM: Prevent runtime suspend during system resume
This patch (as1591) moves the pm_runtime_get_noresume() and pm_runtime_put_sync() calls from __device_suspend() and device_resume() to device_prepare() and device_complete() in the PM core. The reason for doing this is to make sure that parent devices remain at full power (i.e., don't go into runtime suspend) while their children are being resumed from a system sleep. The PCI core already contained equivalent code to serve the same purpose. The patch removes the duplicated code, since it is no longer needed. One of the comments from the PCI core gets moved into the PM core, and a second comment is added to explain whe the _get_noresume and _put_sync calls are present. Signed-off-by: Alan Stern <[email protected]> Signed-off-by: Rafael J. Wysocki <[email protected]>
1 parent 997a031 commit 88d2613

File tree

2 files changed

+18
-28
lines changed

2 files changed

+18
-28
lines changed

drivers/base/power/main.c

Lines changed: 18 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -565,7 +565,6 @@ static int device_resume(struct device *dev, pm_message_t state, bool async)
565565
pm_callback_t callback = NULL;
566566
char *info = NULL;
567567
int error = 0;
568-
bool put = false;
569568

570569
TRACE_DEVICE(dev);
571570
TRACE_RESUME(0);
@@ -583,7 +582,6 @@ static int device_resume(struct device *dev, pm_message_t state, bool async)
583582
goto Unlock;
584583

585584
pm_runtime_enable(dev);
586-
put = true;
587585

588586
if (dev->pm_domain) {
589587
info = "power domain ";
@@ -636,9 +634,6 @@ static int device_resume(struct device *dev, pm_message_t state, bool async)
636634

637635
TRACE_RESUME(error);
638636

639-
if (put)
640-
pm_runtime_put_sync(dev);
641-
642637
return error;
643638
}
644639

@@ -749,6 +744,8 @@ static void device_complete(struct device *dev, pm_message_t state)
749744
}
750745

751746
device_unlock(dev);
747+
748+
pm_runtime_put_sync(dev);
752749
}
753750

754751
/**
@@ -1043,12 +1040,16 @@ static int __device_suspend(struct device *dev, pm_message_t state, bool async)
10431040
if (async_error)
10441041
goto Complete;
10451042

1046-
pm_runtime_get_noresume(dev);
1043+
/*
1044+
* If a device configured to wake up the system from sleep states
1045+
* has been suspended at run time and there's a resume request pending
1046+
* for it, this is equivalent to the device signaling wakeup, so the
1047+
* system suspend operation should be aborted.
1048+
*/
10471049
if (pm_runtime_barrier(dev) && device_may_wakeup(dev))
10481050
pm_wakeup_event(dev, 0);
10491051

10501052
if (pm_wakeup_pending()) {
1051-
pm_runtime_put_sync(dev);
10521053
async_error = -EBUSY;
10531054
goto Complete;
10541055
}
@@ -1111,12 +1112,10 @@ static int __device_suspend(struct device *dev, pm_message_t state, bool async)
11111112
Complete:
11121113
complete_all(&dev->power.completion);
11131114

1114-
if (error) {
1115-
pm_runtime_put_sync(dev);
1115+
if (error)
11161116
async_error = error;
1117-
} else if (dev->power.is_suspended) {
1117+
else if (dev->power.is_suspended)
11181118
__pm_runtime_disable(dev, false);
1119-
}
11201119

11211120
return error;
11221121
}
@@ -1209,6 +1208,14 @@ static int device_prepare(struct device *dev, pm_message_t state)
12091208
char *info = NULL;
12101209
int error = 0;
12111210

1211+
/*
1212+
* If a device's parent goes into runtime suspend at the wrong time,
1213+
* it won't be possible to resume the device. To prevent this we
1214+
* block runtime suspend here, during the prepare phase, and allow
1215+
* it again during the complete phase.
1216+
*/
1217+
pm_runtime_get_noresume(dev);
1218+
12121219
device_lock(dev);
12131220

12141221
dev->power.wakeup_path = device_may_wakeup(dev);

drivers/pci/pci-driver.c

Lines changed: 0 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -623,21 +623,6 @@ static int pci_pm_prepare(struct device *dev)
623623
struct device_driver *drv = dev->driver;
624624
int error = 0;
625625

626-
/*
627-
* If a PCI device configured to wake up the system from sleep states
628-
* has been suspended at run time and there's a resume request pending
629-
* for it, this is equivalent to the device signaling wakeup, so the
630-
* system suspend operation should be aborted.
631-
*/
632-
pm_runtime_get_noresume(dev);
633-
if (pm_runtime_barrier(dev) && device_may_wakeup(dev))
634-
pm_wakeup_event(dev, 0);
635-
636-
if (pm_wakeup_pending()) {
637-
pm_runtime_put_sync(dev);
638-
return -EBUSY;
639-
}
640-
641626
/*
642627
* PCI devices suspended at run time need to be resumed at this
643628
* point, because in general it is necessary to reconfigure them for
@@ -661,8 +646,6 @@ static void pci_pm_complete(struct device *dev)
661646

662647
if (drv && drv->pm && drv->pm->complete)
663648
drv->pm->complete(dev);
664-
665-
pm_runtime_put_sync(dev);
666649
}
667650

668651
#else /* !CONFIG_PM_SLEEP */

0 commit comments

Comments
 (0)