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

PM / QoS: Fix device resume latency framework

The special value of 0 for device resume latency PM QoS means
"no restriction", but there are two problems with that.

First, device resume latency PM QoS requests with 0 as the
value are always put in front of requests with positive
values in the priority lists used internally by the PM QoS
framework, causing 0 to be chosen as an effective constraint
value. However, that 0 is then interpreted as "no restriction"
effectively overriding the other requests with specific
restrictions which is incorrect.

Second, the users of device resume latency PM QoS have no
way to specify that *any* resume latency at all should be
avoided, which is an artificial limitation in general.

To address these issues, modify device resume latency PM QoS to
use S32_MAX as the "no constraint" value and 0 as the "no
latency at all" one and rework its users (the cpuidle menu
governor, the genpd QoS governor and the runtime PM framework)
to follow these changes.

Also add a special "n/a" value to the corresponding user space I/F
to allow user space to indicate that it cannot accept any resume
latencies at all for the given device.

Fixes: 85dc0b8a4019 (PM / QoS: Make it possible to expose PM QoS latency constraints)
Link: https://bugzilla.kernel.org/show_bug.cgi?id=197323
Reported-by: Reinette Chatre <reinette.chatre@intel.com>
Signed-off-by: Rafael J. Wysocki <rafael.j.wysocki@intel.com>
Tested-by: Reinette Chatre <reinette.chatre@intel.com>
Tested-by: Geert Uytterhoeven <geert+renesas@glider.be>
Tested-by: Tero Kristo <t-kristo@ti.com>
Reviewed-by: Ramesh Thomas <ramesh.thomas@intel.com>

