}
 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.
                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) {
        }
 
        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;
                        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) {
                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);
        }
 
        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);
        }
        }
 
  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);
        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;
 
 #include <linux/string.h>
 #include <linux/pm_runtime.h>
 #include <asm/atomic.h>
+#include <linux/jiffies.h>
 #include "power.h"
 
 /*
 
 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)
 {
 #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