Skip to content

Commit

Permalink
Merge tag 'pm-5.12-rc2' of git://git.kernel.org/pub/scm/linux/kernel/…
Browse files Browse the repository at this point in the history
…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
  • Loading branch information
torvalds committed Mar 5, 2021
2 parents ea6be46 + 7bff4c2 commit 6d47254
Show file tree
Hide file tree
Showing 3 changed files with 41 additions and 26 deletions.
62 changes: 37 additions & 25 deletions drivers/base/power/runtime.c
Original file line number Diff line number Diff line change
Expand Up @@ -325,22 +325,22 @@ static void rpm_put_suppliers(struct device *dev)
static int __rpm_callback(int (*cb)(struct device *), struct device *dev)
__releases(&dev->power.lock) __acquires(&dev->power.lock)
{
int retval, idx;
bool use_links = dev->power.links_count > 0;
bool get = false;
int retval, idx;
bool put;

if (dev->power.irq_safe) {
spin_unlock(&dev->power.lock);
} else if (!use_links) {
spin_unlock_irq(&dev->power.lock);
} else {
get = dev->power.runtime_status == RPM_RESUMING;

spin_unlock_irq(&dev->power.lock);

/*
* Resume suppliers if necessary.
*
* 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) {
/* Resume suppliers if necessary. */
if (get) {
idx = device_links_read_lock();

retval = rpm_get_suppliers(dev);
Expand All @@ -355,24 +355,36 @@ static int __rpm_callback(int (*cb)(struct device *), struct device *dev)

if (dev->power.irq_safe) {
spin_lock(&dev->power.lock);
} else {
/*
* If the device is suspending and the callback has returned
* success, drop the usage counters of the suppliers that have
* been reference counted on its resume.
*
* Do that if resume fails too.
*/
if (use_links
&& ((dev->power.runtime_status == RPM_SUSPENDING && !retval)
|| (dev->power.runtime_status == RPM_RESUMING && retval))) {
idx = device_links_read_lock();
return retval;
}

fail:
rpm_put_suppliers(dev);
spin_lock_irq(&dev->power.lock);

device_links_read_unlock(idx);
}
if (!use_links)
return retval;

/*
* If the device is suspending and the callback has returned success,
* drop the usage counters of the suppliers that have been reference
* counted on its resume.
*
* Do that if the resume fails too.
*/
put = dev->power.runtime_status == RPM_SUSPENDING && !retval;
if (put)
__update_runtime_status(dev, RPM_SUSPENDED);
else
put = get && retval;

if (put) {
spin_unlock_irq(&dev->power.lock);

idx = device_links_read_lock();

fail:
rpm_put_suppliers(dev);

device_links_read_unlock(idx);

spin_lock_irq(&dev->power.lock);
}
Expand Down
2 changes: 1 addition & 1 deletion drivers/powercap/Kconfig
Original file line number Diff line number Diff line change
Expand Up @@ -45,7 +45,7 @@ config IDLE_INJECT
on a per CPU basis.

config DTPM
bool "Power capping for Dynamic Thermal Power Management"
bool "Power capping for Dynamic Thermal Power Management (EXPERIMENTAL)"
help
This enables support for the power capping for the dynamic
thermal power management userspace engine.
Expand Down
3 changes: 3 additions & 0 deletions drivers/powercap/dtpm.c
Original file line number Diff line number Diff line change
Expand Up @@ -207,6 +207,9 @@ int dtpm_release_zone(struct powercap_zone *pcz)
if (dtpm->ops)
dtpm->ops->release(dtpm);

if (root == dtpm)
root = NULL;

kfree(dtpm);

return 0;
Expand Down

0 comments on commit 6d47254

Please sign in to comment.