+68 -43
+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 }
+1 -1
drivers/base/power/domain.c
··· 1326 1326 1327 1327 gpd_data->base.dev = dev; 1328 1328 gpd_data->td.constraint_changed = true; 1329 - gpd_data->td.effective_constraint_ns = 0; 1329 + gpd_data->td.effective_constraint_ns = PM_QOS_RESUME_LATENCY_NO_CONSTRAINT_NS; 1330 1330 gpd_data->nb.notifier_call = genpd_dev_pm_qos_notifier; 1331 1331 1332 1332 spin_lock_irq(&dev->power.lock);
+16 -24
drivers/base/power/domain_governor.c
··· 33 33 * known at this point anyway). 34 34 */ 35 35 constraint_ns = dev_pm_qos_read_value(dev); 36 - if (constraint_ns > 0) 37 - constraint_ns *= NSEC_PER_USEC; 36 + constraint_ns *= NSEC_PER_USEC; 38 37 } 39 38 40 - /* 0 means "no constraint" */ 41 - if (constraint_ns == 0) 42 - return 0; 43 - 44 - if (constraint_ns < *constraint_ns_p || *constraint_ns_p == 0) 39 + if (constraint_ns < *constraint_ns_p) 45 40 *constraint_ns_p = constraint_ns; 46 41 47 42 return 0; ··· 64 69 } 65 70 td->constraint_changed = false; 66 71 td->cached_suspend_ok = false; 67 - td->effective_constraint_ns = -1; 72 + td->effective_constraint_ns = 0; 68 73 constraint_ns = __dev_pm_qos_read_value(dev); 69 74 70 75 spin_unlock_irqrestore(&dev->power.lock, flags); 71 76 72 - if (constraint_ns < 0) 77 + if (constraint_ns == 0) 73 78 return false; 74 79 75 80 constraint_ns *= NSEC_PER_USEC; ··· 82 87 device_for_each_child(dev, &constraint_ns, 83 88 dev_update_qos_constraint); 84 89 85 - if (constraint_ns == 0) { 90 + if (constraint_ns == PM_QOS_RESUME_LATENCY_NO_CONSTRAINT_NS) { 86 91 /* "No restriction", so the device is allowed to suspend. */ 87 - td->effective_constraint_ns = 0; 92 + td->effective_constraint_ns = PM_QOS_RESUME_LATENCY_NO_CONSTRAINT_NS; 88 93 td->cached_suspend_ok = true; 89 - } else if (constraint_ns < 0) { 94 + } else if (constraint_ns == 0) { 90 95 /* 91 96 * This triggers if one of the children that don't belong to a 92 - * domain has a negative PM QoS constraint and it's better not 93 - * to suspend then. effective_constraint_ns is negative already 94 - * and cached_suspend_ok is false, so bail out. 97 + * domain has a zero PM QoS constraint and it's better not to 98 + * suspend then. effective_constraint_ns is zero already and 99 + * cached_suspend_ok is false, so bail out. 95 100 */ 96 101 return false; 97 102 } else { 98 103 constraint_ns -= td->suspend_latency_ns + 99 104 td->resume_latency_ns; 100 105 /* 101 - * effective_constraint_ns is negative already and 102 - * cached_suspend_ok is false, so if the computed value is not 103 - * positive, return right away. 106 + * effective_constraint_ns is zero already and cached_suspend_ok 107 + * is false, so if the computed value is not positive, return 108 + * right away. 104 109 */ 105 110 if (constraint_ns <= 0) 106 111 return false; ··· 169 174 td = &to_gpd_data(pdd)->td; 170 175 constraint_ns = td->effective_constraint_ns; 171 176 /* 172 - * Negative values mean "no suspend at all" and this runs only 173 - * when all devices in the domain are suspended, so it must be 174 - * 0 at least. 175 - * 176 - * 0 means "no constraint" 177 + * Zero means "no suspend at all" and this runs only when all 178 + * devices in the domain are suspended, so it must be positive. 177 179 */ 178 - if (constraint_ns == 0) 180 + if (constraint_ns == PM_QOS_RESUME_LATENCY_NO_CONSTRAINT_NS) 179 181 continue; 180 182 181 183 if (constraint_ns <= off_on_time_ns)
+4 -1
drivers/base/power/qos.c
··· 139 139 140 140 switch(req->type) { 141 141 case DEV_PM_QOS_RESUME_LATENCY: 142 + if (WARN_ON(action != PM_QOS_REMOVE_REQ && value < 0)) 143 + value = 0; 144 + 142 145 ret = pm_qos_update_target(&qos->resume_latency, 143 146 &req->data.pnode, action, value); 144 147 break; ··· 192 189 plist_head_init(&c->list); 193 190 c->target_value = PM_QOS_RESUME_LATENCY_DEFAULT_VALUE; 194 191 c->default_value = PM_QOS_RESUME_LATENCY_DEFAULT_VALUE; 195 - c->no_constraint_value = PM_QOS_RESUME_LATENCY_DEFAULT_VALUE; 192 + c->no_constraint_value = PM_QOS_RESUME_LATENCY_NO_CONSTRAINT; 196 193 c->type = PM_QOS_MIN; 197 194 c->notifiers = n; 198 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 */
+18 -8
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 32 + #define PM_QOS_LATENCY_ANY_NS ((s64)PM_QOS_LATENCY_ANY * NSEC_PER_USEC) 31 33 32 34 #define PM_QOS_CPU_DMA_LAT_DEFAULT_VALUE (2000 * USEC_PER_SEC) 33 35 #define PM_QOS_NETWORK_LAT_DEFAULT_VALUE (2000 * USEC_PER_SEC) 34 36 #define PM_QOS_NETWORK_THROUGHPUT_DEFAULT_VALUE 0 35 37 #define PM_QOS_MEMORY_BANDWIDTH_DEFAULT_VALUE 0 36 - #define PM_QOS_RESUME_LATENCY_DEFAULT_VALUE 0 38 + #define PM_QOS_RESUME_LATENCY_DEFAULT_VALUE PM_QOS_LATENCY_ANY 39 + #define PM_QOS_RESUME_LATENCY_NO_CONSTRAINT PM_QOS_LATENCY_ANY 40 + #define PM_QOS_RESUME_LATENCY_NO_CONSTRAINT_NS PM_QOS_LATENCY_ANY_NS 37 41 #define PM_QOS_LATENCY_TOLERANCE_DEFAULT_VALUE 0 38 42 #define PM_QOS_LATENCY_TOLERANCE_NO_CONSTRAINT (-1) 39 - #define PM_QOS_LATENCY_ANY ((s32)(~(__u32)0 >> 1)) 40 43 41 44 #define PM_QOS_FLAG_NO_POWER_OFF (1 << 0) 42 45 ··· 176 173 static inline s32 dev_pm_qos_raw_read_value(struct device *dev) 177 174 { 178 175 return IS_ERR_OR_NULL(dev->power.qos) ? 179 - 0 : pm_qos_read_value(&dev->power.qos->resume_latency); 176 + PM_QOS_RESUME_LATENCY_NO_CONSTRAINT : 177 + pm_qos_read_value(&dev->power.qos->resume_latency); 180 178 } 181 179 #else 182 180 static inline enum pm_qos_flags_status __dev_pm_qos_flags(struct device *dev, ··· 187 183 s32 mask) 188 184 { return PM_QOS_FLAGS_UNDEFINED; } 189 185 static inline s32 __dev_pm_qos_read_value(struct device *dev) 190 - { return 0; } 186 + { return PM_QOS_RESUME_LATENCY_NO_CONSTRAINT; } 191 187 static inline s32 dev_pm_qos_read_value(struct device *dev) 192 - { return 0; } 188 + { return PM_QOS_RESUME_LATENCY_NO_CONSTRAINT; } 193 189 static inline int dev_pm_qos_add_request(struct device *dev, 194 190 struct dev_pm_qos_request *req, 195 191 enum dev_pm_qos_req_type type, ··· 235 231 { return 0; } 236 232 static inline void dev_pm_qos_hide_latency_tolerance(struct device *dev) {} 237 233 238 - static inline s32 dev_pm_qos_requested_resume_latency(struct device *dev) { return 0; } 234 + static inline s32 dev_pm_qos_requested_resume_latency(struct device *dev) 235 + { 236 + return PM_QOS_RESUME_LATENCY_NO_CONSTRAINT; 237 + } 239 238 static inline s32 dev_pm_qos_requested_flags(struct device *dev) { return 0; } 240 - static inline s32 dev_pm_qos_raw_read_value(struct device *dev) { return 0; } 239 + static inline s32 dev_pm_qos_raw_read_value(struct device *dev) 240 + { 241 + return PM_QOS_RESUME_LATENCY_NO_CONSTRAINT; 242 + } 241 243 #endif 242 244 243 245 #endif