|
@@ -44,6 +44,7 @@ static int (*rpm_get_resume_cb(struct device *dev))(struct device *)
|
|
|
return RPM_GET_CALLBACK(dev, runtime_resume);
|
|
|
}
|
|
|
|
|
|
+#ifdef CONFIG_PM_RUNTIME
|
|
|
static int (*rpm_get_idle_cb(struct device *dev))(struct device *)
|
|
|
{
|
|
|
return RPM_GET_CALLBACK(dev, runtime_idle);
|
|
@@ -1401,3 +1402,86 @@ void pm_runtime_remove(struct device *dev)
|
|
|
if (dev->power.irq_safe && dev->parent)
|
|
|
pm_runtime_put(dev->parent);
|
|
|
}
|
|
|
+#endif
|
|
|
+
|
|
|
+/**
|
|
|
+ * pm_runtime_force_suspend - Force a device into suspend state if needed.
|
|
|
+ * @dev: Device to suspend.
|
|
|
+ *
|
|
|
+ * Disable runtime PM so we safely can check the device's runtime PM status and
|
|
|
+ * if it is active, invoke it's .runtime_suspend callback to bring it into
|
|
|
+ * suspend state. Keep runtime PM disabled to preserve the state unless we
|
|
|
+ * encounter errors.
|
|
|
+ *
|
|
|
+ * Typically this function may be invoked from a system suspend callback to make
|
|
|
+ * sure the device is put into low power state.
|
|
|
+ */
|
|
|
+int pm_runtime_force_suspend(struct device *dev)
|
|
|
+{
|
|
|
+ int (*callback)(struct device *);
|
|
|
+ int ret = 0;
|
|
|
+
|
|
|
+ pm_runtime_disable(dev);
|
|
|
+
|
|
|
+ /*
|
|
|
+ * Note that pm_runtime_status_suspended() returns false while
|
|
|
+ * !CONFIG_PM_RUNTIME, which means the device will be put into low
|
|
|
+ * power state.
|
|
|
+ */
|
|
|
+ if (pm_runtime_status_suspended(dev))
|
|
|
+ return 0;
|
|
|
+
|
|
|
+ callback = rpm_get_suspend_cb(dev);
|
|
|
+
|
|
|
+ if (!callback) {
|
|
|
+ ret = -ENOSYS;
|
|
|
+ goto err;
|
|
|
+ }
|
|
|
+
|
|
|
+ ret = callback(dev);
|
|
|
+ if (ret)
|
|
|
+ goto err;
|
|
|
+
|
|
|
+ pm_runtime_set_suspended(dev);
|
|
|
+ return 0;
|
|
|
+err:
|
|
|
+ pm_runtime_enable(dev);
|
|
|
+ return ret;
|
|
|
+}
|
|
|
+EXPORT_SYMBOL_GPL(pm_runtime_force_suspend);
|
|
|
+
|
|
|
+/**
|
|
|
+ * pm_runtime_force_resume - Force a device into resume state.
|
|
|
+ * @dev: Device to resume.
|
|
|
+ *
|
|
|
+ * Prior invoking this function we expect the user to have brought the device
|
|
|
+ * into low power state by a call to pm_runtime_force_suspend(). Here we reverse
|
|
|
+ * those actions and brings the device into full power. We update the runtime PM
|
|
|
+ * status and re-enables runtime PM.
|
|
|
+ *
|
|
|
+ * Typically this function may be invoked from a system resume callback to make
|
|
|
+ * sure the device is put into full power state.
|
|
|
+ */
|
|
|
+int pm_runtime_force_resume(struct device *dev)
|
|
|
+{
|
|
|
+ int (*callback)(struct device *);
|
|
|
+ int ret = 0;
|
|
|
+
|
|
|
+ callback = rpm_get_resume_cb(dev);
|
|
|
+
|
|
|
+ if (!callback) {
|
|
|
+ ret = -ENOSYS;
|
|
|
+ goto out;
|
|
|
+ }
|
|
|
+
|
|
|
+ ret = callback(dev);
|
|
|
+ if (ret)
|
|
|
+ goto out;
|
|
|
+
|
|
|
+ pm_runtime_set_active(dev);
|
|
|
+ pm_runtime_mark_last_busy(dev);
|
|
|
+out:
|
|
|
+ pm_runtime_enable(dev);
|
|
|
+ return ret;
|
|
|
+}
|
|
|
+EXPORT_SYMBOL_GPL(pm_runtime_force_resume);
|