| .. | .. |
|---|
| 1 | 1 | /* SPDX-License-Identifier: GPL-2.0 */ |
|---|
| 2 | +/* |
|---|
| 3 | + * Definitions related to Power Management Quality of Service (PM QoS). |
|---|
| 4 | + * |
|---|
| 5 | + * Copyright (C) 2020 Intel Corporation |
|---|
| 6 | + * |
|---|
| 7 | + * Authors: |
|---|
| 8 | + * Mark Gross <mgross@linux.intel.com> |
|---|
| 9 | + * Rafael J. Wysocki <rafael.j.wysocki@intel.com> |
|---|
| 10 | + */ |
|---|
| 11 | + |
|---|
| 2 | 12 | #ifndef _LINUX_PM_QOS_H |
|---|
| 3 | 13 | #define _LINUX_PM_QOS_H |
|---|
| 4 | | -/* interface for the pm_qos_power infrastructure of the linux kernel. |
|---|
| 5 | | - * |
|---|
| 6 | | - * Mark Gross <mgross@linux.intel.com> |
|---|
| 7 | | - */ |
|---|
| 14 | + |
|---|
| 8 | 15 | #include <linux/plist.h> |
|---|
| 9 | 16 | #include <linux/notifier.h> |
|---|
| 10 | 17 | #include <linux/device.h> |
|---|
| 11 | | -#include <linux/workqueue.h> |
|---|
| 12 | | -#include <linux/cpumask.h> |
|---|
| 13 | | -#include <linux/interrupt.h> |
|---|
| 14 | | - |
|---|
| 15 | | -enum { |
|---|
| 16 | | - PM_QOS_RESERVED = 0, |
|---|
| 17 | | - PM_QOS_CPU_DMA_LATENCY, |
|---|
| 18 | | - PM_QOS_NETWORK_LATENCY, |
|---|
| 19 | | - PM_QOS_NETWORK_THROUGHPUT, |
|---|
| 20 | | - PM_QOS_MEMORY_BANDWIDTH, |
|---|
| 21 | | - |
|---|
| 22 | | - /* insert new class ID */ |
|---|
| 23 | | - PM_QOS_NUM_CLASSES, |
|---|
| 24 | | -}; |
|---|
| 25 | 18 | |
|---|
| 26 | 19 | enum pm_qos_flags_status { |
|---|
| 27 | 20 | PM_QOS_FLAGS_UNDEFINED = -1, |
|---|
| .. | .. |
|---|
| 34 | 27 | #define PM_QOS_LATENCY_ANY S32_MAX |
|---|
| 35 | 28 | #define PM_QOS_LATENCY_ANY_NS ((s64)PM_QOS_LATENCY_ANY * NSEC_PER_USEC) |
|---|
| 36 | 29 | |
|---|
| 37 | | -#define PM_QOS_CPU_DMA_LAT_DEFAULT_VALUE (2000 * USEC_PER_SEC) |
|---|
| 38 | | -#define PM_QOS_NETWORK_LAT_DEFAULT_VALUE (2000 * USEC_PER_SEC) |
|---|
| 39 | | -#define PM_QOS_NETWORK_THROUGHPUT_DEFAULT_VALUE 0 |
|---|
| 40 | | -#define PM_QOS_MEMORY_BANDWIDTH_DEFAULT_VALUE 0 |
|---|
| 30 | +#define PM_QOS_CPU_LATENCY_DEFAULT_VALUE (2000 * USEC_PER_SEC) |
|---|
| 41 | 31 | #define PM_QOS_RESUME_LATENCY_DEFAULT_VALUE PM_QOS_LATENCY_ANY |
|---|
| 42 | 32 | #define PM_QOS_RESUME_LATENCY_NO_CONSTRAINT PM_QOS_LATENCY_ANY |
|---|
| 43 | 33 | #define PM_QOS_RESUME_LATENCY_NO_CONSTRAINT_NS PM_QOS_LATENCY_ANY_NS |
|---|
| 44 | 34 | #define PM_QOS_LATENCY_TOLERANCE_DEFAULT_VALUE 0 |
|---|
| 35 | +#define PM_QOS_MIN_FREQUENCY_DEFAULT_VALUE 0 |
|---|
| 36 | +#define PM_QOS_MAX_FREQUENCY_DEFAULT_VALUE FREQ_QOS_MAX_DEFAULT_VALUE |
|---|
| 45 | 37 | #define PM_QOS_LATENCY_TOLERANCE_NO_CONSTRAINT (-1) |
|---|
| 46 | 38 | |
|---|
| 47 | 39 | #define PM_QOS_FLAG_NO_POWER_OFF (1 << 0) |
|---|
| 48 | | - |
|---|
| 49 | | -enum pm_qos_req_type { |
|---|
| 50 | | - PM_QOS_REQ_ALL_CORES = 0, |
|---|
| 51 | | - PM_QOS_REQ_AFFINE_CORES, |
|---|
| 52 | | -#ifdef CONFIG_SMP |
|---|
| 53 | | - PM_QOS_REQ_AFFINE_IRQ, |
|---|
| 54 | | -#endif |
|---|
| 55 | | -}; |
|---|
| 56 | | - |
|---|
| 57 | | -struct pm_qos_request { |
|---|
| 58 | | - enum pm_qos_req_type type; |
|---|
| 59 | | - struct cpumask cpus_affine; |
|---|
| 60 | | -#ifdef CONFIG_SMP |
|---|
| 61 | | - uint32_t irq; |
|---|
| 62 | | - /* Internal structure members */ |
|---|
| 63 | | - struct irq_affinity_notify irq_notify; |
|---|
| 64 | | -#endif |
|---|
| 65 | | - struct plist_node node; |
|---|
| 66 | | - int pm_qos_class; |
|---|
| 67 | | - struct delayed_work work; /* for pm_qos_update_request_timeout */ |
|---|
| 68 | | -}; |
|---|
| 69 | | - |
|---|
| 70 | | -struct pm_qos_flags_request { |
|---|
| 71 | | - struct list_head node; |
|---|
| 72 | | - s32 flags; /* Do not change to 64 bit */ |
|---|
| 73 | | -}; |
|---|
| 74 | | - |
|---|
| 75 | | -enum dev_pm_qos_req_type { |
|---|
| 76 | | - DEV_PM_QOS_RESUME_LATENCY = 1, |
|---|
| 77 | | - DEV_PM_QOS_LATENCY_TOLERANCE, |
|---|
| 78 | | - DEV_PM_QOS_FLAGS, |
|---|
| 79 | | -}; |
|---|
| 80 | | - |
|---|
| 81 | | -struct dev_pm_qos_request { |
|---|
| 82 | | - enum dev_pm_qos_req_type type; |
|---|
| 83 | | - union { |
|---|
| 84 | | - struct plist_node pnode; |
|---|
| 85 | | - struct pm_qos_flags_request flr; |
|---|
| 86 | | - } data; |
|---|
| 87 | | - struct device *dev; |
|---|
| 88 | | -}; |
|---|
| 89 | 40 | |
|---|
| 90 | 41 | enum pm_qos_type { |
|---|
| 91 | 42 | PM_QOS_UNITIALIZED, |
|---|
| 92 | 43 | PM_QOS_MAX, /* return the largest value */ |
|---|
| 93 | 44 | PM_QOS_MIN, /* return the smallest value */ |
|---|
| 94 | | - PM_QOS_SUM /* return the sum */ |
|---|
| 95 | 45 | }; |
|---|
| 96 | 46 | |
|---|
| 97 | 47 | /* |
|---|
| .. | .. |
|---|
| 102 | 52 | struct pm_qos_constraints { |
|---|
| 103 | 53 | struct plist_head list; |
|---|
| 104 | 54 | s32 target_value; /* Do not change to 64 bit */ |
|---|
| 105 | | - s32 target_per_cpu[NR_CPUS]; |
|---|
| 106 | 55 | s32 default_value; |
|---|
| 107 | 56 | s32 no_constraint_value; |
|---|
| 108 | 57 | enum pm_qos_type type; |
|---|
| 109 | 58 | struct blocking_notifier_head *notifiers; |
|---|
| 59 | +}; |
|---|
| 60 | + |
|---|
| 61 | +struct pm_qos_request { |
|---|
| 62 | + struct plist_node node; |
|---|
| 63 | + struct pm_qos_constraints *qos; |
|---|
| 64 | +}; |
|---|
| 65 | + |
|---|
| 66 | +struct pm_qos_flags_request { |
|---|
| 67 | + struct list_head node; |
|---|
| 68 | + s32 flags; /* Do not change to 64 bit */ |
|---|
| 110 | 69 | }; |
|---|
| 111 | 70 | |
|---|
| 112 | 71 | struct pm_qos_flags { |
|---|
| .. | .. |
|---|
| 114 | 73 | s32 effective_flags; /* Do not change to 64 bit */ |
|---|
| 115 | 74 | }; |
|---|
| 116 | 75 | |
|---|
| 76 | + |
|---|
| 77 | +#define FREQ_QOS_MIN_DEFAULT_VALUE 0 |
|---|
| 78 | +#define FREQ_QOS_MAX_DEFAULT_VALUE S32_MAX |
|---|
| 79 | + |
|---|
| 80 | +enum freq_qos_req_type { |
|---|
| 81 | + FREQ_QOS_MIN = 1, |
|---|
| 82 | + FREQ_QOS_MAX, |
|---|
| 83 | +}; |
|---|
| 84 | + |
|---|
| 85 | +struct freq_constraints { |
|---|
| 86 | + struct pm_qos_constraints min_freq; |
|---|
| 87 | + struct blocking_notifier_head min_freq_notifiers; |
|---|
| 88 | + struct pm_qos_constraints max_freq; |
|---|
| 89 | + struct blocking_notifier_head max_freq_notifiers; |
|---|
| 90 | +}; |
|---|
| 91 | + |
|---|
| 92 | +struct freq_qos_request { |
|---|
| 93 | + enum freq_qos_req_type type; |
|---|
| 94 | + struct plist_node pnode; |
|---|
| 95 | + struct freq_constraints *qos; |
|---|
| 96 | + ANDROID_OEM_DATA_ARRAY(1, 2); |
|---|
| 97 | +}; |
|---|
| 98 | + |
|---|
| 99 | + |
|---|
| 100 | +enum dev_pm_qos_req_type { |
|---|
| 101 | + DEV_PM_QOS_RESUME_LATENCY = 1, |
|---|
| 102 | + DEV_PM_QOS_LATENCY_TOLERANCE, |
|---|
| 103 | + DEV_PM_QOS_MIN_FREQUENCY, |
|---|
| 104 | + DEV_PM_QOS_MAX_FREQUENCY, |
|---|
| 105 | + DEV_PM_QOS_FLAGS, |
|---|
| 106 | +}; |
|---|
| 107 | + |
|---|
| 108 | +struct dev_pm_qos_request { |
|---|
| 109 | + enum dev_pm_qos_req_type type; |
|---|
| 110 | + union { |
|---|
| 111 | + struct plist_node pnode; |
|---|
| 112 | + struct pm_qos_flags_request flr; |
|---|
| 113 | + struct freq_qos_request freq; |
|---|
| 114 | + } data; |
|---|
| 115 | + struct device *dev; |
|---|
| 116 | +}; |
|---|
| 117 | + |
|---|
| 117 | 118 | struct dev_pm_qos { |
|---|
| 118 | 119 | struct pm_qos_constraints resume_latency; |
|---|
| 119 | 120 | struct pm_qos_constraints latency_tolerance; |
|---|
| 121 | + struct freq_constraints freq; |
|---|
| 120 | 122 | struct pm_qos_flags flags; |
|---|
| 121 | 123 | struct dev_pm_qos_request *resume_latency_req; |
|---|
| 122 | 124 | struct dev_pm_qos_request *latency_tolerance_req; |
|---|
| .. | .. |
|---|
| 135 | 137 | return req->dev != NULL; |
|---|
| 136 | 138 | } |
|---|
| 137 | 139 | |
|---|
| 140 | +s32 pm_qos_read_value(struct pm_qos_constraints *c); |
|---|
| 138 | 141 | int pm_qos_update_target(struct pm_qos_constraints *c, struct plist_node *node, |
|---|
| 139 | | - enum pm_qos_req_action action, int value, |
|---|
| 140 | | - bool dev_req); |
|---|
| 142 | + enum pm_qos_req_action action, int value); |
|---|
| 141 | 143 | bool pm_qos_update_flags(struct pm_qos_flags *pqf, |
|---|
| 142 | 144 | struct pm_qos_flags_request *req, |
|---|
| 143 | 145 | enum pm_qos_req_action action, s32 val); |
|---|
| 144 | | -void pm_qos_add_request(struct pm_qos_request *req, int pm_qos_class, |
|---|
| 145 | | - s32 value); |
|---|
| 146 | | -void pm_qos_update_request(struct pm_qos_request *req, |
|---|
| 147 | | - s32 new_value); |
|---|
| 148 | | -void pm_qos_update_request_timeout(struct pm_qos_request *req, |
|---|
| 149 | | - s32 new_value, unsigned long timeout_us); |
|---|
| 150 | | -void pm_qos_remove_request(struct pm_qos_request *req); |
|---|
| 151 | 146 | |
|---|
| 152 | | -int pm_qos_request(int pm_qos_class); |
|---|
| 153 | | -int pm_qos_request_for_cpu(int pm_qos_class, int cpu); |
|---|
| 154 | | -int pm_qos_request_for_cpumask(int pm_qos_class, struct cpumask *mask); |
|---|
| 155 | | -int pm_qos_add_notifier(int pm_qos_class, struct notifier_block *notifier); |
|---|
| 156 | | -int pm_qos_remove_notifier(int pm_qos_class, struct notifier_block *notifier); |
|---|
| 157 | | -int pm_qos_request_active(struct pm_qos_request *req); |
|---|
| 158 | | -s32 pm_qos_read_value(struct pm_qos_constraints *c); |
|---|
| 147 | +#ifdef CONFIG_CPU_IDLE |
|---|
| 148 | +s32 cpu_latency_qos_limit(void); |
|---|
| 149 | +bool cpu_latency_qos_request_active(struct pm_qos_request *req); |
|---|
| 150 | +void cpu_latency_qos_add_request(struct pm_qos_request *req, s32 value); |
|---|
| 151 | +void cpu_latency_qos_update_request(struct pm_qos_request *req, s32 new_value); |
|---|
| 152 | +void cpu_latency_qos_remove_request(struct pm_qos_request *req); |
|---|
| 153 | +#else |
|---|
| 154 | +static inline s32 cpu_latency_qos_limit(void) { return INT_MAX; } |
|---|
| 155 | +static inline bool cpu_latency_qos_request_active(struct pm_qos_request *req) |
|---|
| 156 | +{ |
|---|
| 157 | + return false; |
|---|
| 158 | +} |
|---|
| 159 | +static inline void cpu_latency_qos_add_request(struct pm_qos_request *req, |
|---|
| 160 | + s32 value) {} |
|---|
| 161 | +static inline void cpu_latency_qos_update_request(struct pm_qos_request *req, |
|---|
| 162 | + s32 new_value) {} |
|---|
| 163 | +static inline void cpu_latency_qos_remove_request(struct pm_qos_request *req) {} |
|---|
| 164 | +#endif |
|---|
| 159 | 165 | |
|---|
| 160 | 166 | #ifdef CONFIG_PM |
|---|
| 161 | 167 | enum pm_qos_flags_status __dev_pm_qos_flags(struct device *dev, s32 mask); |
|---|
| 162 | 168 | enum pm_qos_flags_status dev_pm_qos_flags(struct device *dev, s32 mask); |
|---|
| 163 | | -s32 __dev_pm_qos_read_value(struct device *dev); |
|---|
| 164 | | -s32 dev_pm_qos_read_value(struct device *dev); |
|---|
| 169 | +s32 __dev_pm_qos_resume_latency(struct device *dev); |
|---|
| 170 | +s32 dev_pm_qos_read_value(struct device *dev, enum dev_pm_qos_req_type type); |
|---|
| 165 | 171 | int dev_pm_qos_add_request(struct device *dev, struct dev_pm_qos_request *req, |
|---|
| 166 | 172 | enum dev_pm_qos_req_type type, s32 value); |
|---|
| 167 | 173 | int dev_pm_qos_update_request(struct dev_pm_qos_request *req, s32 new_value); |
|---|
| 168 | 174 | int dev_pm_qos_remove_request(struct dev_pm_qos_request *req); |
|---|
| 169 | 175 | int dev_pm_qos_add_notifier(struct device *dev, |
|---|
| 170 | | - struct notifier_block *notifier); |
|---|
| 176 | + struct notifier_block *notifier, |
|---|
| 177 | + enum dev_pm_qos_req_type type); |
|---|
| 171 | 178 | int dev_pm_qos_remove_notifier(struct device *dev, |
|---|
| 172 | | - struct notifier_block *notifier); |
|---|
| 179 | + struct notifier_block *notifier, |
|---|
| 180 | + enum dev_pm_qos_req_type type); |
|---|
| 173 | 181 | void dev_pm_qos_constraints_init(struct device *dev); |
|---|
| 174 | 182 | void dev_pm_qos_constraints_destroy(struct device *dev); |
|---|
| 175 | 183 | int dev_pm_qos_add_ancestor_request(struct device *dev, |
|---|
| .. | .. |
|---|
| 195 | 203 | return dev->power.qos->flags_req->data.flr.flags; |
|---|
| 196 | 204 | } |
|---|
| 197 | 205 | |
|---|
| 198 | | -static inline s32 dev_pm_qos_raw_read_value(struct device *dev) |
|---|
| 206 | +static inline s32 dev_pm_qos_raw_resume_latency(struct device *dev) |
|---|
| 199 | 207 | { |
|---|
| 200 | 208 | return IS_ERR_OR_NULL(dev->power.qos) ? |
|---|
| 201 | 209 | PM_QOS_RESUME_LATENCY_NO_CONSTRAINT : |
|---|
| .. | .. |
|---|
| 208 | 216 | static inline enum pm_qos_flags_status dev_pm_qos_flags(struct device *dev, |
|---|
| 209 | 217 | s32 mask) |
|---|
| 210 | 218 | { return PM_QOS_FLAGS_UNDEFINED; } |
|---|
| 211 | | -static inline s32 __dev_pm_qos_read_value(struct device *dev) |
|---|
| 219 | +static inline s32 __dev_pm_qos_resume_latency(struct device *dev) |
|---|
| 212 | 220 | { return PM_QOS_RESUME_LATENCY_NO_CONSTRAINT; } |
|---|
| 213 | | -static inline s32 dev_pm_qos_read_value(struct device *dev) |
|---|
| 214 | | - { return PM_QOS_RESUME_LATENCY_NO_CONSTRAINT; } |
|---|
| 221 | +static inline s32 dev_pm_qos_read_value(struct device *dev, |
|---|
| 222 | + enum dev_pm_qos_req_type type) |
|---|
| 223 | +{ |
|---|
| 224 | + switch (type) { |
|---|
| 225 | + case DEV_PM_QOS_RESUME_LATENCY: |
|---|
| 226 | + return PM_QOS_RESUME_LATENCY_NO_CONSTRAINT; |
|---|
| 227 | + case DEV_PM_QOS_MIN_FREQUENCY: |
|---|
| 228 | + return PM_QOS_MIN_FREQUENCY_DEFAULT_VALUE; |
|---|
| 229 | + case DEV_PM_QOS_MAX_FREQUENCY: |
|---|
| 230 | + return PM_QOS_MAX_FREQUENCY_DEFAULT_VALUE; |
|---|
| 231 | + default: |
|---|
| 232 | + WARN_ON(1); |
|---|
| 233 | + return 0; |
|---|
| 234 | + } |
|---|
| 235 | +} |
|---|
| 236 | + |
|---|
| 215 | 237 | static inline int dev_pm_qos_add_request(struct device *dev, |
|---|
| 216 | 238 | struct dev_pm_qos_request *req, |
|---|
| 217 | 239 | enum dev_pm_qos_req_type type, |
|---|
| .. | .. |
|---|
| 223 | 245 | static inline int dev_pm_qos_remove_request(struct dev_pm_qos_request *req) |
|---|
| 224 | 246 | { return 0; } |
|---|
| 225 | 247 | static inline int dev_pm_qos_add_notifier(struct device *dev, |
|---|
| 226 | | - struct notifier_block *notifier) |
|---|
| 248 | + struct notifier_block *notifier, |
|---|
| 249 | + enum dev_pm_qos_req_type type) |
|---|
| 227 | 250 | { return 0; } |
|---|
| 228 | 251 | static inline int dev_pm_qos_remove_notifier(struct device *dev, |
|---|
| 229 | | - struct notifier_block *notifier) |
|---|
| 252 | + struct notifier_block *notifier, |
|---|
| 253 | + enum dev_pm_qos_req_type type) |
|---|
| 230 | 254 | { return 0; } |
|---|
| 231 | 255 | static inline void dev_pm_qos_constraints_init(struct device *dev) |
|---|
| 232 | 256 | { |
|---|
| .. | .. |
|---|
| 262 | 286 | return PM_QOS_RESUME_LATENCY_NO_CONSTRAINT; |
|---|
| 263 | 287 | } |
|---|
| 264 | 288 | static inline s32 dev_pm_qos_requested_flags(struct device *dev) { return 0; } |
|---|
| 265 | | -static inline s32 dev_pm_qos_raw_read_value(struct device *dev) |
|---|
| 289 | +static inline s32 dev_pm_qos_raw_resume_latency(struct device *dev) |
|---|
| 266 | 290 | { |
|---|
| 267 | 291 | return PM_QOS_RESUME_LATENCY_NO_CONSTRAINT; |
|---|
| 268 | 292 | } |
|---|
| 269 | 293 | #endif |
|---|
| 270 | 294 | |
|---|
| 295 | +static inline int freq_qos_request_active(struct freq_qos_request *req) |
|---|
| 296 | +{ |
|---|
| 297 | + return !IS_ERR_OR_NULL(req->qos); |
|---|
| 298 | +} |
|---|
| 299 | + |
|---|
| 300 | +void freq_constraints_init(struct freq_constraints *qos); |
|---|
| 301 | + |
|---|
| 302 | +s32 freq_qos_read_value(struct freq_constraints *qos, |
|---|
| 303 | + enum freq_qos_req_type type); |
|---|
| 304 | + |
|---|
| 305 | +int freq_qos_add_request(struct freq_constraints *qos, |
|---|
| 306 | + struct freq_qos_request *req, |
|---|
| 307 | + enum freq_qos_req_type type, s32 value); |
|---|
| 308 | +int freq_qos_update_request(struct freq_qos_request *req, s32 new_value); |
|---|
| 309 | +int freq_qos_remove_request(struct freq_qos_request *req); |
|---|
| 310 | +int freq_qos_apply(struct freq_qos_request *req, |
|---|
| 311 | + enum pm_qos_req_action action, s32 value); |
|---|
| 312 | + |
|---|
| 313 | +int freq_qos_add_notifier(struct freq_constraints *qos, |
|---|
| 314 | + enum freq_qos_req_type type, |
|---|
| 315 | + struct notifier_block *notifier); |
|---|
| 316 | +int freq_qos_remove_notifier(struct freq_constraints *qos, |
|---|
| 317 | + enum freq_qos_req_type type, |
|---|
| 318 | + struct notifier_block *notifier); |
|---|
| 319 | + |
|---|
| 271 | 320 | #endif |
|---|