|
@@ -902,19 +902,19 @@ static int pm_genpd_prepare(struct device *dev)
|
|
|
}
|
|
|
|
|
|
/**
|
|
|
- * pm_genpd_suspend_noirq - Completion of suspend of device in an I/O PM domain.
|
|
|
+ * genpd_finish_suspend - Completion of suspend or hibernation of device in an
|
|
|
+ * I/O pm domain.
|
|
|
* @dev: Device to suspend.
|
|
|
+ * @poweroff: Specifies if this is a poweroff_noirq or suspend_noirq callback.
|
|
|
*
|
|
|
* Stop the device and remove power from the domain if all devices in it have
|
|
|
* been stopped.
|
|
|
*/
|
|
|
-static int pm_genpd_suspend_noirq(struct device *dev)
|
|
|
+static int genpd_finish_suspend(struct device *dev, bool poweroff)
|
|
|
{
|
|
|
struct generic_pm_domain *genpd;
|
|
|
int ret;
|
|
|
|
|
|
- dev_dbg(dev, "%s()\n", __func__);
|
|
|
-
|
|
|
genpd = dev_to_genpd(dev);
|
|
|
if (IS_ERR(genpd))
|
|
|
return -EINVAL;
|
|
@@ -922,6 +922,13 @@ static int pm_genpd_suspend_noirq(struct device *dev)
|
|
|
if (dev->power.wakeup_path && genpd_dev_active_wakeup(genpd, dev))
|
|
|
return 0;
|
|
|
|
|
|
+ if (poweroff)
|
|
|
+ ret = pm_generic_poweroff_noirq(dev);
|
|
|
+ else
|
|
|
+ ret = pm_generic_suspend_noirq(dev);
|
|
|
+ if (ret)
|
|
|
+ return ret;
|
|
|
+
|
|
|
if (genpd->dev_ops.stop && genpd->dev_ops.start) {
|
|
|
ret = pm_runtime_force_suspend(dev);
|
|
|
if (ret)
|
|
@@ -936,6 +943,20 @@ static int pm_genpd_suspend_noirq(struct device *dev)
|
|
|
return 0;
|
|
|
}
|
|
|
|
|
|
+/**
|
|
|
+ * pm_genpd_suspend_noirq - Completion of suspend of device in an I/O PM domain.
|
|
|
+ * @dev: Device to suspend.
|
|
|
+ *
|
|
|
+ * Stop the device and remove power from the domain if all devices in it have
|
|
|
+ * been stopped.
|
|
|
+ */
|
|
|
+static int pm_genpd_suspend_noirq(struct device *dev)
|
|
|
+{
|
|
|
+ dev_dbg(dev, "%s()\n", __func__);
|
|
|
+
|
|
|
+ return genpd_finish_suspend(dev, false);
|
|
|
+}
|
|
|
+
|
|
|
/**
|
|
|
* pm_genpd_resume_noirq - Start of resume of device in an I/O PM domain.
|
|
|
* @dev: Device to resume.
|
|
@@ -964,6 +985,10 @@ static int pm_genpd_resume_noirq(struct device *dev)
|
|
|
if (genpd->dev_ops.stop && genpd->dev_ops.start)
|
|
|
ret = pm_runtime_force_resume(dev);
|
|
|
|
|
|
+ ret = pm_generic_resume_noirq(dev);
|
|
|
+ if (ret)
|
|
|
+ return ret;
|
|
|
+
|
|
|
return ret;
|
|
|
}
|
|
|
|
|
@@ -987,6 +1012,10 @@ static int pm_genpd_freeze_noirq(struct device *dev)
|
|
|
if (IS_ERR(genpd))
|
|
|
return -EINVAL;
|
|
|
|
|
|
+ ret = pm_generic_freeze_noirq(dev);
|
|
|
+ if (ret)
|
|
|
+ return ret;
|
|
|
+
|
|
|
if (genpd->dev_ops.stop && genpd->dev_ops.start)
|
|
|
ret = pm_runtime_force_suspend(dev);
|
|
|
|
|
@@ -1011,10 +1040,28 @@ static int pm_genpd_thaw_noirq(struct device *dev)
|
|
|
if (IS_ERR(genpd))
|
|
|
return -EINVAL;
|
|
|
|
|
|
- if (genpd->dev_ops.stop && genpd->dev_ops.start)
|
|
|
+ if (genpd->dev_ops.stop && genpd->dev_ops.start) {
|
|
|
ret = pm_runtime_force_resume(dev);
|
|
|
+ if (ret)
|
|
|
+ return ret;
|
|
|
+ }
|
|
|
|
|
|
- return ret;
|
|
|
+ return pm_generic_thaw_noirq(dev);
|
|
|
+}
|
|
|
+
|
|
|
+/**
|
|
|
+ * pm_genpd_poweroff_noirq - Completion of hibernation of device in an
|
|
|
+ * I/O PM domain.
|
|
|
+ * @dev: Device to poweroff.
|
|
|
+ *
|
|
|
+ * Stop the device and remove power from the domain if all devices in it have
|
|
|
+ * been stopped.
|
|
|
+ */
|
|
|
+static int pm_genpd_poweroff_noirq(struct device *dev)
|
|
|
+{
|
|
|
+ dev_dbg(dev, "%s()\n", __func__);
|
|
|
+
|
|
|
+ return genpd_finish_suspend(dev, true);
|
|
|
}
|
|
|
|
|
|
/**
|
|
@@ -1051,10 +1098,13 @@ static int pm_genpd_restore_noirq(struct device *dev)
|
|
|
genpd_sync_power_on(genpd, true, 0);
|
|
|
genpd_unlock(genpd);
|
|
|
|
|
|
- if (genpd->dev_ops.stop && genpd->dev_ops.start)
|
|
|
+ if (genpd->dev_ops.stop && genpd->dev_ops.start) {
|
|
|
ret = pm_runtime_force_resume(dev);
|
|
|
+ if (ret)
|
|
|
+ return ret;
|
|
|
+ }
|
|
|
|
|
|
- return ret;
|
|
|
+ return pm_generic_restore_noirq(dev);
|
|
|
}
|
|
|
|
|
|
/**
|
|
@@ -1496,7 +1546,7 @@ int pm_genpd_init(struct generic_pm_domain *genpd,
|
|
|
genpd->domain.ops.resume_noirq = pm_genpd_resume_noirq;
|
|
|
genpd->domain.ops.freeze_noirq = pm_genpd_freeze_noirq;
|
|
|
genpd->domain.ops.thaw_noirq = pm_genpd_thaw_noirq;
|
|
|
- genpd->domain.ops.poweroff_noirq = pm_genpd_suspend_noirq;
|
|
|
+ genpd->domain.ops.poweroff_noirq = pm_genpd_poweroff_noirq;
|
|
|
genpd->domain.ops.restore_noirq = pm_genpd_restore_noirq;
|
|
|
genpd->domain.ops.complete = pm_genpd_complete;
|
|
|
|