Skip to content

Commit

Permalink
---
Browse files Browse the repository at this point in the history
yaml
---
r: 202551
b: refs/heads/master
c: 8d4b9d1
h: refs/heads/master
i:
  202549: 3b24035
  202547: ae2393f
  202543: 241e321
v: v3
  • Loading branch information
Arjan van de Ven authored and Rafael J. Wysocki committed Jul 19, 2010
1 parent 0652003 commit 7c80a98
Show file tree
Hide file tree
Showing 4 changed files with 84 additions and 8 deletions.
2 changes: 1 addition & 1 deletion [refs]
Original file line number Diff line number Diff line change
@@ -1,2 +1,2 @@
---
refs/heads/master: 0fcb4eef8294492c8f1de8236b1ed81f09e42922
refs/heads/master: 8d4b9d1bfef117862a2889dec4dac227068544c9
54 changes: 47 additions & 7 deletions trunk/drivers/base/power/runtime.c
Original file line number Diff line number Diff line change
Expand Up @@ -123,6 +123,45 @@ int pm_runtime_idle(struct device *dev)
}
EXPORT_SYMBOL_GPL(pm_runtime_idle);


/**
* update_pm_runtime_accounting - Update the time accounting of power states
* @dev: Device to update the accounting for
*
* In order to be able to have time accounting of the various power states
* (as used by programs such as PowerTOP to show the effectiveness of runtime
* PM), we need to track the time spent in each state.
* update_pm_runtime_accounting must be called each time before the
* runtime_status field is updated, to account the time in the old state
* correctly.
*/
void update_pm_runtime_accounting(struct device *dev)
{
unsigned long now = jiffies;
int delta;

delta = now - dev->power.accounting_timestamp;

if (delta < 0)
delta = 0;

dev->power.accounting_timestamp = now;

if (dev->power.disable_depth > 0)
return;

if (dev->power.runtime_status == RPM_SUSPENDED)
dev->power.suspended_jiffies += delta;
else
dev->power.active_jiffies += delta;
}

static void __update_runtime_status(struct device *dev, enum rpm_status status)
{
update_pm_runtime_accounting(dev);
dev->power.runtime_status = status;
}

