aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/base
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/base')
-rw-r--r--drivers/base/cpu.c1
-rw-r--r--drivers/base/power/clock_ops.c13
-rw-r--r--drivers/base/power/main.c11
-rw-r--r--drivers/base/power/runtime.c70
-rw-r--r--drivers/base/power/sysfs.c17
5 files changed, 84 insertions, 28 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 */
125void device_pm_add(struct device *dev) 125void 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 */
143void device_pm_remove(struct device *dev) 147void 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 */
67void update_pm_runtime_accounting(struct device *dev) 67void 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
85static void __update_runtime_status(struct device *dev, enum rpm_status status) 95static 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
101u64 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}
115EXPORT_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)
129u64 pm_runtime_autosuspend_expiration(struct device *dev) 155u64 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}
151EXPORT_SYMBOL_GPL(pm_runtime_autosuspend_expiration); 174EXPORT_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
728void dpm_sysfs_remove(struct device *dev) 737void 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);