diff options
| -rw-r--r-- | drivers/base/cpu.c | 1 | ||||
| -rw-r--r-- | drivers/base/power/clock_ops.c | 13 | ||||
| -rw-r--r-- | drivers/base/power/main.c | 11 | ||||
| -rw-r--r-- | drivers/base/power/runtime.c | 70 | ||||
| -rw-r--r-- | drivers/base/power/sysfs.c | 17 | ||||
| -rw-r--r-- | drivers/gpu/drm/i915/i915_pmu.c | 16 | ||||
| -rw-r--r-- | drivers/gpu/drm/i915/i915_pmu.h | 4 | ||||
| -rw-r--r-- | include/linux/device.h | 10 | ||||
| -rw-r--r-- | include/linux/pm.h | 7 | ||||
| -rw-r--r-- | include/linux/pm_runtime.h | 2 |
10 files changed, 108 insertions, 43 deletions
diff --git a/drivers/base/cpu.c b/drivers/base/cpu.c index eb9443d5bae1..6ce93a52bf3f 100644 --- a/drivers/base/cpu.c +++ b/drivers/base/cpu.c | |||
| @@ -427,6 +427,7 @@ __cpu_device_create(struct device *parent, void *drvdata, | |||
| 427 | dev->parent = parent; | 427 | dev->parent = parent; |
| 428 | dev->groups = groups; | 428 | dev->groups = groups; |
| 429 | dev->release = device_create_release; | 429 | dev->release = device_create_release; |
| 430 | device_set_pm_not_required(dev); | ||
| 430 | dev_set_drvdata(dev, drvdata); | 431 | dev_set_drvdata(dev, drvdata); |
| 431 | 432 | ||
| 432 | retval = kobject_set_name_vargs(&dev->kobj, fmt, args); | 433 | retval = kobject_set_name_vargs(&dev->kobj, fmt, args); |
diff --git a/drivers/base/power/clock_ops.c b/drivers/base/power/clock_ops.c index 5a42ae4078c2..365ad751ce0f 100644 --- a/drivers/base/power/clock_ops.c +++ b/drivers/base/power/clock_ops.c | |||
| @@ -65,10 +65,15 @@ static void pm_clk_acquire(struct device *dev, struct pm_clock_entry *ce) | |||
| 65 | if (IS_ERR(ce->clk)) { | 65 | if (IS_ERR(ce->clk)) { |
| 66 | ce->status = PCE_STATUS_ERROR; | 66 | ce->status = PCE_STATUS_ERROR; |
| 67 | } else { | 67 | } else { |
| 68 | clk_prepare(ce->clk); | 68 | if (clk_prepare(ce->clk)) { |
| 69 | ce->status = PCE_STATUS_ACQUIRED; | 69 | ce->status = PCE_STATUS_ERROR; |
| 70 | dev_dbg(dev, "Clock %pC con_id %s managed by runtime PM.\n", | 70 | dev_err(dev, "clk_prepare() failed\n"); |
| 71 | ce->clk, ce->con_id); | 71 | } else { |
| 72 | ce->status = PCE_STATUS_ACQUIRED; | ||
| 73 | dev_dbg(dev, | ||
| 74 | "Clock %pC con_id %s managed by runtime PM.\n", | ||
| 75 | ce->clk, ce->con_id); | ||
| 76 | } | ||
| 72 | } | 77 | } |
| 73 | } | 78 | } |
| 74 | 79 | ||
diff --git a/drivers/base/power/main.c b/drivers/base/power/main.c index 0992e67e862b..893ae464bfd6 100644 --- a/drivers/base/power/main.c +++ b/drivers/base/power/main.c | |||
| @@ -124,6 +124,10 @@ void device_pm_unlock(void) | |||
| 124 | */ | 124 | */ |
| 125 | void device_pm_add(struct device *dev) | 125 | void device_pm_add(struct device *dev) |
| 126 | { | 126 | { |
| 127 | /* Skip PM setup/initialization. */ | ||
| 128 | if (device_pm_not_required(dev)) | ||
| 129 | return; | ||
| 130 | |||
| 127 | pr_debug("PM: Adding info for %s:%s\n", | 131 | pr_debug("PM: Adding info for %s:%s\n", |
| 128 | dev->bus ? dev->bus->name : "No Bus", dev_name(dev)); | 132 | dev->bus ? dev->bus->name : "No Bus", dev_name(dev)); |
| 129 | device_pm_check_callbacks(dev); | 133 | device_pm_check_callbacks(dev); |
| @@ -142,6 +146,9 @@ void device_pm_add(struct device *dev) | |||
| 142 | */ | 146 | */ |
| 143 | void device_pm_remove(struct device *dev) | 147 | void device_pm_remove(struct device *dev) |
| 144 | { | 148 | { |
| 149 | if (device_pm_not_required(dev)) | ||
| 150 | return; | ||
| 151 | |||
| 145 | pr_debug("PM: Removing info for %s:%s\n", | 152 | pr_debug("PM: Removing info for %s:%s\n", |
| 146 | dev->bus ? dev->bus->name : "No Bus", dev_name(dev)); | 153 | dev->bus ? dev->bus->name : "No Bus", dev_name(dev)); |
| 147 | complete_all(&dev->power.completion); | 154 | complete_all(&dev->power.completion); |
| @@ -1741,8 +1748,10 @@ static int __device_suspend(struct device *dev, pm_message_t state, bool async) | |||
| 1741 | if (dev->power.direct_complete) { | 1748 | if (dev->power.direct_complete) { |
| 1742 | if (pm_runtime_status_suspended(dev)) { | 1749 | if (pm_runtime_status_suspended(dev)) { |
| 1743 | pm_runtime_disable(dev); | 1750 | pm_runtime_disable(dev); |
| 1744 | if (pm_runtime_status_suspended(dev)) | 1751 | if (pm_runtime_status_suspended(dev)) { |
| 1752 | pm_dev_dbg(dev, state, "direct-complete "); | ||
| 1745 | goto Complete; | 1753 | goto Complete; |
| 1754 | } | ||
| 1746 | 1755 | ||
| 1747 | pm_runtime_enable(dev); | 1756 | pm_runtime_enable(dev); |
| 1748 | } | 1757 | } |
diff --git a/drivers/base/power/runtime.c b/drivers/base/power/runtime.c index ccd296dbb95c..78937c45278c 100644 --- a/drivers/base/power/runtime.c +++ b/drivers/base/power/runtime.c | |||
| @@ -66,20 +66,30 @@ static int rpm_suspend(struct device *dev, int rpmflags); | |||
| 66 | */ | 66 | */ |
| 67 | void update_pm_runtime_accounting(struct device *dev) | 67 | void update_pm_runtime_accounting(struct device *dev) |
| 68 | { | 68 | { |
| 69 | unsigned long now = jiffies; | 69 | u64 now, last, delta; |
| 70 | unsigned long delta; | ||
| 71 | 70 | ||
| 72 | delta = now - dev->power.accounting_timestamp; | 71 | if (dev->power.disable_depth > 0) |
| 72 | return; | ||
| 73 | |||
| 74 | last = dev->power.accounting_timestamp; | ||
| 73 | 75 | ||
| 76 | now = ktime_get_mono_fast_ns(); | ||
| 74 | dev->power.accounting_timestamp = now; | 77 | dev->power.accounting_timestamp = now; |
| 75 | 78 | ||
| 76 | if (dev->power.disable_depth > 0) | 79 | /* |
| 80 | * Because ktime_get_mono_fast_ns() is not monotonic during | ||
| 81 | * timekeeping updates, ensure that 'now' is after the last saved | ||
| 82 | * timesptamp. | ||
| 83 | */ | ||
| 84 | if (now < last) | ||
| 77 | return; | 85 | return; |
| 78 | 86 | ||
| 87 | delta = now - last; | ||
| 88 | |||
| 79 | if (dev->power.runtime_status == RPM_SUSPENDED) | 89 | if (dev->power.runtime_status == RPM_SUSPENDED) |
| 80 | dev->power.suspended_jiffies += delta; | 90 | dev->power.suspended_time += delta; |
| 81 | else | 91 | else |
| 82 | dev->power.active_jiffies += delta; | 92 | dev->power.active_time += delta; |
| 83 | } | 93 | } |
| 84 | 94 | ||
| 85 | static void __update_runtime_status(struct device *dev, enum rpm_status status) | 95 | static void __update_runtime_status(struct device *dev, enum rpm_status status) |
| @@ -88,6 +98,22 @@ static void __update_runtime_status(struct device *dev, enum rpm_status status) | |||
| 88 | dev->power.runtime_status = status; | 98 | dev->power.runtime_status = status; |
| 89 | } | 99 | } |
| 90 | 100 | ||
| 101 | u64 pm_runtime_suspended_time(struct device *dev) | ||
| 102 | { | ||
| 103 | u64 time; | ||
| 104 | unsigned long flags; | ||
| 105 | |||
| 106 | spin_lock_irqsave(&dev->power.lock, flags); | ||
| 107 | |||
| 108 | update_pm_runtime_accounting(dev); | ||
| 109 | time = dev->power.suspended_time; | ||
| 110 | |||
| 111 | spin_unlock_irqrestore(&dev->power.lock, flags); | ||
| 112 | |||
| 113 | return time; | ||
| 114 | } | ||
| 115 | EXPORT_SYMBOL_GPL(pm_runtime_suspended_time); | ||
| 116 | |||
| 91 | /** | 117 | /** |
| 92 | * pm_runtime_deactivate_timer - Deactivate given device's suspend timer. | 118 | * pm_runtime_deactivate_timer - Deactivate given device's suspend timer. |
| 93 | * @dev: Device to handle. | 119 | * @dev: Device to handle. |
| @@ -129,24 +155,21 @@ static void pm_runtime_cancel_pending(struct device *dev) | |||
| 129 | u64 pm_runtime_autosuspend_expiration(struct device *dev) | 155 | u64 pm_runtime_autosuspend_expiration(struct device *dev) |
| 130 | { | 156 | { |
| 131 | int autosuspend_delay; | 157 | int autosuspend_delay; |
| 132 | u64 last_busy, expires = 0; | 158 | u64 expires; |
| 133 | u64 now = ktime_get_mono_fast_ns(); | ||
| 134 | 159 | ||
| 135 | if (!dev->power.use_autosuspend) | 160 | if (!dev->power.use_autosuspend) |
| 136 | goto out; | 161 | return 0; |
| 137 | 162 | ||
| 138 | autosuspend_delay = READ_ONCE(dev->power.autosuspend_delay); | 163 | autosuspend_delay = READ_ONCE(dev->power.autosuspend_delay); |
| 139 | if (autosuspend_delay < 0) | 164 | if (autosuspend_delay < 0) |
| 140 | goto out; | 165 | return 0; |
| 141 | |||
| 142 | last_busy = READ_ONCE(dev->power.last_busy); | ||
| 143 | 166 | ||
| 144 | expires = last_busy + (u64)autosuspend_delay * NSEC_PER_MSEC; | 167 | expires = READ_ONCE(dev->power.last_busy); |
| 145 | if (expires <= now) | 168 | expires += (u64)autosuspend_delay * NSEC_PER_MSEC; |
| 146 | expires = 0; /* Already expired. */ | 169 | if (expires > ktime_get_mono_fast_ns()) |
| 170 | return expires; /* Expires in the future */ | ||
| 147 | 171 | ||
| 148 | out: | 172 | return 0; |
| 149 | return expires; | ||
| 150 | } | 173 | } |
| 151 | EXPORT_SYMBOL_GPL(pm_runtime_autosuspend_expiration); | 174 | EXPORT_SYMBOL_GPL(pm_runtime_autosuspend_expiration); |
| 152 | 175 | ||
| @@ -1276,6 +1299,9 @@ void __pm_runtime_disable(struct device *dev, bool check_resume) | |||
| 1276 | pm_runtime_put_noidle(dev); | 1299 | pm_runtime_put_noidle(dev); |
| 1277 | } | 1300 | } |
| 1278 | 1301 | ||
| 1302 | /* Update time accounting before disabling PM-runtime. */ | ||
| 1303 | update_pm_runtime_accounting(dev); | ||
| 1304 | |||
| 1279 | if (!dev->power.disable_depth++) | 1305 | if (!dev->power.disable_depth++) |
| 1280 | __pm_runtime_barrier(dev); | 1306 | __pm_runtime_barrier(dev); |
| 1281 | 1307 | ||
| @@ -1294,10 +1320,15 @@ void pm_runtime_enable(struct device *dev) | |||
| 1294 | 1320 | ||
| 1295 | spin_lock_irqsave(&dev->power.lock, flags); | 1321 | spin_lock_irqsave(&dev->power.lock, flags); |
| 1296 | 1322 | ||
| 1297 | if (dev->power.disable_depth > 0) | 1323 | if (dev->power.disable_depth > 0) { |
| 1298 | dev->power.disable_depth--; | 1324 | dev->power.disable_depth--; |
| 1299 | else | 1325 | |
| 1326 | /* About to enable runtime pm, set accounting_timestamp to now */ | ||
| 1327 | if (!dev->power.disable_depth) | ||
| 1328 | dev->power.accounting_timestamp = ktime_get_mono_fast_ns(); | ||
| 1329 | } else { | ||
| 1300 | dev_warn(dev, "Unbalanced %s!\n", __func__); | 1330 | dev_warn(dev, "Unbalanced %s!\n", __func__); |
| 1331 | } | ||
| 1301 | 1332 | ||
| 1302 | WARN(!dev->power.disable_depth && | 1333 | WARN(!dev->power.disable_depth && |
| 1303 | dev->power.runtime_status == RPM_SUSPENDED && | 1334 | dev->power.runtime_status == RPM_SUSPENDED && |
| @@ -1494,7 +1525,6 @@ void pm_runtime_init(struct device *dev) | |||
| 1494 | dev->power.request_pending = false; | 1525 | dev->power.request_pending = false; |
| 1495 | dev->power.request = RPM_REQ_NONE; | 1526 | dev->power.request = RPM_REQ_NONE; |
| 1496 | dev->power.deferred_resume = false; | 1527 | dev->power.deferred_resume = false; |
| 1497 | dev->power.accounting_timestamp = jiffies; | ||
| 1498 | INIT_WORK(&dev->power.work, pm_runtime_work); | 1528 | INIT_WORK(&dev->power.work, pm_runtime_work); |
| 1499 | 1529 | ||
| 1500 | dev->power.timer_expires = 0; | 1530 | dev->power.timer_expires = 0; |
diff --git a/drivers/base/power/sysfs.c b/drivers/base/power/sysfs.c index d713738ce796..c6bf76124184 100644 --- a/drivers/base/power/sysfs.c +++ b/drivers/base/power/sysfs.c | |||
| @@ -125,9 +125,12 @@ static ssize_t runtime_active_time_show(struct device *dev, | |||
| 125 | struct device_attribute *attr, char *buf) | 125 | struct device_attribute *attr, char *buf) |
| 126 | { | 126 | { |
| 127 | int ret; | 127 | int ret; |
| 128 | u64 tmp; | ||
| 128 | spin_lock_irq(&dev->power.lock); | 129 | spin_lock_irq(&dev->power.lock); |
| 129 | update_pm_runtime_accounting(dev); | 130 | update_pm_runtime_accounting(dev); |
| 130 | ret = sprintf(buf, "%i\n", jiffies_to_msecs(dev->power.active_jiffies)); | 131 | tmp = dev->power.active_time; |
| 132 | do_div(tmp, NSEC_PER_MSEC); | ||
| 133 | ret = sprintf(buf, "%llu\n", tmp); | ||
| 131 | spin_unlock_irq(&dev->power.lock); | 134 | spin_unlock_irq(&dev->power.lock); |
| 132 | return ret; | 135 | return ret; |
| 133 | } | 136 | } |
| @@ -138,10 +141,12 @@ static ssize_t runtime_suspended_time_show(struct device *dev, | |||
| 138 | struct device_attribute *attr, char *buf) | 141 | struct device_attribute *attr, char *buf) |
| 139 | { | 142 | { |
| 140 | int ret; | 143 | int ret; |
| 144 | u64 tmp; | ||
| 141 | spin_lock_irq(&dev->power.lock); | 145 | spin_lock_irq(&dev->power.lock); |
| 142 | update_pm_runtime_accounting(dev); | 146 | update_pm_runtime_accounting(dev); |
| 143 | ret = sprintf(buf, "%i\n", | 147 | tmp = dev->power.suspended_time; |
| 144 | jiffies_to_msecs(dev->power.suspended_jiffies)); | 148 | do_div(tmp, NSEC_PER_MSEC); |
| 149 | ret = sprintf(buf, "%llu\n", tmp); | ||
| 145 | spin_unlock_irq(&dev->power.lock); | 150 | spin_unlock_irq(&dev->power.lock); |
| 146 | return ret; | 151 | return ret; |
| 147 | } | 152 | } |
| @@ -648,6 +653,10 @@ int dpm_sysfs_add(struct device *dev) | |||
| 648 | { | 653 | { |
| 649 | int rc; | 654 | int rc; |
| 650 | 655 | ||
| 656 | /* No need to create PM sysfs if explicitly disabled. */ | ||
| 657 | if (device_pm_not_required(dev)) | ||
| 658 | return 0; | ||
| 659 | |||
| 651 | rc = sysfs_create_group(&dev->kobj, &pm_attr_group); | 660 | rc = sysfs_create_group(&dev->kobj, &pm_attr_group); |
| 652 | if (rc) | 661 | if (rc) |
| 653 | return rc; | 662 | return rc; |
| @@ -727,6 +736,8 @@ void rpm_sysfs_remove(struct device *dev) | |||
| 727 | 736 | ||
| 728 | void dpm_sysfs_remove(struct device *dev) | 737 | void dpm_sysfs_remove(struct device *dev) |
| 729 | { | 738 | { |
| 739 | if (device_pm_not_required(dev)) | ||
| 740 | return; | ||
| 730 | sysfs_unmerge_group(&dev->kobj, &pm_qos_latency_tolerance_attr_group); | 741 | sysfs_unmerge_group(&dev->kobj, &pm_qos_latency_tolerance_attr_group); |
| 731 | dev_pm_qos_constraints_destroy(dev); | 742 | dev_pm_qos_constraints_destroy(dev); |
| 732 | rpm_sysfs_remove(dev); | 743 | rpm_sysfs_remove(dev); |
diff --git a/drivers/gpu/drm/i915/i915_pmu.c b/drivers/gpu/drm/i915/i915_pmu.c index 017fc602a10e..cf7c66bb3ed9 100644 --- a/drivers/gpu/drm/i915/i915_pmu.c +++ b/drivers/gpu/drm/i915/i915_pmu.c | |||
| @@ -5,6 +5,7 @@ | |||
| 5 | */ | 5 | */ |
| 6 | 6 | ||
| 7 | #include <linux/irq.h> | 7 | #include <linux/irq.h> |
| 8 | #include <linux/pm_runtime.h> | ||
| 8 | #include "i915_pmu.h" | 9 | #include "i915_pmu.h" |
| 9 | #include "intel_ringbuffer.h" | 10 | #include "intel_ringbuffer.h" |
| 10 | #include "i915_drv.h" | 11 | #include "i915_drv.h" |
| @@ -478,7 +479,6 @@ static u64 get_rc6(struct drm_i915_private *i915) | |||
| 478 | * counter value. | 479 | * counter value. |
| 479 | */ | 480 | */ |
| 480 | spin_lock_irqsave(&i915->pmu.lock, flags); | 481 | spin_lock_irqsave(&i915->pmu.lock, flags); |
| 481 | spin_lock(&kdev->power.lock); | ||
| 482 | 482 | ||
| 483 | /* | 483 | /* |
| 484 | * After the above branch intel_runtime_pm_get_if_in_use failed | 484 | * After the above branch intel_runtime_pm_get_if_in_use failed |
| @@ -491,16 +491,13 @@ static u64 get_rc6(struct drm_i915_private *i915) | |||
| 491 | * suspended and if not we cannot do better than report the last | 491 | * suspended and if not we cannot do better than report the last |
| 492 | * known RC6 value. | 492 | * known RC6 value. |
| 493 | */ | 493 | */ |
| 494 | if (kdev->power.runtime_status == RPM_SUSPENDED) { | 494 | if (pm_runtime_status_suspended(kdev)) { |
| 495 | if (!i915->pmu.sample[__I915_SAMPLE_RC6_ESTIMATED].cur) | 495 | val = pm_runtime_suspended_time(kdev); |
| 496 | i915->pmu.suspended_jiffies_last = | ||
| 497 | kdev->power.suspended_jiffies; | ||
| 498 | 496 | ||
| 499 | val = kdev->power.suspended_jiffies - | 497 | if (!i915->pmu.sample[__I915_SAMPLE_RC6_ESTIMATED].cur) |
| 500 | i915->pmu.suspended_jiffies_last; | 498 | i915->pmu.suspended_time_last = val; |
| 501 | val += jiffies - kdev->power.accounting_timestamp; | ||
| 502 | 499 | ||
| 503 | val = jiffies_to_nsecs(val); | 500 | val -= i915->pmu.suspended_time_last; |
| 504 | val += i915->pmu.sample[__I915_SAMPLE_RC6].cur; | 501 | val += i915->pmu.sample[__I915_SAMPLE_RC6].cur; |
| 505 | 502 | ||
| 506 | i915->pmu.sample[__I915_SAMPLE_RC6_ESTIMATED].cur = val; | 503 | i915->pmu.sample[__I915_SAMPLE_RC6_ESTIMATED].cur = val; |
| @@ -510,7 +507,6 @@ static u64 get_rc6(struct drm_i915_private *i915) | |||
| 510 | val = i915->pmu.sample[__I915_SAMPLE_RC6].cur; | 507 | val = i915->pmu.sample[__I915_SAMPLE_RC6].cur; |
| 511 | } | 508 | } |
| 512 | 509 | ||
| 513 | spin_unlock(&kdev->power.lock); | ||
| 514 | spin_unlock_irqrestore(&i915->pmu.lock, flags); | 510 | spin_unlock_irqrestore(&i915->pmu.lock, flags); |
| 515 | } | 511 | } |
| 516 | 512 | ||
diff --git a/drivers/gpu/drm/i915/i915_pmu.h b/drivers/gpu/drm/i915/i915_pmu.h index b3728c5f13e7..4fc4f2478301 100644 --- a/drivers/gpu/drm/i915/i915_pmu.h +++ b/drivers/gpu/drm/i915/i915_pmu.h | |||
| @@ -97,9 +97,9 @@ struct i915_pmu { | |||
| 97 | */ | 97 | */ |
| 98 | struct i915_pmu_sample sample[__I915_NUM_PMU_SAMPLERS]; | 98 | struct i915_pmu_sample sample[__I915_NUM_PMU_SAMPLERS]; |
| 99 | /** | 99 | /** |
| 100 | * @suspended_jiffies_last: Cached suspend time from PM core. | 100 | * @suspended_time_last: Cached suspend time from PM core. |
| 101 | */ | 101 | */ |
| 102 | unsigned long suspended_jiffies_last; | 102 | u64 suspended_time_last; |
| 103 | /** | 103 | /** |
| 104 | * @i915_attr: Memory block holding device attributes. | 104 | * @i915_attr: Memory block holding device attributes. |
| 105 | */ | 105 | */ |
diff --git a/include/linux/device.h b/include/linux/device.h index 6cb4640b6160..53028636fe39 100644 --- a/include/linux/device.h +++ b/include/linux/device.h | |||
| @@ -1165,6 +1165,16 @@ static inline bool device_async_suspend_enabled(struct device *dev) | |||
| 1165 | return !!dev->power.async_suspend; | 1165 | return !!dev->power.async_suspend; |
| 1166 | } | 1166 | } |
| 1167 | 1167 | ||
| 1168 | static inline bool device_pm_not_required(struct device *dev) | ||
| 1169 | { | ||
| 1170 | return dev->power.no_pm; | ||
| 1171 | } | ||
| 1172 | |||
| 1173 | static inline void device_set_pm_not_required(struct device *dev) | ||
| 1174 | { | ||
| 1175 | dev->power.no_pm = true; | ||
| 1176 | } | ||
| 1177 | |||
| 1168 | static inline void dev_pm_syscore_device(struct device *dev, bool val) | 1178 | static inline void dev_pm_syscore_device(struct device *dev, bool val) |
| 1169 | { | 1179 | { |
| 1170 | #ifdef CONFIG_PM_SLEEP | 1180 | #ifdef CONFIG_PM_SLEEP |
diff --git a/include/linux/pm.h b/include/linux/pm.h index 0bd9de116826..06f7ed893928 100644 --- a/include/linux/pm.h +++ b/include/linux/pm.h | |||
| @@ -592,6 +592,7 @@ struct dev_pm_info { | |||
| 592 | bool is_suspended:1; /* Ditto */ | 592 | bool is_suspended:1; /* Ditto */ |
| 593 | bool is_noirq_suspended:1; | 593 | bool is_noirq_suspended:1; |
| 594 | bool is_late_suspended:1; | 594 | bool is_late_suspended:1; |
| 595 | bool no_pm:1; | ||
| 595 | bool early_init:1; /* Owned by the PM core */ | 596 | bool early_init:1; /* Owned by the PM core */ |
| 596 | bool direct_complete:1; /* Owned by the PM core */ | 597 | bool direct_complete:1; /* Owned by the PM core */ |
| 597 | u32 driver_flags; | 598 | u32 driver_flags; |
| @@ -633,9 +634,9 @@ struct dev_pm_info { | |||
| 633 | int runtime_error; | 634 | int runtime_error; |
| 634 | int autosuspend_delay; | 635 | int autosuspend_delay; |
| 635 | u64 last_busy; | 636 | u64 last_busy; |
| 636 | unsigned long active_jiffies; | 637 | u64 active_time; |
| 637 | unsigned long suspended_jiffies; | 638 | u64 suspended_time; |
| 638 | unsigned long accounting_timestamp; | 639 | u64 accounting_timestamp; |
| 639 | #endif | 640 | #endif |
| 640 | struct pm_subsys_data *subsys_data; /* Owned by the subsystem. */ | 641 | struct pm_subsys_data *subsys_data; /* Owned by the subsystem. */ |
| 641 | void (*set_latency_tolerance)(struct device *, s32); | 642 | void (*set_latency_tolerance)(struct device *, s32); |
diff --git a/include/linux/pm_runtime.h b/include/linux/pm_runtime.h index fed5be706bc9..9dc6eebf62d2 100644 --- a/include/linux/pm_runtime.h +++ b/include/linux/pm_runtime.h | |||
| @@ -113,6 +113,8 @@ static inline bool pm_runtime_is_irq_safe(struct device *dev) | |||
| 113 | return dev->power.irq_safe; | 113 | return dev->power.irq_safe; |
| 114 | } | 114 | } |
| 115 | 115 | ||
| 116 | extern u64 pm_runtime_suspended_time(struct device *dev); | ||
| 117 | |||
| 116 | #else /* !CONFIG_PM */ | 118 | #else /* !CONFIG_PM */ |
| 117 | 119 | ||
| 118 | static inline bool queue_pm_work(struct work_struct *work) { return false; } | 120 | static inline bool queue_pm_work(struct work_struct *work) { return false; } |
