aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorRafael J. Wysocki <rafael.j.wysocki@intel.com>2017-11-16 16:51:22 -0500
committerRafael J. Wysocki <rafael.j.wysocki@intel.com>2017-11-16 16:51:22 -0500
commitf8817f61e8215b0ff1b73a0d33fa04ef9e6bce8b (patch)
tree6c90b8f2ee96d1a384f96f437e05d4d937a7fdae
parentbd2cd7d5a8f83ddc761025f42a3ca8e56351a6cc (diff)
PM / runtime: Drop children check from __pm_runtime_set_status()
The check for "active" children in __pm_runtime_set_status(), when trying to set the parent device status to "suspended", doesn't really make sense, because in fact it is not invalid to set the status of a device with runtime PM disabled to "suspended" in any case. It is invalid to enable runtime PM for a device with its status set to "suspended" while its child_count reference counter is nonzero, but the check in __pm_runtime_set_status() doesn't really cover that situation. For this reason, drop the children check from __pm_runtime_set_status() and add a check against child_count reference counters of "suspended" devices to pm_runtime_enable(). Fixes: a8636c89648a (PM / Runtime: Don't allow to suspend a device with an active child) Signed-off-by: Rafael J. Wysocki <rafael.j.wysocki@intel.com> Reviewed-by: Ulf Hansson <ulf.hansson@linaro.org> Reviewed-by: Johan Hovold <johan@kernel.org>
-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);