diff options
author | Rafael J. Wysocki <rafael.j.wysocki@intel.com> | 2017-10-31 13:26:15 -0400 |
---|---|---|
committer | Rafael J. Wysocki <rafael.j.wysocki@intel.com> | 2017-10-31 13:35:40 -0400 |
commit | d5919dcc349d2a16d805ef8096d36e4f519e42ae (patch) | |
tree | 583956db5482efb7b38a0eddb51bac5b63db051d | |
parent | 5ba257249e9c8cb2c670e22b0f02d1806f349102 (diff) |
Revert "PM / QoS: Fix device resume latency PM QoS"
This reverts commit 0cc2b4e5a020 (PM / QoS: Fix device resume latency PM
QoS) as it introduced regressions on multiple systems and the fix-up
in commit 2a9a86d5c813 (PM / QoS: Fix default runtime_pm device resume
latency) does not address all of them.
The original problem that commit 0cc2b4e5a020 was attempting to fix
will be addressed later.
Fixes: 0cc2b4e5a020 (PM / QoS: Fix device resume latency PM QoS)
Reported-by: Geert Uytterhoeven <geert@linux-m68k.org>
Signed-off-by: Rafael J. Wysocki <rafael.j.wysocki@intel.com>
-rw-r--r-- | Documentation/ABI/testing/sysfs-devices-power | 4 | ||||
-rw-r--r-- | drivers/base/cpu.c | 3 | ||||
-rw-r--r-- | drivers/base/power/domain_governor.c | 53 | ||||
-rw-r--r-- | drivers/base/power/qos.c | 2 | ||||
-rw-r--r-- | drivers/base/power/runtime.c | 2 | ||||
-rw-r--r-- | drivers/base/power/sysfs.c | 25 | ||||
-rw-r--r-- | drivers/cpuidle/governors/menu.c | 4 | ||||
-rw-r--r-- | include/linux/pm_qos.h | 5 |
8 files changed, 35 insertions, 63 deletions
diff --git a/Documentation/ABI/testing/sysfs-devices-power b/Documentation/ABI/testing/sysfs-devices-power index 5cbb6f038615..676fdf5f2a99 100644 --- a/Documentation/ABI/testing/sysfs-devices-power +++ b/Documentation/ABI/testing/sysfs-devices-power | |||
@@ -211,9 +211,7 @@ Description: | |||
211 | device, after it has been suspended at run time, from a resume | 211 | device, after it has been suspended at run time, from a resume |
212 | request to the moment the device will be ready to process I/O, | 212 | request to the moment the device will be ready to process I/O, |
213 | in microseconds. If it is equal to 0, however, this means that | 213 | in microseconds. If it is equal to 0, however, this means that |
214 | the PM QoS resume latency may be arbitrary and the special value | 214 | the PM QoS resume latency may be arbitrary. |
215 | "n/a" means that user space cannot accept any resume latency at | ||
216 | all for the given device. | ||
217 | 215 | ||
218 | Not all drivers support this attribute. If it isn't supported, | 216 | Not all drivers support this attribute. If it isn't supported, |
219 | it is not present. | 217 | it is not present. |
diff --git a/drivers/base/cpu.c b/drivers/base/cpu.c index 227bac5f1191..321cd7b4d817 100644 --- a/drivers/base/cpu.c +++ b/drivers/base/cpu.c | |||
@@ -377,8 +377,7 @@ int register_cpu(struct cpu *cpu, int num) | |||
377 | 377 | ||
378 | per_cpu(cpu_sys_devices, num) = &cpu->dev; | 378 | per_cpu(cpu_sys_devices, num) = &cpu->dev; |
379 | register_cpu_under_node(num, cpu_to_node(num)); | 379 | register_cpu_under_node(num, cpu_to_node(num)); |
380 | dev_pm_qos_expose_latency_limit(&cpu->dev, | 380 | dev_pm_qos_expose_latency_limit(&cpu->dev, 0); |
381 | PM_QOS_RESUME_LATENCY_NO_CONSTRAINT); | ||
382 | 381 | ||
383 | return 0; | 382 | return 0; |
384 | } | 383 | } |
diff --git a/drivers/base/power/domain_governor.c b/drivers/base/power/domain_governor.c index 51751cc8c9e6..281f949c5ffe 100644 --- a/drivers/base/power/domain_governor.c +++ b/drivers/base/power/domain_governor.c | |||
@@ -14,20 +14,23 @@ | |||
14 | static int dev_update_qos_constraint(struct device *dev, void *data) | 14 | static int dev_update_qos_constraint(struct device *dev, void *data) |
15 | { | 15 | { |
16 | s64 *constraint_ns_p = data; | 16 | s64 *constraint_ns_p = data; |
17 | s64 constraint_ns = -1; | 17 | s32 constraint_ns = -1; |
18 | 18 | ||
19 | if (dev->power.subsys_data && dev->power.subsys_data->domain_data) | 19 | if (dev->power.subsys_data && dev->power.subsys_data->domain_data) |
20 | constraint_ns = dev_gpd_data(dev)->td.effective_constraint_ns; | 20 | constraint_ns = dev_gpd_data(dev)->td.effective_constraint_ns; |
21 | 21 | ||
22 | if (constraint_ns < 0) | 22 | if (constraint_ns < 0) { |
23 | constraint_ns = dev_pm_qos_read_value(dev); | 23 | constraint_ns = dev_pm_qos_read_value(dev); |
24 | 24 | constraint_ns *= NSEC_PER_USEC; | |
25 | if (constraint_ns == PM_QOS_RESUME_LATENCY_NO_CONSTRAINT) | 25 | } |
26 | if (constraint_ns == 0) | ||
26 | return 0; | 27 | return 0; |
27 | 28 | ||
28 | constraint_ns *= NSEC_PER_USEC; | 29 | /* |
29 | 30 | * constraint_ns cannot be negative here, because the device has been | |
30 | if (constraint_ns < *constraint_ns_p || *constraint_ns_p < 0) | 31 | * suspended. |
32 | */ | ||
33 | if (constraint_ns < *constraint_ns_p || *constraint_ns_p == 0) | ||
31 | *constraint_ns_p = constraint_ns; | 34 | *constraint_ns_p = constraint_ns; |
32 | 35 | ||
33 | return 0; | 36 | return 0; |
@@ -60,14 +63,10 @@ static bool default_suspend_ok(struct device *dev) | |||
60 | 63 | ||
61 | spin_unlock_irqrestore(&dev->power.lock, flags); | 64 | spin_unlock_irqrestore(&dev->power.lock, flags); |
62 | 65 | ||
63 | if (constraint_ns == 0) | 66 | if (constraint_ns < 0) |
64 | return false; | 67 | return false; |
65 | 68 | ||
66 | if (constraint_ns == PM_QOS_RESUME_LATENCY_NO_CONSTRAINT) | 69 | constraint_ns *= NSEC_PER_USEC; |
67 | constraint_ns = -1; | ||
68 | else | ||
69 | constraint_ns *= NSEC_PER_USEC; | ||
70 | |||
71 | /* | 70 | /* |
72 | * We can walk the children without any additional locking, because | 71 | * We can walk the children without any additional locking, because |
73 | * they all have been suspended at this point and their | 72 | * they all have been suspended at this point and their |
@@ -77,19 +76,14 @@ static bool default_suspend_ok(struct device *dev) | |||
77 | device_for_each_child(dev, &constraint_ns, | 76 | device_for_each_child(dev, &constraint_ns, |
78 | dev_update_qos_constraint); | 77 | dev_update_qos_constraint); |
79 | 78 | ||
80 | if (constraint_ns < 0) { | 79 | if (constraint_ns > 0) { |
81 | /* The children have no constraints. */ | 80 | constraint_ns -= td->suspend_latency_ns + |
82 | td->effective_constraint_ns = PM_QOS_RESUME_LATENCY_NO_CONSTRAINT; | 81 | td->resume_latency_ns; |
83 | td->cached_suspend_ok = true; | 82 | if (constraint_ns == 0) |
84 | } else { | 83 | return false; |
85 | constraint_ns -= td->suspend_latency_ns + td->resume_latency_ns; | ||
86 | if (constraint_ns > 0) { | ||
87 | td->effective_constraint_ns = constraint_ns; | ||
88 | td->cached_suspend_ok = true; | ||
89 | } else { | ||
90 | td->effective_constraint_ns = 0; | ||
91 | } | ||
92 | } | 84 | } |
85 | td->effective_constraint_ns = constraint_ns; | ||
86 | td->cached_suspend_ok = constraint_ns >= 0; | ||
93 | 87 | ||
94 | /* | 88 | /* |
95 | * The children have been suspended already, so we don't need to take | 89 | * The children have been suspended already, so we don't need to take |
@@ -151,14 +145,13 @@ static bool __default_power_down_ok(struct dev_pm_domain *pd, | |||
151 | td = &to_gpd_data(pdd)->td; | 145 | td = &to_gpd_data(pdd)->td; |
152 | constraint_ns = td->effective_constraint_ns; | 146 | constraint_ns = td->effective_constraint_ns; |
153 | /* default_suspend_ok() need not be called before us. */ | 147 | /* default_suspend_ok() need not be called before us. */ |
154 | if (constraint_ns < 0) | 148 | if (constraint_ns < 0) { |
155 | constraint_ns = dev_pm_qos_read_value(pdd->dev); | 149 | constraint_ns = dev_pm_qos_read_value(pdd->dev); |
156 | 150 | constraint_ns *= NSEC_PER_USEC; | |
157 | if (constraint_ns == PM_QOS_RESUME_LATENCY_NO_CONSTRAINT) | 151 | } |
152 | if (constraint_ns == 0) | ||
158 | continue; | 153 | continue; |
159 | 154 | ||
160 | constraint_ns *= NSEC_PER_USEC; | ||
161 | |||
162 | /* | 155 | /* |
163 | * constraint_ns cannot be negative here, because the device has | 156 | * constraint_ns cannot be negative here, because the device has |
164 | * been suspended. | 157 | * been suspended. |
diff --git a/drivers/base/power/qos.c b/drivers/base/power/qos.c index 7d29286d9313..277d43a83f53 100644 --- a/drivers/base/power/qos.c +++ b/drivers/base/power/qos.c | |||
@@ -189,7 +189,7 @@ static int dev_pm_qos_constraints_allocate(struct device *dev) | |||
189 | plist_head_init(&c->list); | 189 | plist_head_init(&c->list); |
190 | c->target_value = PM_QOS_RESUME_LATENCY_DEFAULT_VALUE; | 190 | c->target_value = PM_QOS_RESUME_LATENCY_DEFAULT_VALUE; |
191 | c->default_value = PM_QOS_RESUME_LATENCY_DEFAULT_VALUE; | 191 | c->default_value = PM_QOS_RESUME_LATENCY_DEFAULT_VALUE; |
192 | c->no_constraint_value = PM_QOS_RESUME_LATENCY_NO_CONSTRAINT; | 192 | c->no_constraint_value = PM_QOS_RESUME_LATENCY_DEFAULT_VALUE; |
193 | c->type = PM_QOS_MIN; | 193 | c->type = PM_QOS_MIN; |
194 | c->notifiers = n; | 194 | c->notifiers = n; |
195 | 195 | ||
diff --git a/drivers/base/power/runtime.c b/drivers/base/power/runtime.c index 13e015905543..7bcf80fa9ada 100644 --- a/drivers/base/power/runtime.c +++ b/drivers/base/power/runtime.c | |||
@@ -253,7 +253,7 @@ static int rpm_check_suspend_allowed(struct device *dev) | |||
253 | || (dev->power.request_pending | 253 | || (dev->power.request_pending |
254 | && dev->power.request == RPM_REQ_RESUME)) | 254 | && dev->power.request == RPM_REQ_RESUME)) |
255 | retval = -EAGAIN; | 255 | retval = -EAGAIN; |
256 | else if (__dev_pm_qos_read_value(dev) == 0) | 256 | else if (__dev_pm_qos_read_value(dev) < 0) |
257 | retval = -EPERM; | 257 | retval = -EPERM; |
258 | else if (dev->power.runtime_status == RPM_SUSPENDED) | 258 | else if (dev->power.runtime_status == RPM_SUSPENDED) |
259 | retval = 1; | 259 | retval = 1; |
diff --git a/drivers/base/power/sysfs.c b/drivers/base/power/sysfs.c index 632077f05c57..156ab57bca77 100644 --- a/drivers/base/power/sysfs.c +++ b/drivers/base/power/sysfs.c | |||
@@ -218,14 +218,7 @@ static ssize_t pm_qos_resume_latency_show(struct device *dev, | |||
218 | struct device_attribute *attr, | 218 | struct device_attribute *attr, |
219 | char *buf) | 219 | char *buf) |
220 | { | 220 | { |
221 | s32 value = dev_pm_qos_requested_resume_latency(dev); | 221 | return sprintf(buf, "%d\n", dev_pm_qos_requested_resume_latency(dev)); |
222 | |||
223 | if (value == 0) | ||
224 | return sprintf(buf, "n/a\n"); | ||
225 | else if (value == PM_QOS_RESUME_LATENCY_NO_CONSTRAINT) | ||
226 | value = 0; | ||
227 | |||
228 | return sprintf(buf, "%d\n", value); | ||
229 | } | 222 | } |
230 | 223 | ||
231 | static ssize_t pm_qos_resume_latency_store(struct device *dev, | 224 | static ssize_t pm_qos_resume_latency_store(struct device *dev, |
@@ -235,21 +228,11 @@ static ssize_t pm_qos_resume_latency_store(struct device *dev, | |||
235 | s32 value; | 228 | s32 value; |
236 | int ret; | 229 | int ret; |
237 | 230 | ||
238 | if (!kstrtos32(buf, 0, &value)) { | 231 | if (kstrtos32(buf, 0, &value)) |
239 | /* | 232 | return -EINVAL; |
240 | * Prevent users from writing negative or "no constraint" values | ||
241 | * directly. | ||
242 | */ | ||
243 | if (value < 0 || value == PM_QOS_RESUME_LATENCY_NO_CONSTRAINT) | ||
244 | return -EINVAL; | ||
245 | 233 | ||
246 | if (value == 0) | 234 | if (value < 0) |
247 | value = PM_QOS_RESUME_LATENCY_NO_CONSTRAINT; | ||
248 | } else if (!strcmp(buf, "n/a") || !strcmp(buf, "n/a\n")) { | ||
249 | value = 0; | ||
250 | } else { | ||
251 | return -EINVAL; | 235 | return -EINVAL; |
252 | } | ||
253 | 236 | ||
254 | ret = dev_pm_qos_update_request(dev->power.qos->resume_latency_req, | 237 | ret = dev_pm_qos_update_request(dev->power.qos->resume_latency_req, |
255 | value); | 238 | value); |
diff --git a/drivers/cpuidle/governors/menu.c b/drivers/cpuidle/governors/menu.c index aa390404e85f..48eaf2879228 100644 --- a/drivers/cpuidle/governors/menu.c +++ b/drivers/cpuidle/governors/menu.c | |||
@@ -298,8 +298,8 @@ static int menu_select(struct cpuidle_driver *drv, struct cpuidle_device *dev) | |||
298 | data->needs_update = 0; | 298 | data->needs_update = 0; |
299 | } | 299 | } |
300 | 300 | ||
301 | if (resume_latency < latency_req && | 301 | /* resume_latency is 0 means no restriction */ |
302 | resume_latency != PM_QOS_RESUME_LATENCY_NO_CONSTRAINT) | 302 | if (resume_latency && resume_latency < latency_req) |
303 | latency_req = resume_latency; | 303 | latency_req = resume_latency; |
304 | 304 | ||
305 | /* Special case when user has set very strict latency requirement */ | 305 | /* Special case when user has set very strict latency requirement */ |
diff --git a/include/linux/pm_qos.h b/include/linux/pm_qos.h index 6737a8c9e8c6..032b55909145 100644 --- a/include/linux/pm_qos.h +++ b/include/linux/pm_qos.h | |||
@@ -27,17 +27,16 @@ enum pm_qos_flags_status { | |||
27 | PM_QOS_FLAGS_ALL, | 27 | PM_QOS_FLAGS_ALL, |
28 | }; | 28 | }; |
29 | 29 | ||
30 | #define PM_QOS_DEFAULT_VALUE (-1) | 30 | #define PM_QOS_DEFAULT_VALUE -1 |
31 | #define PM_QOS_LATENCY_ANY S32_MAX | ||
32 | 31 | ||
33 | #define PM_QOS_CPU_DMA_LAT_DEFAULT_VALUE (2000 * USEC_PER_SEC) | 32 | #define PM_QOS_CPU_DMA_LAT_DEFAULT_VALUE (2000 * USEC_PER_SEC) |
34 | #define PM_QOS_NETWORK_LAT_DEFAULT_VALUE (2000 * USEC_PER_SEC) | 33 | #define PM_QOS_NETWORK_LAT_DEFAULT_VALUE (2000 * USEC_PER_SEC) |
35 | #define PM_QOS_NETWORK_THROUGHPUT_DEFAULT_VALUE 0 | 34 | #define PM_QOS_NETWORK_THROUGHPUT_DEFAULT_VALUE 0 |
36 | #define PM_QOS_MEMORY_BANDWIDTH_DEFAULT_VALUE 0 | 35 | #define PM_QOS_MEMORY_BANDWIDTH_DEFAULT_VALUE 0 |
37 | #define PM_QOS_RESUME_LATENCY_DEFAULT_VALUE 0 | 36 | #define PM_QOS_RESUME_LATENCY_DEFAULT_VALUE 0 |
38 | #define PM_QOS_RESUME_LATENCY_NO_CONSTRAINT PM_QOS_LATENCY_ANY | ||
39 | #define PM_QOS_LATENCY_TOLERANCE_DEFAULT_VALUE 0 | 37 | #define PM_QOS_LATENCY_TOLERANCE_DEFAULT_VALUE 0 |
40 | #define PM_QOS_LATENCY_TOLERANCE_NO_CONSTRAINT (-1) | 38 | #define PM_QOS_LATENCY_TOLERANCE_NO_CONSTRAINT (-1) |
39 | #define PM_QOS_LATENCY_ANY ((s32)(~(__u32)0 >> 1)) | ||
41 | 40 | ||
42 | #define PM_QOS_FLAG_NO_POWER_OFF (1 << 0) | 41 | #define PM_QOS_FLAG_NO_POWER_OFF (1 << 0) |
43 | #define PM_QOS_FLAG_REMOTE_WAKEUP (1 << 1) | 42 | #define PM_QOS_FLAG_REMOTE_WAKEUP (1 << 1) |