aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--Documentation/power/runtime_pm.txt3
-rw-r--r--drivers/base/power/runtime.c31
2 files changed, 12 insertions, 22 deletions
diff --git a/Documentation/power/runtime_pm.txt b/Documentation/power/runtime_pm.txt
index 57af2f7963ee..937e33c46211 100644
--- a/Documentation/power/runtime_pm.txt
+++ b/Documentation/power/runtime_pm.txt
@@ -435,8 +435,7 @@ drivers/base/power/runtime.c and include/linux/pm_runtime.h:
435 PM status to 'suspended' and update its parent's counter of 'active' 435 PM status to 'suspended' and update its parent's counter of 'active'
436 children as appropriate (it is only valid to use this function if 436 children as appropriate (it is only valid to use this function if
437 'power.runtime_error' is set or 'power.disable_depth' is greater than 437 'power.runtime_error' is set or 'power.disable_depth' is greater than
438 zero); it will fail and return an error code if the device has a child 438 zero)
439 which is active and the 'power.ignore_children' flag is unset
440 439
441 bool pm_runtime_active(struct device *dev); 440 bool pm_runtime_active(struct device *dev);
442 - return true if the device's runtime PM status is 'active' or its 441 - return true if the device's runtime PM status is 'active' or its
diff --git a/drivers/base/power/runtime.c b/drivers/base/power/runtime.c
index 2362b9e9701e..027d159ac381 100644
--- a/drivers/base/power/runtime.c
+++ b/drivers/base/power/runtime.c
@@ -1101,29 +1101,13 @@ int __pm_runtime_set_status(struct device *dev, unsigned int status)
1101 goto out; 1101 goto out;
1102 } 1102 }
1103 1103
1104 if (dev->power.runtime_status == status) 1104 if (dev->power.runtime_status == status || !parent)
1105 goto out_set; 1105 goto out_set;
1106 1106
1107 if (status == RPM_SUSPENDED) { 1107 if (status == RPM_SUSPENDED) {
1108 /* 1108 atomic_add_unless(&parent->power.child_count, -1, 0);
1109 * It is invalid to suspend a device with an active child, 1109 notify_parent = !parent->power.ignore_children;
1110 * unless it has been set to ignore its children. 1110 } else {
1111 */
1112 if (!dev->power.ignore_children &&
1113 atomic_read(&dev->power.child_count)) {
1114 dev_err(dev, "runtime PM trying to suspend device but active child\n");
1115 error = -EBUSY;
1116 goto out;
1117 }
1118
1119 if (parent) {
1120 atomic_add_unless(&parent->power.child_count, -1, 0);
1121 notify_parent = !parent->power.ignore_children;
1122 }
1123 goto out_set;
1124 }
1125
1126 if (parent) {
1127 spin_lock_nested(&parent->power.lock, SINGLE_DEPTH_NESTING); 1111 spin_lock_nested(&parent->power.lock, SINGLE_DEPTH_NESTING);
1128 1112
1129 /* 1113 /*
@@ -1307,6 +1291,13 @@ void pm_runtime_enable(struct device *dev)
1307 else 1291 else
1308 dev_warn(dev, "Unbalanced %s!\n", __func__); 1292 dev_warn(dev, "Unbalanced %s!\n", __func__);
1309 1293
1294 WARN(!dev->power.disable_depth &&
1295 dev->power.runtime_status == RPM_SUSPENDED &&
1296 !dev->power.ignore_children &&
1297 atomic_read(&dev->power.child_count) > 0,
1298 "Enabling runtime PM for inactive device (%s) with active children\n",
1299 dev_name(dev));
1300
1310 spin_unlock_irqrestore(&dev->power.lock, flags); 1301 spin_unlock_irqrestore(&dev->power.lock, flags);
1311} 1302}
1312EXPORT_SYMBOL_GPL(pm_runtime_enable); 1303EXPORT_SYMBOL_GPL(pm_runtime_enable);