• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 // SPDX-License-Identifier: GPL-2.0-only
2 /*
3  * Power Management Quality of Service (PM QoS) support base.
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  * Provided here is an interface for specifying PM QoS dependencies.  It allows
12  * entities depending on QoS constraints to register their requests which are
13  * aggregated as appropriate to produce effective constraints (target values)
14  * that can be monitored by entities needing to respect them, either by polling
15  * or through a built-in notification mechanism.
16  *
17  * In addition to the basic functionality, more specific interfaces for managing
18  * global CPU latency QoS requests and frequency QoS requests are provided.
19  */
20 
21 /*#define DEBUG*/
22 
23 #include <linux/pm_qos.h>
24 #include <linux/sched.h>
25 #include <linux/spinlock.h>
26 #include <linux/slab.h>
27 #include <linux/time.h>
28 #include <linux/fs.h>
29 #include <linux/device.h>
30 #include <linux/miscdevice.h>
31 #include <linux/string.h>
32 #include <linux/platform_device.h>
33 #include <linux/init.h>
34 #include <linux/kernel.h>
35 #include <linux/debugfs.h>
36 #include <linux/seq_file.h>
37 
38 #include <linux/uaccess.h>
39 #include <linux/export.h>
40 #include <trace/events/power.h>
41 #include <trace/hooks/power.h>
42 
43 /*
44  * locking rule: all changes to constraints or notifiers lists
45  * or pm_qos_object list and pm_qos_objects need to happen with pm_qos_lock
46  * held, taken with _irqsave.  One lock to rule them all
47  */
48 static DEFINE_SPINLOCK(pm_qos_lock);
49 
50 /**
51  * pm_qos_read_value - Return the current effective constraint value.
52  * @c: List of PM QoS constraint requests.
53  */
pm_qos_read_value(struct pm_qos_constraints * c)54 s32 pm_qos_read_value(struct pm_qos_constraints *c)
55 {
56 	return READ_ONCE(c->target_value);
57 }
58 
pm_qos_get_value(struct pm_qos_constraints * c)59 static int pm_qos_get_value(struct pm_qos_constraints *c)
60 {
61 	if (plist_head_empty(&c->list))
62 		return c->no_constraint_value;
63 
64 	switch (c->type) {
65 	case PM_QOS_MIN:
66 		return plist_first(&c->list)->prio;
67 
68 	case PM_QOS_MAX:
69 		return plist_last(&c->list)->prio;
70 
71 	default:
72 		WARN(1, "Unknown PM QoS type in %s\n", __func__);
73 		return PM_QOS_DEFAULT_VALUE;
74 	}
75 }
76 
pm_qos_set_value(struct pm_qos_constraints * c,s32 value)77 static void pm_qos_set_value(struct pm_qos_constraints *c, s32 value)
78 {
79 	WRITE_ONCE(c->target_value, value);
80 }
81 
82 /**
83  * pm_qos_update_target - Update a list of PM QoS constraint requests.
84  * @c: List of PM QoS requests.
85  * @node: Target list entry.
86  * @action: Action to carry out (add, update or remove).
87  * @value: New request value for the target list entry.
88  *
89  * Update the given list of PM QoS constraint requests, @c, by carrying an
90  * @action involving the @node list entry and @value on it.
91  *
92  * The recognized values of @action are PM_QOS_ADD_REQ (store @value in @node
93  * and add it to the list), PM_QOS_UPDATE_REQ (remove @node from the list, store
94  * @value in it and add it to the list again), and PM_QOS_REMOVE_REQ (remove
95  * @node from the list, ignore @value).
96  *
97  * Return: 1 if the aggregate constraint value has changed, 0  otherwise.
98  */
pm_qos_update_target(struct pm_qos_constraints * c,struct plist_node * node,enum pm_qos_req_action action,int value)99 int pm_qos_update_target(struct pm_qos_constraints *c, struct plist_node *node,
100 			 enum pm_qos_req_action action, int value)
101 {
102 	int prev_value, curr_value, new_value;
103 	unsigned long flags;
104 
105 	spin_lock_irqsave(&pm_qos_lock, flags);
106 
107 	prev_value = pm_qos_get_value(c);
108 	if (value == PM_QOS_DEFAULT_VALUE)
109 		new_value = c->default_value;
110 	else
111 		new_value = value;
112 
113 	switch (action) {
114 	case PM_QOS_REMOVE_REQ:
115 		plist_del(node, &c->list);
116 		break;
117 	case PM_QOS_UPDATE_REQ:
118 		/*
119 		 * To change the list, atomically remove, reinit with new value
120 		 * and add, then see if the aggregate has changed.
121 		 */
122 		plist_del(node, &c->list);
123 		fallthrough;
124 	case PM_QOS_ADD_REQ:
125 		plist_node_init(node, new_value);
126 		plist_add(node, &c->list);
127 		break;
128 	default:
129 		/* no action */
130 		;
131 	}
132 
133 	curr_value = pm_qos_get_value(c);
134 	pm_qos_set_value(c, curr_value);
135 
136 	spin_unlock_irqrestore(&pm_qos_lock, flags);
137 
138 	trace_pm_qos_update_target(action, prev_value, curr_value);
139 
140 	if (prev_value == curr_value)
141 		return 0;
142 
143 	if (c->notifiers)
144 		blocking_notifier_call_chain(c->notifiers, curr_value, NULL);
145 
146 	return 1;
147 }
148 
149 /**
150  * pm_qos_flags_remove_req - Remove device PM QoS flags request.
151  * @pqf: Device PM QoS flags set to remove the request from.
152  * @req: Request to remove from the set.
153  */
pm_qos_flags_remove_req(struct pm_qos_flags * pqf,struct pm_qos_flags_request * req)154 static void pm_qos_flags_remove_req(struct pm_qos_flags *pqf,
155 				    struct pm_qos_flags_request *req)
156 {
157 	s32 val = 0;
158 
159 	list_del(&req->node);
160 	list_for_each_entry(req, &pqf->list, node)
161 		val |= req->flags;
162 
163 	pqf->effective_flags = val;
164 }
165 
166 /**
167  * pm_qos_update_flags - Update a set of PM QoS flags.
168  * @pqf: Set of PM QoS flags to update.
169  * @req: Request to add to the set, to modify, or to remove from the set.
170  * @action: Action to take on the set.
171  * @val: Value of the request to add or modify.
172  *
173  * Return: 1 if the aggregate constraint value has changed, 0 otherwise.
174  */
pm_qos_update_flags(struct pm_qos_flags * pqf,struct pm_qos_flags_request * req,enum pm_qos_req_action action,s32 val)175 bool pm_qos_update_flags(struct pm_qos_flags *pqf,
176 			 struct pm_qos_flags_request *req,
177 			 enum pm_qos_req_action action, s32 val)
178 {
179 	unsigned long irqflags;
180 	s32 prev_value, curr_value;
181 
182 	spin_lock_irqsave(&pm_qos_lock, irqflags);
183 
184 	prev_value = list_empty(&pqf->list) ? 0 : pqf->effective_flags;
185 
186 	switch (action) {
187 	case PM_QOS_REMOVE_REQ:
188 		pm_qos_flags_remove_req(pqf, req);
189 		break;
190 	case PM_QOS_UPDATE_REQ:
191 		pm_qos_flags_remove_req(pqf, req);
192 		fallthrough;
193 	case PM_QOS_ADD_REQ:
194 		req->flags = val;
195 		INIT_LIST_HEAD(&req->node);
196 		list_add_tail(&req->node, &pqf->list);
197 		pqf->effective_flags |= val;
198 		break;
199 	default:
200 		/* no action */
201 		;
202 	}
203 
204 	curr_value = list_empty(&pqf->list) ? 0 : pqf->effective_flags;
205 
206 	spin_unlock_irqrestore(&pm_qos_lock, irqflags);
207 
208 	trace_pm_qos_update_flags(action, prev_value, curr_value);
209 
210 	return prev_value != curr_value;
211 }
212 
213 #ifdef CONFIG_CPU_IDLE
214 /* Definitions related to the CPU latency QoS. */
215 
216 static struct pm_qos_constraints cpu_latency_constraints = {
217 	.list = PLIST_HEAD_INIT(cpu_latency_constraints.list),
218 	.target_value = PM_QOS_CPU_LATENCY_DEFAULT_VALUE,
219 	.default_value = PM_QOS_CPU_LATENCY_DEFAULT_VALUE,
220 	.no_constraint_value = PM_QOS_CPU_LATENCY_DEFAULT_VALUE,
221 	.type = PM_QOS_MIN,
222 };
223 
224 /**
225  * cpu_latency_qos_limit - Return current system-wide CPU latency QoS limit.
226  */
cpu_latency_qos_limit(void)227 s32 cpu_latency_qos_limit(void)
228 {
229 	return pm_qos_read_value(&cpu_latency_constraints);
230 }
231 
232 /**
233  * cpu_latency_qos_request_active - Check the given PM QoS request.
234  * @req: PM QoS request to check.
235  *
236  * Return: 'true' if @req has been added to the CPU latency QoS list, 'false'
237  * otherwise.
238  */
cpu_latency_qos_request_active(struct pm_qos_request * req)239 bool cpu_latency_qos_request_active(struct pm_qos_request *req)
240 {
241 	return req->qos == &cpu_latency_constraints;
242 }
243 EXPORT_SYMBOL_GPL(cpu_latency_qos_request_active);
244 
cpu_latency_qos_apply(struct pm_qos_request * req,enum pm_qos_req_action action,s32 value)245 static void cpu_latency_qos_apply(struct pm_qos_request *req,
246 				  enum pm_qos_req_action action, s32 value)
247 {
248 	int ret = pm_qos_update_target(req->qos, &req->node, action, value);
249 	if (ret > 0)
250 		wake_up_all_idle_cpus();
251 }
252 
253 /**
254  * cpu_latency_qos_add_request - Add new CPU latency QoS request.
255  * @req: Pointer to a preallocated handle.
256  * @value: Requested constraint value.
257  *
258  * Use @value to initialize the request handle pointed to by @req, insert it as
259  * a new entry to the CPU latency QoS list and recompute the effective QoS
260  * constraint for that list.
261  *
262  * Callers need to save the handle for later use in updates and removal of the
263  * QoS request represented by it.
264  */
cpu_latency_qos_add_request(struct pm_qos_request * req,s32 value)265 void cpu_latency_qos_add_request(struct pm_qos_request *req, s32 value)
266 {
267 	if (!req)
268 		return;
269 
270 	if (cpu_latency_qos_request_active(req)) {
271 		WARN(1, KERN_ERR "%s called for already added request\n", __func__);
272 		return;
273 	}
274 
275 	trace_pm_qos_add_request(value);
276 
277 	req->qos = &cpu_latency_constraints;
278 	cpu_latency_qos_apply(req, PM_QOS_ADD_REQ, value);
279 }
280 EXPORT_SYMBOL_GPL(cpu_latency_qos_add_request);
281 
282 /**
283  * cpu_latency_qos_update_request - Modify existing CPU latency QoS request.
284  * @req : QoS request to update.
285  * @new_value: New requested constraint value.
286  *
287  * Use @new_value to update the QoS request represented by @req in the CPU
288  * latency QoS list along with updating the effective constraint value for that
289  * list.
290  */
cpu_latency_qos_update_request(struct pm_qos_request * req,s32 new_value)291 void cpu_latency_qos_update_request(struct pm_qos_request *req, s32 new_value)
292 {
293 	if (!req)
294 		return;
295 
296 	if (!cpu_latency_qos_request_active(req)) {
297 		WARN(1, KERN_ERR "%s called for unknown object\n", __func__);
298 		return;
299 	}
300 
301 	trace_pm_qos_update_request(new_value);
302 
303 	if (new_value == req->node.prio)
304 		return;
305 
306 	cpu_latency_qos_apply(req, PM_QOS_UPDATE_REQ, new_value);
307 }
308 EXPORT_SYMBOL_GPL(cpu_latency_qos_update_request);
309 
310 /**
311  * cpu_latency_qos_remove_request - Remove existing CPU latency QoS request.
312  * @req: QoS request to remove.
313  *
314  * Remove the CPU latency QoS request represented by @req from the CPU latency
315  * QoS list along with updating the effective constraint value for that list.
316  */
cpu_latency_qos_remove_request(struct pm_qos_request * req)317 void cpu_latency_qos_remove_request(struct pm_qos_request *req)
318 {
319 	if (!req)
320 		return;
321 
322 	if (!cpu_latency_qos_request_active(req)) {
323 		WARN(1, KERN_ERR "%s called for unknown object\n", __func__);
324 		return;
325 	}
326 
327 	trace_pm_qos_remove_request(PM_QOS_DEFAULT_VALUE);
328 
329 	cpu_latency_qos_apply(req, PM_QOS_REMOVE_REQ, PM_QOS_DEFAULT_VALUE);
330 	memset(req, 0, sizeof(*req));
331 }
332 EXPORT_SYMBOL_GPL(cpu_latency_qos_remove_request);
333 
334 /* User space interface to the CPU latency QoS via misc device. */
335 
cpu_latency_qos_open(struct inode * inode,struct file * filp)336 static int cpu_latency_qos_open(struct inode *inode, struct file *filp)
337 {
338 	struct pm_qos_request *req;
339 
340 	req = kzalloc(sizeof(*req), GFP_KERNEL);
341 	if (!req)
342 		return -ENOMEM;
343 
344 	cpu_latency_qos_add_request(req, PM_QOS_DEFAULT_VALUE);
345 	filp->private_data = req;
346 
347 	return 0;
348 }
349 
cpu_latency_qos_release(struct inode * inode,struct file * filp)350 static int cpu_latency_qos_release(struct inode *inode, struct file *filp)
351 {
352 	struct pm_qos_request *req = filp->private_data;
353 
354 	filp->private_data = NULL;
355 
356 	cpu_latency_qos_remove_request(req);
357 	kfree(req);
358 
359 	return 0;
360 }
361 
cpu_latency_qos_read(struct file * filp,char __user * buf,size_t count,loff_t * f_pos)362 static ssize_t cpu_latency_qos_read(struct file *filp, char __user *buf,
363 				    size_t count, loff_t *f_pos)
364 {
365 	struct pm_qos_request *req = filp->private_data;
366 	unsigned long flags;
367 	s32 value;
368 
369 	if (!req || !cpu_latency_qos_request_active(req))
370 		return -EINVAL;
371 
372 	spin_lock_irqsave(&pm_qos_lock, flags);
373 	value = pm_qos_get_value(&cpu_latency_constraints);
374 	spin_unlock_irqrestore(&pm_qos_lock, flags);
375 
376 	return simple_read_from_buffer(buf, count, f_pos, &value, sizeof(s32));
377 }
378 
cpu_latency_qos_write(struct file * filp,const char __user * buf,size_t count,loff_t * f_pos)379 static ssize_t cpu_latency_qos_write(struct file *filp, const char __user *buf,
380 				     size_t count, loff_t *f_pos)
381 {
382 	s32 value;
383 
384 	if (count == sizeof(s32)) {
385 		if (copy_from_user(&value, buf, sizeof(s32)))
386 			return -EFAULT;
387 	} else {
388 		int ret;
389 
390 		ret = kstrtos32_from_user(buf, count, 16, &value);
391 		if (ret)
392 			return ret;
393 	}
394 
395 	cpu_latency_qos_update_request(filp->private_data, value);
396 
397 	return count;
398 }
399 
400 static const struct file_operations cpu_latency_qos_fops = {
401 	.write = cpu_latency_qos_write,
402 	.read = cpu_latency_qos_read,
403 	.open = cpu_latency_qos_open,
404 	.release = cpu_latency_qos_release,
405 	.llseek = noop_llseek,
406 };
407 
408 static struct miscdevice cpu_latency_qos_miscdev = {
409 	.minor = MISC_DYNAMIC_MINOR,
410 	.name = "cpu_dma_latency",
411 	.fops = &cpu_latency_qos_fops,
412 };
413 
cpu_latency_qos_init(void)414 static int __init cpu_latency_qos_init(void)
415 {
416 	int ret;
417 
418 	ret = misc_register(&cpu_latency_qos_miscdev);
419 	if (ret < 0)
420 		pr_err("%s: %s setup failed\n", __func__,
421 		       cpu_latency_qos_miscdev.name);
422 
423 	return ret;
424 }
425 late_initcall(cpu_latency_qos_init);
426 #endif /* CONFIG_CPU_IDLE */
427 
428 /* Definitions related to the frequency QoS below. */
429 
freq_qos_value_invalid(s32 value)430 static inline bool freq_qos_value_invalid(s32 value)
431 {
432 	return value < 0 && value != PM_QOS_DEFAULT_VALUE;
433 }
434 
435 /**
436  * freq_constraints_init - Initialize frequency QoS constraints.
437  * @qos: Frequency QoS constraints to initialize.
438  */
freq_constraints_init(struct freq_constraints * qos)439 void freq_constraints_init(struct freq_constraints *qos)
440 {
441 	struct pm_qos_constraints *c;
442 
443 	c = &qos->min_freq;
444 	plist_head_init(&c->list);
445 	c->target_value = FREQ_QOS_MIN_DEFAULT_VALUE;
446 	c->default_value = FREQ_QOS_MIN_DEFAULT_VALUE;
447 	c->no_constraint_value = FREQ_QOS_MIN_DEFAULT_VALUE;
448 	c->type = PM_QOS_MAX;
449 	c->notifiers = &qos->min_freq_notifiers;
450 	BLOCKING_INIT_NOTIFIER_HEAD(c->notifiers);
451 
452 	c = &qos->max_freq;
453 	plist_head_init(&c->list);
454 	c->target_value = FREQ_QOS_MAX_DEFAULT_VALUE;
455 	c->default_value = FREQ_QOS_MAX_DEFAULT_VALUE;
456 	c->no_constraint_value = FREQ_QOS_MAX_DEFAULT_VALUE;
457 	c->type = PM_QOS_MIN;
458 	c->notifiers = &qos->max_freq_notifiers;
459 	BLOCKING_INIT_NOTIFIER_HEAD(c->notifiers);
460 }
461 
462 /**
463  * freq_qos_read_value - Get frequency QoS constraint for a given list.
464  * @qos: Constraints to evaluate.
465  * @type: QoS request type.
466  */
freq_qos_read_value(struct freq_constraints * qos,enum freq_qos_req_type type)467 s32 freq_qos_read_value(struct freq_constraints *qos,
468 			enum freq_qos_req_type type)
469 {
470 	s32 ret;
471 
472 	switch (type) {
473 	case FREQ_QOS_MIN:
474 		ret = IS_ERR_OR_NULL(qos) ?
475 			FREQ_QOS_MIN_DEFAULT_VALUE :
476 			pm_qos_read_value(&qos->min_freq);
477 		break;
478 	case FREQ_QOS_MAX:
479 		ret = IS_ERR_OR_NULL(qos) ?
480 			FREQ_QOS_MAX_DEFAULT_VALUE :
481 			pm_qos_read_value(&qos->max_freq);
482 		break;
483 	default:
484 		WARN_ON(1);
485 		ret = 0;
486 	}
487 
488 	return ret;
489 }
490 
491 /**
492  * freq_qos_apply - Add/modify/remove frequency QoS request.
493  * @req: Constraint request to apply.
494  * @action: Action to perform (add/update/remove).
495  * @value: Value to assign to the QoS request.
496  *
497  * This is only meant to be called from inside pm_qos, not drivers.
498  */
freq_qos_apply(struct freq_qos_request * req,enum pm_qos_req_action action,s32 value)499 int freq_qos_apply(struct freq_qos_request *req,
500 			  enum pm_qos_req_action action, s32 value)
501 {
502 	int ret;
503 
504 	switch(req->type) {
505 	case FREQ_QOS_MIN:
506 		ret = pm_qos_update_target(&req->qos->min_freq, &req->pnode,
507 					   action, value);
508 		break;
509 	case FREQ_QOS_MAX:
510 		ret = pm_qos_update_target(&req->qos->max_freq, &req->pnode,
511 					   action, value);
512 		break;
513 	default:
514 		ret = -EINVAL;
515 	}
516 
517 	return ret;
518 }
519 
520 /**
521  * freq_qos_add_request - Insert new frequency QoS request into a given list.
522  * @qos: Constraints to update.
523  * @req: Preallocated request object.
524  * @type: Request type.
525  * @value: Request value.
526  *
527  * Insert a new entry into the @qos list of requests, recompute the effective
528  * QoS constraint value for that list and initialize the @req object.  The
529  * caller needs to save that object for later use in updates and removal.
530  *
531  * Return 1 if the effective constraint value has changed, 0 if the effective
532  * constraint value has not changed, or a negative error code on failures.
533  */
freq_qos_add_request(struct freq_constraints * qos,struct freq_qos_request * req,enum freq_qos_req_type type,s32 value)534 int freq_qos_add_request(struct freq_constraints *qos,
535 			 struct freq_qos_request *req,
536 			 enum freq_qos_req_type type, s32 value)
537 {
538 	int ret;
539 
540 	if (IS_ERR_OR_NULL(qos) || !req || freq_qos_value_invalid(value))
541 		return -EINVAL;
542 
543 	if (WARN(freq_qos_request_active(req),
544 		 "%s() called for active request\n", __func__))
545 		return -EINVAL;
546 
547 	req->qos = qos;
548 	req->type = type;
549 	ret = freq_qos_apply(req, PM_QOS_ADD_REQ, value);
550 	if (ret < 0) {
551 		req->qos = NULL;
552 		req->type = 0;
553 	}
554 
555 	trace_android_vh_freq_qos_add_request(qos, req, type, value, ret);
556 	return ret;
557 }
558 EXPORT_SYMBOL_GPL(freq_qos_add_request);
559 
560 /**
561  * freq_qos_update_request - Modify existing frequency QoS request.
562  * @req: Request to modify.
563  * @new_value: New request value.
564  *
565  * Update an existing frequency QoS request along with the effective constraint
566  * value for the list of requests it belongs to.
567  *
568  * Return 1 if the effective constraint value has changed, 0 if the effective
569  * constraint value has not changed, or a negative error code on failures.
570  */
freq_qos_update_request(struct freq_qos_request * req,s32 new_value)571 int freq_qos_update_request(struct freq_qos_request *req, s32 new_value)
572 {
573 	if (!req || freq_qos_value_invalid(new_value))
574 		return -EINVAL;
575 
576 	if (WARN(!freq_qos_request_active(req),
577 		 "%s() called for unknown object\n", __func__))
578 		return -EINVAL;
579 
580 	trace_android_vh_freq_qos_update_request(req, new_value);
581 	if (req->pnode.prio == new_value)
582 		return 0;
583 
584 	return freq_qos_apply(req, PM_QOS_UPDATE_REQ, new_value);
585 }
586 EXPORT_SYMBOL_GPL(freq_qos_update_request);
587 
588 /**
589  * freq_qos_remove_request - Remove frequency QoS request from its list.
590  * @req: Request to remove.
591  *
592  * Remove the given frequency QoS request from the list of constraints it
593  * belongs to and recompute the effective constraint value for that list.
594  *
595  * Return 1 if the effective constraint value has changed, 0 if the effective
596  * constraint value has not changed, or a negative error code on failures.
597  */
freq_qos_remove_request(struct freq_qos_request * req)598 int freq_qos_remove_request(struct freq_qos_request *req)
599 {
600 	int ret;
601 
602 	if (!req)
603 		return -EINVAL;
604 
605 	if (WARN(!freq_qos_request_active(req),
606 		 "%s() called for unknown object\n", __func__))
607 		return -EINVAL;
608 
609 	trace_android_vh_freq_qos_remove_request(req);
610 	ret = freq_qos_apply(req, PM_QOS_REMOVE_REQ, PM_QOS_DEFAULT_VALUE);
611 	req->qos = NULL;
612 	req->type = 0;
613 
614 	return ret;
615 }
616 EXPORT_SYMBOL_GPL(freq_qos_remove_request);
617 
618 /**
619  * freq_qos_add_notifier - Add frequency QoS change notifier.
620  * @qos: List of requests to add the notifier to.
621  * @type: Request type.
622  * @notifier: Notifier block to add.
623  */
freq_qos_add_notifier(struct freq_constraints * qos,enum freq_qos_req_type type,struct notifier_block * notifier)624 int freq_qos_add_notifier(struct freq_constraints *qos,
625 			  enum freq_qos_req_type type,
626 			  struct notifier_block *notifier)
627 {
628 	int ret;
629 
630 	if (IS_ERR_OR_NULL(qos) || !notifier)
631 		return -EINVAL;
632 
633 	switch (type) {
634 	case FREQ_QOS_MIN:
635 		ret = blocking_notifier_chain_register(qos->min_freq.notifiers,
636 						       notifier);
637 		break;
638 	case FREQ_QOS_MAX:
639 		ret = blocking_notifier_chain_register(qos->max_freq.notifiers,
640 						       notifier);
641 		break;
642 	default:
643 		WARN_ON(1);
644 		ret = -EINVAL;
645 	}
646 
647 	return ret;
648 }
649 EXPORT_SYMBOL_GPL(freq_qos_add_notifier);
650 
651 /**
652  * freq_qos_remove_notifier - Remove frequency QoS change notifier.
653  * @qos: List of requests to remove the notifier from.
654  * @type: Request type.
655  * @notifier: Notifier block to remove.
656  */
freq_qos_remove_notifier(struct freq_constraints * qos,enum freq_qos_req_type type,struct notifier_block * notifier)657 int freq_qos_remove_notifier(struct freq_constraints *qos,
658 			     enum freq_qos_req_type type,
659 			     struct notifier_block *notifier)
660 {
661 	int ret;
662 
663 	if (IS_ERR_OR_NULL(qos) || !notifier)
664 		return -EINVAL;
665 
666 	switch (type) {
667 	case FREQ_QOS_MIN:
668 		ret = blocking_notifier_chain_unregister(qos->min_freq.notifiers,
669 							 notifier);
670 		break;
671 	case FREQ_QOS_MAX:
672 		ret = blocking_notifier_chain_unregister(qos->max_freq.notifiers,
673 							 notifier);
674 		break;
675 	default:
676 		WARN_ON(1);
677 		ret = -EINVAL;
678 	}
679 
680 	return ret;
681 }
682 EXPORT_SYMBOL_GPL(freq_qos_remove_notifier);
683