| From ebb50b76c08f058dfa56ba5a7bb314474a0a7754 Mon Sep 17 00:00:00 2001 |
| From: "Rafael J. Wysocki" <rafael.j.wysocki@intel.com> |
| Date: Thu, 16 Nov 2017 22:51:22 +0100 |
| Subject: [PATCH 0408/1795] 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> |
| (cherry picked from commit f8817f61e8215b0ff1b73a0d33fa04ef9e6bce8b) |
| Signed-off-by: Simon Horman <horms+renesas@verge.net.au> |
| Signed-off-by: Geert Uytterhoeven <geert+renesas@glider.be> |
| --- |
| Documentation/power/runtime_pm.txt | 3 +-- |
| drivers/base/power/runtime.c | 31 +++++++++++------------------- |
| 2 files changed, 12 insertions(+), 22 deletions(-) |
| |
| diff --git a/Documentation/power/runtime_pm.txt b/Documentation/power/runtime_pm.txt |
| index 625549d4c74a..0fde3dcf077a 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: |
| PM status to 'suspended' and update its parent's counter of 'active' |
| children as appropriate (it is only valid to use this function if |
| 'power.runtime_error' is set or 'power.disable_depth' is greater than |
| - zero); it will fail and return an error code if the device has a child |
| - which is active and the 'power.ignore_children' flag is unset |
| + zero) |
| |
| bool pm_runtime_active(struct device *dev); |
| - 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 b2b1eece0db1..3da090e7ed05 100644 |
| --- a/drivers/base/power/runtime.c |
| +++ b/drivers/base/power/runtime.c |
| @@ -1102,29 +1102,13 @@ int __pm_runtime_set_status(struct device *dev, unsigned int status) |
| goto out; |
| } |
| |
| - if (dev->power.runtime_status == status) |
| + if (dev->power.runtime_status == status || !parent) |
| goto out_set; |
| |
| if (status == RPM_SUSPENDED) { |
| - /* |
| - * It is invalid to suspend a device with an active child, |
| - * unless it has been set to ignore its children. |
| - */ |
| - if (!dev->power.ignore_children && |
| - atomic_read(&dev->power.child_count)) { |
| - dev_err(dev, "runtime PM trying to suspend device but active child\n"); |
| - error = -EBUSY; |
| - goto out; |
| - } |
| - |
| - if (parent) { |
| - atomic_add_unless(&parent->power.child_count, -1, 0); |
| - notify_parent = !parent->power.ignore_children; |
| - } |
| - goto out_set; |
| - } |
| - |
| - if (parent) { |
| + atomic_add_unless(&parent->power.child_count, -1, 0); |
| + notify_parent = !parent->power.ignore_children; |
| + } else { |
| spin_lock_nested(&parent->power.lock, SINGLE_DEPTH_NESTING); |
| |
| /* |
| @@ -1308,6 +1292,13 @@ void pm_runtime_enable(struct device *dev) |
| else |
| dev_warn(dev, "Unbalanced %s!\n", __func__); |
| |
| + WARN(!dev->power.disable_depth && |
| + dev->power.runtime_status == RPM_SUSPENDED && |
| + !dev->power.ignore_children && |
| + atomic_read(&dev->power.child_count) > 0, |
| + "Enabling runtime PM for inactive device (%s) with active children\n", |
| + dev_name(dev)); |
| + |
| spin_unlock_irqrestore(&dev->power.lock, flags); |
| } |
| EXPORT_SYMBOL_GPL(pm_runtime_enable); |
| -- |
| 2.19.0 |
| |