Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux
1
fork

Configure Feed

Select the types of activity you want to include in your feed.

Merge tag 'pm-4.14-rc7' of git://git.kernel.org/pub/scm/linux/kernel/git/rafael/linux-pm

Pull power management fix from Rafael Wysocki:
"This fixes a device power management quality of service (PM QoS)
framework implementation issue causing 'no restriction' requests for
device resume latency, including 'no restriction' set by user space,
to effectively override requests with specific device resume latency
requirements.

It is late in the cycle, but the bug in question is in the 'user space
can trigger unexpected behavior' category and the fix is
stable-candidate, so here it goes"

* tag 'pm-4.14-rc7' of git://git.kernel.org/pub/scm/linux/kernel/git/rafael/linux-pm:
PM / QoS: Fix device resume latency PM QoS

+63 -35
+3 -1
Documentation/ABI/testing/sysfs-devices-power
··· 211 211 device, after it has been suspended at run time, from a resume 212 212 request to the moment the device will be ready to process I/O, 213 213 in microseconds. If it is equal to 0, however, this means that 214 - the PM QoS resume latency may be arbitrary. 214 + the PM QoS resume latency may be arbitrary and the special value 215 + "n/a" means that user space cannot accept any resume latency at 216 + all for the given device. 215 217 216 218 Not all drivers support this attribute. If it isn't supported, 217 219 it is not present.
+2 -1
drivers/base/cpu.c
··· 377 377 378 378 per_cpu(cpu_sys_devices, num) = &cpu->dev; 379 379 register_cpu_under_node(num, cpu_to_node(num)); 380 - dev_pm_qos_expose_latency_limit(&cpu->dev, 0); 380 + dev_pm_qos_expose_latency_limit(&cpu->dev, 381 + PM_QOS_RESUME_LATENCY_NO_CONSTRAINT); 381 382 382 383 return 0; 383 384 }
+30 -23
drivers/base/power/domain_governor.c
··· 14 14 static int dev_update_qos_constraint(struct device *dev, void *data) 15 15 { 16 16 s64 *constraint_ns_p = data; 17 - s32 constraint_ns = -1; 17 + s64 constraint_ns = -1; 18 18 19 19 if (dev->power.subsys_data && dev->power.subsys_data->domain_data) 20 20 constraint_ns = dev_gpd_data(dev)->td.effective_constraint_ns; 21 21 22 - if (constraint_ns < 0) { 22 + if (constraint_ns < 0) 23 23 constraint_ns = dev_pm_qos_read_value(dev); 24 - constraint_ns *= NSEC_PER_USEC; 25 - } 26 - if (constraint_ns == 0) 24 + 25 + if (constraint_ns == PM_QOS_RESUME_LATENCY_NO_CONSTRAINT) 27 26 return 0; 28 27 29 - /* 30 - * constraint_ns cannot be negative here, because the device has been 31 - * suspended. 32 - */ 33 - if (constraint_ns < *constraint_ns_p || *constraint_ns_p == 0) 28 + constraint_ns *= NSEC_PER_USEC; 29 + 30 + if (constraint_ns < *constraint_ns_p || *constraint_ns_p < 0) 34 31 *constraint_ns_p = constraint_ns; 35 32 36 33 return 0; ··· 60 63 61 64 spin_unlock_irqrestore(&dev->power.lock, flags); 62 65 63 - if (constraint_ns < 0) 66 + if (constraint_ns == 0) 64 67 return false; 65 68 66 - constraint_ns *= NSEC_PER_USEC; 69 + if (constraint_ns == PM_QOS_RESUME_LATENCY_NO_CONSTRAINT) 70 + constraint_ns = -1; 71 + else 72 + constraint_ns *= NSEC_PER_USEC; 73 + 67 74 /* 68 75 * We can walk the children without any additional locking, because 69 76 * they all have been suspended at this point and their ··· 77 76 device_for_each_child(dev, &constraint_ns, 78 77 dev_update_qos_constraint); 79 78 80 - if (constraint_ns > 0) { 81 - constraint_ns -= td->suspend_latency_ns + 82 - td->resume_latency_ns; 83 - if (constraint_ns == 0) 84 - return false; 79 + if (constraint_ns < 0) { 80 + /* The children have no constraints. */ 81 + td->effective_constraint_ns = PM_QOS_RESUME_LATENCY_NO_CONSTRAINT; 82 + td->cached_suspend_ok = true; 83 + } else { 84 + constraint_ns -= td->suspend_latency_ns + td->resume_latency_ns; 85 + if (constraint_ns > 0) { 86 + td->effective_constraint_ns = constraint_ns; 87 + td->cached_suspend_ok = true; 88 + } else { 89 + td->effective_constraint_ns = 0; 90 + } 85 91 } 86 - td->effective_constraint_ns = constraint_ns; 87 - td->cached_suspend_ok = constraint_ns >= 0; 88 92 89 93 /* 90 94 * The children have been suspended already, so we don't need to take ··· 151 145 td = &to_gpd_data(pdd)->td; 152 146 constraint_ns = td->effective_constraint_ns; 153 147 /* default_suspend_ok() need not be called before us. */ 154 - if (constraint_ns < 0) { 148 + if (constraint_ns < 0) 155 149 constraint_ns = dev_pm_qos_read_value(pdd->dev); 156 - constraint_ns *= NSEC_PER_USEC; 157 - } 158 - if (constraint_ns == 0) 150 + 151 + if (constraint_ns == PM_QOS_RESUME_LATENCY_NO_CONSTRAINT) 159 152 continue; 153 + 154 + constraint_ns *= NSEC_PER_USEC; 160 155 161 156 /* 162 157 * constraint_ns cannot be negative here, because the device has
+1 -1
drivers/base/power/qos.c
··· 189 189 plist_head_init(&c->list); 190 190 c->target_value = PM_QOS_RESUME_LATENCY_DEFAULT_VALUE; 191 191 c->default_value = PM_QOS_RESUME_LATENCY_DEFAULT_VALUE; 192 - c->no_constraint_value = PM_QOS_RESUME_LATENCY_DEFAULT_VALUE; 192 + c->no_constraint_value = PM_QOS_RESUME_LATENCY_NO_CONSTRAINT; 193 193 c->type = PM_QOS_MIN; 194 194 c->notifiers = n; 195 195
+1 -1
drivers/base/power/runtime.c
··· 253 253 || (dev->power.request_pending 254 254 && dev->power.request == RPM_REQ_RESUME)) 255 255 retval = -EAGAIN; 256 - else if (__dev_pm_qos_read_value(dev) < 0) 256 + else if (__dev_pm_qos_read_value(dev) == 0) 257 257 retval = -EPERM; 258 258 else if (dev->power.runtime_status == RPM_SUSPENDED) 259 259 retval = 1;
+21 -4
drivers/base/power/sysfs.c
··· 218 218 struct device_attribute *attr, 219 219 char *buf) 220 220 { 221 - return sprintf(buf, "%d\n", dev_pm_qos_requested_resume_latency(dev)); 221 + s32 value = 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); 222 229 } 223 230 224 231 static ssize_t pm_qos_resume_latency_store(struct device *dev, ··· 235 228 s32 value; 236 229 int ret; 237 230 238 - if (kstrtos32(buf, 0, &value)) 239 - return -EINVAL; 231 + if (!kstrtos32(buf, 0, &value)) { 232 + /* 233 + * Prevent users from writing negative or "no constraint" values 234 + * directly. 235 + */ 236 + if (value < 0 || value == PM_QOS_RESUME_LATENCY_NO_CONSTRAINT) 237 + return -EINVAL; 240 238 241 - if (value < 0) 239 + if (value == 0) 240 + value = PM_QOS_RESUME_LATENCY_NO_CONSTRAINT; 241 + } else if (!strcmp(buf, "n/a") || !strcmp(buf, "n/a\n")) { 242 + value = 0; 243 + } else { 242 244 return -EINVAL; 245 + } 243 246 244 247 ret = dev_pm_qos_update_request(dev->power.qos->resume_latency_req, 245 248 value);
+2 -2
drivers/cpuidle/governors/menu.c
··· 298 298 data->needs_update = 0; 299 299 } 300 300 301 - /* resume_latency is 0 means no restriction */ 302 - if (resume_latency && resume_latency < latency_req) 301 + if (resume_latency < latency_req && 302 + resume_latency != PM_QOS_RESUME_LATENCY_NO_CONSTRAINT) 303 303 latency_req = resume_latency; 304 304 305 305 /* Special case when user has set very strict latency requirement */
+3 -2
include/linux/pm_qos.h
··· 27 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 31 32 32 33 #define PM_QOS_CPU_DMA_LAT_DEFAULT_VALUE (2000 * USEC_PER_SEC) 33 34 #define PM_QOS_NETWORK_LAT_DEFAULT_VALUE (2000 * USEC_PER_SEC) 34 35 #define PM_QOS_NETWORK_THROUGHPUT_DEFAULT_VALUE 0 35 36 #define PM_QOS_MEMORY_BANDWIDTH_DEFAULT_VALUE 0 36 37 #define PM_QOS_RESUME_LATENCY_DEFAULT_VALUE 0 38 + #define PM_QOS_RESUME_LATENCY_NO_CONSTRAINT PM_QOS_LATENCY_ANY 37 39 #define PM_QOS_LATENCY_TOLERANCE_DEFAULT_VALUE 0 38 40 #define PM_QOS_LATENCY_TOLERANCE_NO_CONSTRAINT (-1) 39 - #define PM_QOS_LATENCY_ANY ((s32)(~(__u32)0 >> 1)) 40 41 41 42 #define PM_QOS_FLAG_NO_POWER_OFF (1 << 0) 42 43 #define PM_QOS_FLAG_REMOTE_WAKEUP (1 << 1)