summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--drivers/base/dd.c2
-rw-r--r--drivers/base/power/power.h2
-rw-r--r--drivers/base/power/runtime.c26
3 files changed, 24 insertions, 6 deletions
diff --git a/drivers/base/dd.c b/drivers/base/dd.c
index a641cf3ccad6..cd2d79b1bf01 100644
--- a/drivers/base/dd.c
+++ b/drivers/base/dd.c
@@ -340,6 +340,7 @@ probe_failed:
dev_set_drvdata(dev, NULL);
if (dev->pm_domain && dev->pm_domain->dismiss)
dev->pm_domain->dismiss(dev);
+ pm_runtime_reinit(dev);
switch (ret) {
case -EPROBE_DEFER:
@@ -695,6 +696,7 @@ static void __device_release_driver(struct device *dev)
dev_set_drvdata(dev, NULL);
if (dev->pm_domain && dev->pm_domain->dismiss)
dev->pm_domain->dismiss(dev);
+ pm_runtime_reinit(dev);
klist_remove(&dev->p->knode_driver);
if (dev->bus)
diff --git a/drivers/base/power/power.h b/drivers/base/power/power.h
index 998fa6b23084..8b06193d4a5e 100644
--- a/drivers/base/power/power.h
+++ b/drivers/base/power/power.h
@@ -18,6 +18,7 @@ static inline void pm_runtime_early_init(struct device *dev)
}
extern void pm_runtime_init(struct device *dev);
+extern void pm_runtime_reinit(struct device *dev);
extern void pm_runtime_remove(struct device *dev);
struct wake_irq {
@@ -84,6 +85,7 @@ static inline void pm_runtime_early_init(struct device *dev)
}
static inline void pm_runtime_init(struct device *dev) {}
+static inline void pm_runtime_reinit(struct device *dev) {}
static inline void pm_runtime_remove(struct device *dev) {}
static inline int dpm_sysfs_add(struct device *dev) { return 0; }
diff --git a/drivers/base/power/runtime.c b/drivers/base/power/runtime.c
index e1a10a03df8e..ab3fcd9f6c98 100644
--- a/drivers/base/power/runtime.c
+++ b/drivers/base/power/runtime.c
@@ -1390,18 +1390,32 @@ void pm_runtime_init(struct device *dev)
}
/**
+ * pm_runtime_reinit - Re-initialize runtime PM fields in given device object.
+ * @dev: Device object to re-initialize.
+ */
+void pm_runtime_reinit(struct device *dev)
+{
+ if (!pm_runtime_enabled(dev)) {
+ if (dev->power.runtime_status == RPM_ACTIVE)
+ pm_runtime_set_suspended(dev);
+ if (dev->power.irq_safe) {
+ spin_lock_irq(&dev->power.lock);
+ dev->power.irq_safe = 0;
+ spin_unlock_irq(&dev->power.lock);
+ if (dev->parent)
+ pm_runtime_put(dev->parent);
+ }
+ }
+}
+
+/**
* pm_runtime_remove - Prepare for removing a device from device hierarchy.
* @dev: Device object being removed from device hierarchy.
*/
void pm_runtime_remove(struct device *dev)
{
__pm_runtime_disable(dev, false);
-
- /* Change the status back to 'suspended' to match the initial status. */
- if (dev->power.runtime_status == RPM_ACTIVE)
- pm_runtime_set_suspended(dev);
- if (dev->power.irq_safe && dev->parent)
- pm_runtime_put(dev->parent);
+ pm_runtime_reinit(dev);
}
/**