/**
* __pm_runtime_suspend - Carry out run-time suspend of given device.
* @dev: Device to suspend.
Expand Down Expand Up @@ -197,7 +236,7 @@ int __pm_runtime_suspend(struct device *dev, bool from_wq)
goto repeat;
}

dev->power.runtime_status = RPM_SUSPENDING;
__update_runtime_status(dev, RPM_SUSPENDING);
dev->power.deferred_resume = false;

if (dev->bus && dev->bus->pm && dev->bus->pm->runtime_suspend) {
Expand Down Expand Up @@ -228,7 +267,7 @@ int __pm_runtime_suspend(struct device *dev, bool from_wq)
}

if (retval) {
dev->power.runtime_status = RPM_ACTIVE;
__update_runtime_status(dev, RPM_ACTIVE);
if (retval == -EAGAIN || retval == -EBUSY) {
if (dev->power.timer_expires == 0)
notify = true;
Expand All @@ -237,7 +276,7 @@ int __pm_runtime_suspend(struct device *dev, bool from_wq)
pm_runtime_cancel_pending(dev);
}
} else {
dev->power.runtime_status = RPM_SUSPENDED;
__update_runtime_status(dev, RPM_SUSPENDED);
pm_runtime_deactivate_timer(dev);

if (dev->parent) {
Expand Down Expand Up @@ -381,7 +420,7 @@ int __pm_runtime_resume(struct device *dev, bool from_wq)
goto repeat;
}

dev->power.runtime_status = RPM_RESUMING;
__update_runtime_status(dev, RPM_RESUMING);

if (dev->bus && dev->bus->pm && dev->bus->pm->runtime_resume) {
spin_unlock_irq(&dev->power.lock);
Expand Down Expand Up @@ -411,10 +450,10 @@ int __pm_runtime_resume(struct device *dev, bool from_wq)
}

if (retval) {
dev->power.runtime_status = RPM_SUSPENDED;
__update_runtime_status(dev, RPM_SUSPENDED);
pm_runtime_cancel_pending(dev);
} else {
dev->power.runtime_status = RPM_ACTIVE;
__update_runtime_status(dev, RPM_ACTIVE);
if (parent)
atomic_inc(&parent->power.child_count);
}
Expand Down Expand Up @@ -848,7 +887,7 @@ int __pm_runtime_set_status(struct device *dev, unsigned int status)
}

out_set:
dev->power.runtime_status = status;
__update_runtime_status(dev, status);
dev->power.runtime_error = 0;
out:
spin_unlock_irqrestore(&dev->power.lock, flags);
Expand Down Expand Up @@ -1077,6 +1116,7 @@ void pm_runtime_init(struct device *dev)
dev->power.request_pending = false;
dev->power.request = RPM_REQ_NONE;
dev->power.deferred_resume = false;
dev->power.accounting_timestamp = jiffies;
INIT_WORK(&dev->power.work, pm_runtime_work);

dev->power.timer_expires = 0;
Expand Down
30 changes: 30 additions & 0 deletions trunk/drivers/base/power/sysfs.c
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@
#include <linux/string.h>
#include <linux/pm_runtime.h>
#include <asm/atomic.h>
#include <linux/jiffies.h>
#include "power.h"

/*
Expand Down Expand Up @@ -111,6 +112,33 @@ static ssize_t control_store(struct device * dev, struct device_attribute *attr,

static DEVICE_ATTR(control, 0644, control_show, control_store);

static ssize_t rtpm_active_time_show(struct device *dev,
struct device_attribute *attr, char *buf)
{
int ret;
spin_lock_irq(&dev->power.lock);
update_pm_runtime_accounting(dev);
ret = sprintf(buf, "%i\n", jiffies_to_msecs(dev->power.active_jiffies));
spin_unlock_irq(&dev->power.lock);
return ret;
}

static DEVICE_ATTR(runtime_active_time, 0444, rtpm_active_time_show, NULL);

static ssize_t rtpm_suspended_time_show(struct device *dev,
struct device_attribute *attr, char *buf)
{
int ret;
spin_lock_irq(&dev->power.lock);
update_pm_runtime_accounting(dev);
ret = sprintf(buf, "%i\n",
jiffies_to_msecs(dev->power.suspended_jiffies));
spin_unlock_irq(&dev->power.lock);
return ret;
}

static DEVICE_ATTR(runtime_suspended_time, 0444, rtpm_suspended_time_show, NULL);

static ssize_t rtpm_status_show(struct device *dev,
struct device_attribute *attr, char *buf)
{
Expand Down Expand Up @@ -254,6 +282,8 @@ static struct attribute * power_attrs[] = {
#ifdef CONFIG_PM_RUNTIME
&dev_attr_control.attr,
&dev_attr_runtime_status.attr,
&dev_attr_runtime_suspended_time.attr,
&dev_attr_runtime_active_time.attr,
#endif
&dev_attr_wakeup.attr,
#ifdef CONFIG_PM_SLEEP
Expand Down
6 changes: 6 additions & 0 deletions trunk/include/linux/pm.h
Original file line number Diff line number Diff line change
Expand Up @@ -477,9 +477,15 @@ struct dev_pm_info {
enum rpm_request request;
enum rpm_status runtime_status;
int runtime_error;
unsigned long active_jiffies;
unsigned long suspended_jiffies;
unsigned long accounting_timestamp;
#endif
};

extern void update_pm_runtime_accounting(struct device *dev);


/*
* The PM_EVENT_ messages are also used by drivers implementing the legacy
* suspend framework, based on the ->suspend() and ->resume() callbacks common
Expand Down

0 comments on commit 7c80a98

Please sign in to comment.