···788788789789During system-wide resume from a sleep state it's easiest to put devices into790790the full-power state, as explained in :file:`Documentation/power/runtime_pm.txt`.791791-Refer to that document for more information regarding this particular issue as791791+[Refer to that document for more information regarding this particular issue as792792well as for information on the device runtime power management framework in793793-general.793793+general.]794794+795795+However, it often is desirable to leave devices in suspend after system796796+transitions to the working state, especially if those devices had been in797797+runtime suspend before the preceding system-wide suspend (or analogous)798798+transition. Device drivers can use the ``DPM_FLAG_LEAVE_SUSPENDED`` flag to799799+indicate to the PM core (and middle-layer code) that they prefer the specific800800+devices handled by them to be left suspended and they have no problems with801801+skipping their system-wide resume callbacks for this reason. Whether or not the802802+devices will actually be left in suspend may depend on their state before the803803+given system suspend-resume cycle and on the type of the system transition under804804+way. In particular, devices are not left suspended if that transition is a805805+restore from hibernation, as device states are not guaranteed to be reflected806806+by the information stored in the hibernation image in that case.807807+808808+The middle-layer code involved in the handling of the device is expected to809809+indicate to the PM core if the device may be left in suspend by setting its810810+:c:member:`power.may_skip_resume` status bit which is checked by the PM core811811+during the "noirq" phase of the preceding system-wide suspend (or analogous)812812+transition. The middle layer is then responsible for handling the device as813813+appropriate in its "noirq" resume callback, which is executed regardless of814814+whether or not the device is left suspended, but the other resume callbacks815815+(except for ``->complete``) will be skipped automatically by the PM core if the816816+device really can be left in suspend.
+11
Documentation/power/pci.txt
···994994the function will set the power.direct_complete flag for it (to make the PM core995995skip the subsequent "thaw" callbacks for it) and return.996996997997+Setting the DPM_FLAG_LEAVE_SUSPENDED flag means that the driver prefers the998998+device to be left in suspend after system-wide transitions to the working state.999999+This flag is checked by the PM core, but the PCI bus type informs the PM core10001000+which devices may be left in suspend from its perspective (that happens during10011001+the "noirq" phase of system-wide suspend and analogous transitions) and next it10021002+uses the dev_pm_may_skip_resume() helper to decide whether or not to return from10031003+pci_pm_resume_noirq() early, as the PM core will skip the remaining resume10041004+callbacks for the device during the transition under way and will set its10051005+runtime PM status to "suspended" if dev_pm_may_skip_resume() returns "true" for10061006+it.10071007+99710083.2. Device Runtime Power Management9981009------------------------------------9991010In addition to providing device power management callbacks PCI device drivers
+25-4
drivers/acpi/device_pm.c
···990990 * the sleep state it is going out of and it has never been resumed till991991 * now, resume it in case the firmware powered it up.992992 */993993- if (dev->power.direct_complete && pm_resume_via_firmware())993993+ if (pm_runtime_suspended(dev) && pm_resume_via_firmware())994994 pm_request_resume(dev);995995}996996EXPORT_SYMBOL_GPL(acpi_subsys_complete);···10391039 */10401040int acpi_subsys_suspend_noirq(struct device *dev)10411041{10421042- if (dev_pm_smart_suspend_and_suspended(dev))10431043- return 0;10421042+ int ret;1044104310451045- return pm_generic_suspend_noirq(dev);10441044+ if (dev_pm_smart_suspend_and_suspended(dev)) {10451045+ dev->power.may_skip_resume = true;10461046+ return 0;10471047+ }10481048+10491049+ ret = pm_generic_suspend_noirq(dev);10501050+ if (ret)10511051+ return ret;10521052+10531053+ /*10541054+ * If the target system sleep state is suspend-to-idle, it is sufficient10551055+ * to check whether or not the device's wakeup settings are good for10561056+ * runtime PM. Otherwise, the pm_resume_via_firmware() check will cause10571057+ * acpi_subsys_complete() to take care of fixing up the device's state10581058+ * anyway, if need be.10591059+ */10601060+ dev->power.may_skip_resume = device_may_wakeup(dev) ||10611061+ !device_can_wakeup(dev);10621062+10631063+ return 0;10461064}10471065EXPORT_SYMBOL_GPL(acpi_subsys_suspend_noirq);10481066···10701052 */10711053int acpi_subsys_resume_noirq(struct device *dev)10721054{10551055+ if (dev_pm_may_skip_resume(dev))10561056+ return 0;10571057+10731058 /*10741059 * Devices with DPM_FLAG_SMART_SUSPEND may be left in runtime suspend10751060 * during system suspend, so update their runtime PM status to "active"
+85-17
drivers/base/power/main.c
···526526/*------------------------- Resume routines -------------------------*/527527528528/**529529+ * dev_pm_may_skip_resume - System-wide device resume optimization check.530530+ * @dev: Target device.531531+ *532532+ * Checks whether or not the device may be left in suspend after a system-wide533533+ * transition to the working state.534534+ */535535+bool dev_pm_may_skip_resume(struct device *dev)536536+{537537+ return !dev->power.must_resume && pm_transition.event != PM_EVENT_RESTORE;538538+}539539+540540+/**529541 * device_resume_noirq - Execute a "noirq resume" callback for given device.530542 * @dev: Device to handle.531543 * @state: PM transition of the system being carried out.···584572585573 error = dpm_run_callback(callback, dev, state, info);586574 dev->power.is_noirq_suspended = false;575575+576576+ if (dev_pm_may_skip_resume(dev)) {577577+ /*578578+ * The device is going to be left in suspend, but it might not579579+ * have been in runtime suspend before the system suspended, so580580+ * its runtime PM status needs to be updated to avoid confusing581581+ * the runtime PM framework when runtime PM is enabled for the582582+ * device again.583583+ */584584+ pm_runtime_set_suspended(dev);585585+ dev->power.is_late_suspended = false;586586+ dev->power.is_suspended = false;587587+ }587588588589 Out:589590 complete_all(&dev->power.completion);···10991074 return PMSG_ON;11001075}1101107610771077+static void dpm_superior_set_must_resume(struct device *dev)10781078+{10791079+ struct device_link *link;10801080+ int idx;10811081+10821082+ if (dev->parent)10831083+ dev->parent->power.must_resume = true;10841084+10851085+ idx = device_links_read_lock();10861086+10871087+ list_for_each_entry_rcu(link, &dev->links.suppliers, c_node)10881088+ link->supplier->power.must_resume = true;10891089+10901090+ device_links_read_unlock(idx);10911091+}10921092+11021093/**11031094 * __device_suspend_noirq - Execute a "noirq suspend" callback for given device.11041095 * @dev: Device to handle.···11661125 }1167112611681127 error = dpm_run_callback(callback, dev, state, info);11691169- if (!error)11701170- dev->power.is_noirq_suspended = true;11711171- else11281128+ if (error) {11721129 async_error = error;11301130+ goto Complete;11311131+ }11321132+11331133+ dev->power.is_noirq_suspended = true;11341134+11351135+ if (dev_pm_test_driver_flags(dev, DPM_FLAG_LEAVE_SUSPENDED)) {11361136+ /*11371137+ * The only safe strategy here is to require that if the device11381138+ * may not be left in suspend, resume callbacks must be invoked11391139+ * for it.11401140+ */11411141+ dev->power.must_resume = dev->power.must_resume ||11421142+ !dev->power.may_skip_resume ||11431143+ atomic_read(&dev->power.usage_count) > 1;11441144+ } else {11451145+ dev->power.must_resume = true;11461146+ }11471147+11481148+ if (dev->power.must_resume)11491149+ dpm_superior_set_must_resume(dev);1173115011741151Complete:11751152 complete_all(&dev->power.completion);···14791420 return error;14801421}1481142214231423+static void dpm_propagate_to_parent(struct device *dev)14241424+{14251425+ struct device *parent = dev->parent;14261426+14271427+ if (!parent)14281428+ return;14291429+14301430+ spin_lock_irq(&parent->power.lock);14311431+14321432+ parent->power.direct_complete = false;14331433+ if (dev->power.wakeup_path && !parent->power.ignore_children)14341434+ parent->power.wakeup_path = true;14351435+14361436+ spin_unlock_irq(&parent->power.lock);14371437+}14381438+14821439static void dpm_clear_suppliers_direct_complete(struct device *dev)14831440{14841441 struct device_link *link;···15601485 dev->power.direct_complete = false;15611486 }1562148714881488+ dev->power.may_skip_resume = false;14891489+ dev->power.must_resume = false;14901490+15631491 dpm_watchdog_set(&wd, dev);15641492 device_lock(dev);15651493···1606152816071529 End:16081530 if (!error) {16091609- struct device *parent = dev->parent;16101610-16111531 dev->power.is_suspended = true;16121612- if (parent) {16131613- spin_lock_irq(&parent->power.lock);16141614-16151615- dev->parent->power.direct_complete = false;16161616- if (dev->power.wakeup_path16171617- && !dev->parent->power.ignore_children)16181618- dev->parent->power.wakeup_path = true;16191619-16201620- spin_unlock_irq(&parent->power.lock);16211621- }15321532+ dpm_propagate_to_parent(dev);16221533 dpm_clear_suppliers_direct_complete(dev);16231534 }16241535···17171650 if (dev->power.syscore)17181651 return 0;1719165217201720- WARN_ON(dev_pm_test_driver_flags(dev, DPM_FLAG_SMART_SUSPEND) &&17211721- !pm_runtime_enabled(dev));16531653+ WARN_ON(!pm_runtime_enabled(dev) &&16541654+ dev_pm_test_driver_flags(dev, DPM_FLAG_SMART_SUSPEND |16551655+ DPM_FLAG_LEAVE_SUSPENDED));1722165617231657 /*17241658 * If a device's parent goes into runtime suspend at the wrong time,
···699699 pm_generic_complete(dev);700700701701 /* Resume device if platform firmware has put it in reset-power-on */702702- if (dev->power.direct_complete && pm_resume_via_firmware()) {702702+ if (pm_runtime_suspended(dev) && pm_resume_via_firmware()) {703703 pci_power_t pre_sleep_state = pci_dev->current_state;704704705705 pci_update_current_state(pci_dev, pci_dev->current_state);···783783 struct pci_dev *pci_dev = to_pci_dev(dev);784784 const struct dev_pm_ops *pm = dev->driver ? dev->driver->pm : NULL;785785786786- if (dev_pm_smart_suspend_and_suspended(dev))786786+ if (dev_pm_smart_suspend_and_suspended(dev)) {787787+ dev->power.may_skip_resume = true;787788 return 0;789789+ }788790789791 if (pci_has_legacy_pm_support(pci_dev))790792 return pci_legacy_suspend_late(dev, PMSG_SUSPEND);···840838Fixup:841839 pci_fixup_device(pci_fixup_suspend_late, pci_dev);842840841841+ /*842842+ * If the target system sleep state is suspend-to-idle, it is sufficient843843+ * to check whether or not the device's wakeup settings are good for844844+ * runtime PM. Otherwise, the pm_resume_via_firmware() check will cause845845+ * pci_pm_complete() to take care of fixing up the device's state846846+ * anyway, if need be.847847+ */848848+ dev->power.may_skip_resume = device_may_wakeup(dev) ||849849+ !device_can_wakeup(dev);850850+843851 return 0;844852}845853···858846 struct pci_dev *pci_dev = to_pci_dev(dev);859847 struct device_driver *drv = dev->driver;860848 int error = 0;849849+850850+ if (dev_pm_may_skip_resume(dev))851851+ return 0;861852862853 /*863854 * Devices with DPM_FLAG_SMART_SUSPEND may be left in runtime suspend
+12-4
include/linux/pm.h
···556556 * These flags can be set by device drivers at the probe time. They need not be557557 * cleared by the drivers as the driver core will take care of that.558558 *559559- * NEVER_SKIP: Do not skip system suspend/resume callbacks for the device.559559+ * NEVER_SKIP: Do not skip all system suspend/resume callbacks for the device.560560 * SMART_PREPARE: Check the return value of the driver's ->prepare callback.561561 * SMART_SUSPEND: No need to resume the device from runtime suspend.562562+ * LEAVE_SUSPENDED: Avoid resuming the device during system resume if possible.562563 *563564 * Setting SMART_PREPARE instructs bus types and PM domains which may want564565 * system suspend/resume callbacks to be skipped for the device to return 0 from···573572 * necessary from the driver's perspective. It also may cause them to skip574573 * invocations of the ->suspend_late and ->suspend_noirq callbacks provided by575574 * the driver if they decide to leave the device in runtime suspend.575575+ *576576+ * Setting LEAVE_SUSPENDED informs the PM core and middle-layer code that the577577+ * driver prefers the device to be left in suspend after system resume.576578 */577577-#define DPM_FLAG_NEVER_SKIP BIT(0)578578-#define DPM_FLAG_SMART_PREPARE BIT(1)579579-#define DPM_FLAG_SMART_SUSPEND BIT(2)579579+#define DPM_FLAG_NEVER_SKIP BIT(0)580580+#define DPM_FLAG_SMART_PREPARE BIT(1)581581+#define DPM_FLAG_SMART_SUSPEND BIT(2)582582+#define DPM_FLAG_LEAVE_SUSPENDED BIT(3)580583581584struct dev_pm_info {582585 pm_message_t power_state;···602597 bool wakeup_path:1;603598 bool syscore:1;604599 bool no_pm_callbacks:1; /* Owned by the PM core */600600+ unsigned int must_resume:1; /* Owned by the PM core */601601+ unsigned int may_skip_resume:1; /* Set by subsystems */605602#else606603 unsigned int should_wakeup:1;607604#endif···772765extern int pm_generic_poweroff(struct device *dev);773766extern void pm_generic_complete(struct device *dev);774767768768+extern bool dev_pm_may_skip_resume(struct device *dev);775769extern bool dev_pm_smart_suspend_and_suspended(struct device *dev);776770777771#else /* !CONFIG_PM_SLEEP */