* MEI requires to resume from runtime suspend mode
* in order to perform link reset flow upon system suspend.
*/
- pdev->dev_flags |= PCI_DEV_FLAGS_NEEDS_RESUME;
+ dev_pm_set_driver_flags(&pdev->dev, DPM_FLAG_NEVER_SKIP);
/*
- * For not wake-able HW runtime pm framework
- * can't be used on pci device level.
- * Use domain runtime pm callbacks instead.
- */
- if (!pci_dev_run_wake(pdev))
- mei_me_set_pm_domain(dev);
+ * ME maps runtime suspend/resume to D0i states,
+ * hence we need to go around native PCI runtime service which
+ * eventually brings the device into D3cold/hot state,
+ * but the mei device cannot wake up from D3 unlike from D0i3.
+ * To get around the PCI device native runtime pm,
+ * ME uses runtime pm domain handlers which take precedence
+ * over the driver's pm handlers.
+ */
+ mei_me_set_pm_domain(dev);
if (mei_pg_is_enabled(dev))
pm_runtime_put_noidle(&pdev->dev);
* MEI requires to resume from runtime suspend mode
* in order to perform link reset flow upon system suspend.
*/
- pdev->dev_flags |= PCI_DEV_FLAGS_NEEDS_RESUME;
+ dev_pm_set_driver_flags(&pdev->dev, DPM_FLAG_NEVER_SKIP);
/*
- * For not wake-able HW runtime pm framework
- * can't be used on pci device level.
- * Use domain runtime pm callbacks instead.
- */
- if (!pci_dev_run_wake(pdev))
- mei_txe_set_pm_domain(dev);
+ * TXE maps runtime suspend/resume to own power gating states,
+ * hence we need to go around native PCI runtime service which
+ * eventually brings the device into D3cold/hot state.
+ * But the TXE device cannot wake up from D3 unlike from own
+ * power gating. To get around PCI device native runtime pm,
+ * TXE uses runtime pm domain handlers which take precedence.
+ */
+ mei_txe_set_pm_domain(dev);
pm_runtime_put_noidle(&pdev->dev);
{
struct device_driver *drv = dev->driver;
- /*
- * Devices having power.ignore_children set may still be necessary for
- * suspending their children in the next phase of device suspend.
- */
- if (dev->power.ignore_children)
- pm_runtime_resume(dev);
-
if (drv && drv->pm && drv->pm->prepare) {
int error = drv->pm->prepare(dev);
- if (error)
+ if (error < 0)
return error;
+
+ if (!error && dev_pm_test_driver_flags(dev, DPM_FLAG_SMART_PREPARE))
+ return 0;
}
return pci_dev_keep_suspended(to_pci_dev(dev));
}