|
|
@@ -229,17 +229,6 @@ static int genpd_poweron(struct generic_pm_domain *genpd, unsigned int depth)
|
|
|
return ret;
|
|
|
}
|
|
|
|
|
|
-static int genpd_save_dev(struct generic_pm_domain *genpd, struct device *dev)
|
|
|
-{
|
|
|
- return GENPD_DEV_CALLBACK(genpd, int, save_state, dev);
|
|
|
-}
|
|
|
-
|
|
|
-static int genpd_restore_dev(struct generic_pm_domain *genpd,
|
|
|
- struct device *dev)
|
|
|
-{
|
|
|
- return GENPD_DEV_CALLBACK(genpd, int, restore_state, dev);
|
|
|
-}
|
|
|
-
|
|
|
static int genpd_dev_pm_qos_notifier(struct notifier_block *nb,
|
|
|
unsigned long val, void *ptr)
|
|
|
{
|
|
|
@@ -372,17 +361,63 @@ static void genpd_power_off_work_fn(struct work_struct *work)
|
|
|
}
|
|
|
|
|
|
/**
|
|
|
- * pm_genpd_runtime_suspend - Suspend a device belonging to I/O PM domain.
|
|
|
+ * __genpd_runtime_suspend - walk the hierarchy of ->runtime_suspend() callbacks
|
|
|
+ * @dev: Device to handle.
|
|
|
+ */
|
|
|
+static int __genpd_runtime_suspend(struct device *dev)
|
|
|
+{
|
|
|
+ int (*cb)(struct device *__dev);
|
|
|
+
|
|
|
+ if (dev->type && dev->type->pm)
|
|
|
+ cb = dev->type->pm->runtime_suspend;
|
|
|
+ else if (dev->class && dev->class->pm)
|
|
|
+ cb = dev->class->pm->runtime_suspend;
|
|
|
+ else if (dev->bus && dev->bus->pm)
|
|
|
+ cb = dev->bus->pm->runtime_suspend;
|
|
|
+ else
|
|
|
+ cb = NULL;
|
|
|
+
|
|
|
+ if (!cb && dev->driver && dev->driver->pm)
|
|
|
+ cb = dev->driver->pm->runtime_suspend;
|
|
|
+
|
|
|
+ return cb ? cb(dev) : 0;
|
|
|
+}
|
|
|
+
|
|
|
+/**
|
|
|
+ * __genpd_runtime_resume - walk the hierarchy of ->runtime_resume() callbacks
|
|
|
+ * @dev: Device to handle.
|
|
|
+ */
|
|
|
+static int __genpd_runtime_resume(struct device *dev)
|
|
|
+{
|
|
|
+ int (*cb)(struct device *__dev);
|
|
|
+
|
|
|
+ if (dev->type && dev->type->pm)
|
|
|
+ cb = dev->type->pm->runtime_resume;
|
|
|
+ else if (dev->class && dev->class->pm)
|
|
|
+ cb = dev->class->pm->runtime_resume;
|
|
|
+ else if (dev->bus && dev->bus->pm)
|
|
|
+ cb = dev->bus->pm->runtime_resume;
|
|
|
+ else
|
|
|
+ cb = NULL;
|
|
|
+
|
|
|
+ if (!cb && dev->driver && dev->driver->pm)
|
|
|
+ cb = dev->driver->pm->runtime_resume;
|
|
|
+
|
|
|
+ return cb ? cb(dev) : 0;
|
|
|
+}
|
|
|
+
|
|
|
+/**
|
|
|
+ * genpd_runtime_suspend - Suspend a device belonging to I/O PM domain.
|
|
|
* @dev: Device to suspend.
|
|
|
*
|
|
|
* Carry out a runtime suspend of a device under the assumption that its
|
|
|
* pm_domain field points to the domain member of an object of type
|
|
|
* struct generic_pm_domain representing a PM domain consisting of I/O devices.
|
|
|
*/
|
|
|
-static int pm_genpd_runtime_suspend(struct device *dev)
|
|
|
+static int genpd_runtime_suspend(struct device *dev)
|
|
|
{
|
|
|
struct generic_pm_domain *genpd;
|
|
|
- bool (*stop_ok)(struct device *__dev);
|
|
|
+ bool (*suspend_ok)(struct device *__dev);
|
|
|
struct gpd_timing_data *td = &dev_gpd_data(dev)->td;
|
|
|
bool runtime_pm = pm_runtime_enabled(dev);
|
|
|
ktime_t time_start;
|
|
|
@@ -401,21 +436,21 @@ static int pm_genpd_runtime_suspend(struct device *dev)
|
|
|
* runtime PM is disabled. Under these circumstances, we shall skip
|
|
|
* validating/measuring the PM QoS latency.
|
|
|
*/
|
|
|
- stop_ok = genpd->gov ? genpd->gov->stop_ok : NULL;
|
|
|
- if (runtime_pm && stop_ok && !stop_ok(dev))
|
|
|
+ suspend_ok = genpd->gov ? genpd->gov->suspend_ok : NULL;
|
|
|
+ if (runtime_pm && suspend_ok && !suspend_ok(dev))
|
|
|
return -EBUSY;
|
|
|
|
|
|
/* Measure suspend latency. */
|
|
|
if (runtime_pm)
|
|
|
time_start = ktime_get();
|
|
|
|
|
|
- ret = genpd_save_dev(genpd, dev);
|
|
|
+ ret = __genpd_runtime_suspend(dev);
|
|
|
if (ret)
|
|
|
return ret;
|
|
|
|
|
|
ret = genpd_stop_dev(genpd, dev);
|
|
|
if (ret) {
|
|
|
- genpd_restore_dev(genpd, dev);
|
|
|
+ __genpd_runtime_resume(dev);
|
|
|
return ret;
|
|
|
}
|
|
|
|
|
|
@@ -446,14 +481,14 @@ static int pm_genpd_runtime_suspend(struct device *dev)
|
|
|
}
|
|
|
|
|
|
/**
|
|
|
- * pm_genpd_runtime_resume - Resume a device belonging to I/O PM domain.
|
|
|
+ * genpd_runtime_resume - Resume a device belonging to I/O PM domain.
|
|
|
* @dev: Device to resume.
|
|
|
*
|
|
|
* Carry out a runtime resume of a device under the assumption that its
|
|
|
* pm_domain field points to the domain member of an object of type
|
|
|
* struct generic_pm_domain representing a PM domain consisting of I/O devices.
|
|
|
*/
|
|
|
-static int pm_genpd_runtime_resume(struct device *dev)
|
|
|
+static int genpd_runtime_resume(struct device *dev)
|
|
|
{
|
|
|
struct generic_pm_domain *genpd;
|
|
|
struct gpd_timing_data *td = &dev_gpd_data(dev)->td;
|
|
|
@@ -491,7 +526,7 @@ static int pm_genpd_runtime_resume(struct device *dev)
|
|
|
if (ret)
|
|
|
goto err_poweroff;
|
|
|
|
|
|
- ret = genpd_restore_dev(genpd, dev);
|
|
|
+ ret = __genpd_runtime_resume(dev);
|
|
|
if (ret)
|
|
|
goto err_stop;
|
|
|
|
|
|
@@ -695,15 +730,6 @@ static int pm_genpd_prepare(struct device *dev)
|
|
|
* at this point and a system wakeup event should be reported if it's
|
|
|
* set up to wake up the system from sleep states.
|
|
|
*/
|
|
|
- pm_runtime_get_noresume(dev);
|
|
|
- if (pm_runtime_barrier(dev) && device_may_wakeup(dev))
|
|
|
- pm_wakeup_event(dev, 0);
|
|
|
-
|
|
|
- if (pm_wakeup_pending()) {
|
|
|
- pm_runtime_put(dev);
|
|
|
- return -EBUSY;
|
|
|
- }
|
|
|
-
|
|
|
if (resume_needed(dev, genpd))
|
|
|
pm_runtime_resume(dev);
|
|
|
|
|
|
@@ -716,10 +742,8 @@ static int pm_genpd_prepare(struct device *dev)
|
|
|
|
|
|
mutex_unlock(&genpd->lock);
|
|
|
|
|
|
- if (genpd->suspend_power_off) {
|
|
|
- pm_runtime_put_noidle(dev);
|
|
|
+ if (genpd->suspend_power_off)
|
|
|
return 0;
|
|
|
- }
|
|
|
|
|
|
/*
|
|
|
* The PM domain must be in the GPD_STATE_ACTIVE state at this point,
|
|
|
@@ -741,7 +765,6 @@ static int pm_genpd_prepare(struct device *dev)
|
|
|
pm_runtime_enable(dev);
|
|
|
}
|
|
|
|
|
|
- pm_runtime_put(dev);
|
|
|
return ret;
|
|
|
}
|
|
|
|
|
|
@@ -1427,54 +1450,6 @@ out:
|
|
|
}
|
|
|
EXPORT_SYMBOL_GPL(pm_genpd_remove_subdomain);
|
|
|
|
|
|
-/* Default device callbacks for generic PM domains. */
|
|
|
-
|
|
|
-/**
|
|
|
- * pm_genpd_default_save_state - Default "save device state" for PM domains.
|
|
|
- * @dev: Device to handle.
|
|
|
- */
|
|
|
-static int pm_genpd_default_save_state(struct device *dev)
|
|
|
-{
|
|
|
- int (*cb)(struct device *__dev);
|
|
|
-
|
|
|
- if (dev->type && dev->type->pm)
|
|
|
- cb = dev->type->pm->runtime_suspend;
|
|
|
- else if (dev->class && dev->class->pm)
|
|
|
- cb = dev->class->pm->runtime_suspend;
|
|
|
- else if (dev->bus && dev->bus->pm)
|
|
|
- cb = dev->bus->pm->runtime_suspend;
|
|
|
- else
|
|
|
- cb = NULL;
|
|
|
-
|
|
|
- if (!cb && dev->driver && dev->driver->pm)
|
|
|
- cb = dev->driver->pm->runtime_suspend;
|
|
|
-
|
|
|
- return cb ? cb(dev) : 0;
|
|
|
-}
|
|
|
-
|
|
|
-/**
|
|
|
- * pm_genpd_default_restore_state - Default PM domains "restore device state".
|
|
|
- * @dev: Device to handle.
|
|
|
- */
|
|
|
-static int pm_genpd_default_restore_state(struct device *dev)
|
|
|
-{
|
|
|
- int (*cb)(struct device *__dev);
|
|
|
-
|
|
|
- if (dev->type && dev->type->pm)
|
|
|
- cb = dev->type->pm->runtime_resume;
|
|
|
- else if (dev->class && dev->class->pm)
|
|
|
- cb = dev->class->pm->runtime_resume;
|
|
|
- else if (dev->bus && dev->bus->pm)
|
|
|
- cb = dev->bus->pm->runtime_resume;
|
|
|
- else
|
|
|
- cb = NULL;
|
|
|
-
|
|
|
- if (!cb && dev->driver && dev->driver->pm)
|
|
|
- cb = dev->driver->pm->runtime_resume;
|
|
|
-
|
|
|
- return cb ? cb(dev) : 0;
|
|
|
-}
|
|
|
-
|
|
|
/**
|
|
|
* pm_genpd_init - Initialize a generic I/O PM domain object.
|
|
|
* @genpd: PM domain object to initialize.
|
|
|
@@ -1498,8 +1473,8 @@ void pm_genpd_init(struct generic_pm_domain *genpd,
|
|
|
genpd->device_count = 0;
|
|
|
genpd->max_off_time_ns = -1;
|
|
|
genpd->max_off_time_changed = true;
|
|
|
- genpd->domain.ops.runtime_suspend = pm_genpd_runtime_suspend;
|
|
|
- genpd->domain.ops.runtime_resume = pm_genpd_runtime_resume;
|
|
|
+ genpd->domain.ops.runtime_suspend = genpd_runtime_suspend;
|
|
|
+ genpd->domain.ops.runtime_resume = genpd_runtime_resume;
|
|
|
genpd->domain.ops.prepare = pm_genpd_prepare;
|
|
|
genpd->domain.ops.suspend = pm_genpd_suspend;
|
|
|
genpd->domain.ops.suspend_late = pm_genpd_suspend_late;
|
|
|
@@ -1520,8 +1495,6 @@ void pm_genpd_init(struct generic_pm_domain *genpd,
|
|
|
genpd->domain.ops.restore_early = pm_genpd_resume_early;
|
|
|
genpd->domain.ops.restore = pm_genpd_resume;
|
|
|
genpd->domain.ops.complete = pm_genpd_complete;
|
|
|
- genpd->dev_ops.save_state = pm_genpd_default_save_state;
|
|
|
- genpd->dev_ops.restore_state = pm_genpd_default_restore_state;
|
|
|
|
|
|
if (genpd->flags & GENPD_FLAG_PM_CLK) {
|
|
|
genpd->dev_ops.stop = pm_clk_suspend;
|