Commit 6d47254c authored by Linus Torvalds's avatar Linus Torvalds

Merge tag 'pm-5.12-rc2' of git://git.kernel.org/pub/scm/linux/kernel/git/rafael/linux-pm

Pull power management fixes from Rafael Wysocki:
 "These fix the usage of device links in the runtime PM core code and
  update the DTPM (Dynamic Thermal Power Management) feature added
  recently.

  Specifics:

   - Make the runtime PM core code avoid attempting to suspend supplier
     devices before updating the PM-runtime status of a consumer to
     'suspended' (Rafael Wysocki).

   - Fix DTPM (Dynamic Thermal Power Management) root node
     initialization and label that feature as EXPERIMENTAL in Kconfig
     (Daniel Lezcano)"

* tag 'pm-5.12-rc2' of git://git.kernel.org/pub/scm/linux/kernel/git/rafael/linux-pm:
  powercap/drivers/dtpm: Add the experimental label to the option description
  powercap/drivers/dtpm: Fix root node initialization
  PM: runtime: Update device status before letting suppliers suspend
parents ea6be461 7bff4c26
...@@ -325,22 +325,22 @@ static void rpm_put_suppliers(struct device *dev) ...@@ -325,22 +325,22 @@ static void rpm_put_suppliers(struct device *dev)
static int __rpm_callback(int (*cb)(struct device *), struct device *dev) static int __rpm_callback(int (*cb)(struct device *), struct device *dev)
__releases(&dev->power.lock) __acquires(&dev->power.lock) __releases(&dev->power.lock) __acquires(&dev->power.lock)
{ {
int retval, idx;
bool use_links = dev->power.links_count > 0; bool use_links = dev->power.links_count > 0;
bool get = false;
int retval, idx;
bool put;
if (dev->power.irq_safe) { if (dev->power.irq_safe) {
spin_unlock(&dev->power.lock); spin_unlock(&dev->power.lock);
} else if (!use_links) {
spin_unlock_irq(&dev->power.lock);
} else { } else {
get = dev->power.runtime_status == RPM_RESUMING;
spin_unlock_irq(&dev->power.lock); spin_unlock_irq(&dev->power.lock);
/* /* Resume suppliers if necessary. */
* Resume suppliers if necessary. if (get) {
*
* The device's runtime PM status cannot change until this
* routine returns, so it is safe to read the status outside of
* the lock.
*/
if (use_links && dev->power.runtime_status == RPM_RESUMING) {
idx = device_links_read_lock(); idx = device_links_read_lock();
retval = rpm_get_suppliers(dev); retval = rpm_get_suppliers(dev);
...@@ -355,24 +355,36 @@ static int __rpm_callback(int (*cb)(struct device *), struct device *dev) ...@@ -355,24 +355,36 @@ static int __rpm_callback(int (*cb)(struct device *), struct device *dev)
if (dev->power.irq_safe) { if (dev->power.irq_safe) {
spin_lock(&dev->power.lock); spin_lock(&dev->power.lock);
} else { return retval;
}
spin_lock_irq(&dev->power.lock);
if (!use_links)
return retval;
/* /*
* If the device is suspending and the callback has returned * If the device is suspending and the callback has returned success,
* success, drop the usage counters of the suppliers that have * drop the usage counters of the suppliers that have been reference
* been reference counted on its resume. * counted on its resume.
* *
* Do that if resume fails too. * Do that if the resume fails too.
*/ */
if (use_links put = dev->power.runtime_status == RPM_SUSPENDING && !retval;
&& ((dev->power.runtime_status == RPM_SUSPENDING && !retval) if (put)
|| (dev->power.runtime_status == RPM_RESUMING && retval))) { __update_runtime_status(dev, RPM_SUSPENDED);
else
put = get && retval;
if (put) {
spin_unlock_irq(&dev->power.lock);
idx = device_links_read_lock(); idx = device_links_read_lock();
fail: fail:
rpm_put_suppliers(dev); rpm_put_suppliers(dev);
device_links_read_unlock(idx); device_links_read_unlock(idx);
}
spin_lock_irq(&dev->power.lock); spin_lock_irq(&dev->power.lock);
} }
......
...@@ -45,7 +45,7 @@ config IDLE_INJECT ...@@ -45,7 +45,7 @@ config IDLE_INJECT
on a per CPU basis. on a per CPU basis.
config DTPM config DTPM
bool "Power capping for Dynamic Thermal Power Management" bool "Power capping for Dynamic Thermal Power Management (EXPERIMENTAL)"
help help
This enables support for the power capping for the dynamic This enables support for the power capping for the dynamic
thermal power management userspace engine. thermal power management userspace engine.
......
...@@ -207,6 +207,9 @@ int dtpm_release_zone(struct powercap_zone *pcz) ...@@ -207,6 +207,9 @@ int dtpm_release_zone(struct powercap_zone *pcz)
if (dtpm->ops) if (dtpm->ops)
dtpm->ops->release(dtpm); dtpm->ops->release(dtpm);
if (root == dtpm)
root = NULL;
kfree(dtpm); kfree(dtpm);
return 0; return 0;
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment