.. | .. |
---|
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 |
---|