PM: QoS: Clean up misc device file operations
[sfrench/cifs-2.6.git] / kernel / power / qos.c
1 // SPDX-License-Identifier: GPL-2.0-only
2 /*
3  * This module exposes the interface to kernel space for specifying
4  * QoS dependencies.  It provides infrastructure for registration of:
5  *
6  * Dependents on a QoS value : register requests
7  * Watchers of QoS value : get notified when target QoS value changes
8  *
9  * This QoS design is best effort based.  Dependents register their QoS needs.
10  * Watchers register to keep track of the current QoS needs of the system.
11  *
12  * There are 3 basic classes of QoS parameter: latency, timeout, throughput
13  * each have defined units:
14  * latency: usec
15  * timeout: usec <-- currently not used.
16  * throughput: kbs (kilo byte / sec)
17  *
18  * There are lists of pm_qos_objects each one wrapping requests, notifiers
19  *
20  * User mode requests on a QOS parameter register themselves to the
21  * subsystem by opening the device node /dev/... and writing there request to
22  * the node.  As long as the process holds a file handle open to the node the
23  * client continues to be accounted for.  Upon file release the usermode
24  * request is removed and a new qos target is computed.  This way when the
25  * request that the application has is cleaned up when closes the file
26  * pointer or exits the pm_qos_object will get an opportunity to clean up.
27  *
28  * Mark Gross <mgross@linux.intel.com>
29  */
30
31 /*#define DEBUG*/
32
33 #include <linux/pm_qos.h>
34 #include <linux/sched.h>
35 #include <linux/spinlock.h>
36 #include <linux/slab.h>
37 #include <linux/time.h>
38 #include <linux/fs.h>
39 #include <linux/device.h>
40 #include <linux/miscdevice.h>
41 #include <linux/string.h>
42 #include <linux/platform_device.h>
43 #include <linux/init.h>
44 #include <linux/kernel.h>
45 #include <linux/debugfs.h>
46 #include <linux/seq_file.h>
47
48 #include <linux/uaccess.h>
49 #include <linux/export.h>
50 #include <trace/events/power.h>
51
52 /*
53  * locking rule: all changes to constraints or notifiers lists
54  * or pm_qos_object list and pm_qos_objects need to happen with pm_qos_lock
55  * held, taken with _irqsave.  One lock to rule them all
56  */
57 struct pm_qos_object {
58         struct pm_qos_constraints *constraints;
59         struct miscdevice pm_qos_power_miscdev;
60         char *name;
61 };
62
63 static DEFINE_SPINLOCK(pm_qos_lock);
64
65 static struct pm_qos_object null_pm_qos;
66
67 static BLOCKING_NOTIFIER_HEAD(cpu_dma_lat_notifier);
68 static struct pm_qos_constraints cpu_dma_constraints = {
69         .list = PLIST_HEAD_INIT(cpu_dma_constraints.list),
70         .target_value = PM_QOS_CPU_DMA_LAT_DEFAULT_VALUE,
71         .default_value = PM_QOS_CPU_DMA_LAT_DEFAULT_VALUE,
72         .no_constraint_value = PM_QOS_CPU_DMA_LAT_DEFAULT_VALUE,
73         .type = PM_QOS_MIN,
74         .notifiers = &cpu_dma_lat_notifier,
75 };
76 static struct pm_qos_object cpu_dma_pm_qos = {
77         .constraints = &cpu_dma_constraints,
78         .name = "cpu_dma_latency",
79 };
80
81 static struct pm_qos_object *pm_qos_array[] = {
82         &null_pm_qos,
83         &cpu_dma_pm_qos,
84 };
85
86 /**
87  * pm_qos_read_value - Return the current effective constraint value.
88  * @c: List of PM QoS constraint requests.
89  */
90 s32 pm_qos_read_value(struct pm_qos_constraints *c)
91 {
92         return c->target_value;
93 }
94
95 static int pm_qos_get_value(struct pm_qos_constraints *c)
96 {
97         if (plist_head_empty(&c->list))
98                 return c->no_constraint_value;
99
100         switch (c->type) {
101         case PM_QOS_MIN:
102                 return plist_first(&c->list)->prio;
103
104         case PM_QOS_MAX:
105                 return plist_last(&c->list)->prio;
106
107         default:
108                 WARN(1, "Unknown PM QoS type in %s\n", __func__);
109                 return PM_QOS_DEFAULT_VALUE;
110         }
111 }
112
113 static void pm_qos_set_value(struct pm_qos_constraints *c, s32 value)
114 {
115         c->target_value = value;
116 }
117
118 /**
119  * pm_qos_update_target - Update a list of PM QoS constraint requests.
120  * @c: List of PM QoS requests.
121  * @node: Target list entry.
122  * @action: Action to carry out (add, update or remove).
123  * @value: New request value for the target list entry.
124  *
125  * Update the given list of PM QoS constraint requests, @c, by carrying an
126  * @action involving the @node list entry and @value on it.
127  *
128  * The recognized values of @action are PM_QOS_ADD_REQ (store @value in @node
129  * and add it to the list), PM_QOS_UPDATE_REQ (remove @node from the list, store
130  * @value in it and add it to the list again), and PM_QOS_REMOVE_REQ (remove
131  * @node from the list, ignore @value).
132  *
133  * Return: 1 if the aggregate constraint value has changed, 0  otherwise.
134  */
135 int pm_qos_update_target(struct pm_qos_constraints *c, struct plist_node *node,
136                          enum pm_qos_req_action action, int value)
137 {
138         int prev_value, curr_value, new_value;
139         unsigned long flags;
140
141         spin_lock_irqsave(&pm_qos_lock, flags);
142
143         prev_value = pm_qos_get_value(c);
144         if (value == PM_QOS_DEFAULT_VALUE)
145                 new_value = c->default_value;
146         else
147                 new_value = value;
148
149         switch (action) {
150         case PM_QOS_REMOVE_REQ:
151                 plist_del(node, &c->list);
152                 break;
153         case PM_QOS_UPDATE_REQ:
154                 /*
155                  * To change the list, atomically remove, reinit with new value
156                  * and add, then see if the aggregate has changed.
157                  */
158                 plist_del(node, &c->list);
159                 /* fall through */
160         case PM_QOS_ADD_REQ:
161                 plist_node_init(node, new_value);
162                 plist_add(node, &c->list);
163                 break;
164         default:
165                 /* no action */
166                 ;
167         }
168
169         curr_value = pm_qos_get_value(c);
170         pm_qos_set_value(c, curr_value);
171
172         spin_unlock_irqrestore(&pm_qos_lock, flags);
173
174         trace_pm_qos_update_target(action, prev_value, curr_value);
175
176         if (prev_value == curr_value)
177                 return 0;
178
179         if (c->notifiers)
180                 blocking_notifier_call_chain(c->notifiers, curr_value, NULL);
181
182         return 1;
183 }
184
185 /**
186  * pm_qos_flags_remove_req - Remove device PM QoS flags request.
187  * @pqf: Device PM QoS flags set to remove the request from.
188  * @req: Request to remove from the set.
189  */
190 static void pm_qos_flags_remove_req(struct pm_qos_flags *pqf,
191                                     struct pm_qos_flags_request *req)
192 {
193         s32 val = 0;
194
195         list_del(&req->node);
196         list_for_each_entry(req, &pqf->list, node)
197                 val |= req->flags;
198
199         pqf->effective_flags = val;
200 }
201
202 /**
203  * pm_qos_update_flags - Update a set of PM QoS flags.
204  * @pqf: Set of PM QoS flags to update.
205  * @req: Request to add to the set, to modify, or to remove from the set.
206  * @action: Action to take on the set.
207  * @val: Value of the request to add or modify.
208  *
209  * Return: 1 if the aggregate constraint value has changed, 0 otherwise.
210  */
211 bool pm_qos_update_flags(struct pm_qos_flags *pqf,
212                          struct pm_qos_flags_request *req,
213                          enum pm_qos_req_action action, s32 val)
214 {
215         unsigned long irqflags;
216         s32 prev_value, curr_value;
217
218         spin_lock_irqsave(&pm_qos_lock, irqflags);
219
220         prev_value = list_empty(&pqf->list) ? 0 : pqf->effective_flags;
221
222         switch (action) {
223         case PM_QOS_REMOVE_REQ:
224                 pm_qos_flags_remove_req(pqf, req);
225                 break;
226         case PM_QOS_UPDATE_REQ:
227                 pm_qos_flags_remove_req(pqf, req);
228                 /* fall through */
229         case PM_QOS_ADD_REQ:
230                 req->flags = val;
231                 INIT_LIST_HEAD(&req->node);
232                 list_add_tail(&req->node, &pqf->list);
233                 pqf->effective_flags |= val;
234                 break;
235         default:
236                 /* no action */
237                 ;
238         }
239
240         curr_value = list_empty(&pqf->list) ? 0 : pqf->effective_flags;
241
242         spin_unlock_irqrestore(&pm_qos_lock, irqflags);
243
244         trace_pm_qos_update_flags(action, prev_value, curr_value);
245
246         return prev_value != curr_value;
247 }
248
249 /**
250  * pm_qos_request - returns current system wide qos expectation
251  * @pm_qos_class: identification of which qos value is requested
252  *
253  * This function returns the current target value.
254  */
255 int pm_qos_request(int pm_qos_class)
256 {
257         return pm_qos_read_value(pm_qos_array[pm_qos_class]->constraints);
258 }
259 EXPORT_SYMBOL_GPL(pm_qos_request);
260
261 int pm_qos_request_active(struct pm_qos_request *req)
262 {
263         return req->pm_qos_class != 0;
264 }
265 EXPORT_SYMBOL_GPL(pm_qos_request_active);
266
267 static void __pm_qos_update_request(struct pm_qos_request *req,
268                            s32 new_value)
269 {
270         trace_pm_qos_update_request(req->pm_qos_class, new_value);
271
272         if (new_value != req->node.prio)
273                 pm_qos_update_target(
274                         pm_qos_array[req->pm_qos_class]->constraints,
275                         &req->node, PM_QOS_UPDATE_REQ, new_value);
276 }
277
278 /**
279  * pm_qos_add_request - inserts new qos request into the list
280  * @req: pointer to a preallocated handle
281  * @pm_qos_class: identifies which list of qos request to use
282  * @value: defines the qos request
283  *
284  * This function inserts a new entry in the pm_qos_class list of requested qos
285  * performance characteristics.  It recomputes the aggregate QoS expectations
286  * for the pm_qos_class of parameters and initializes the pm_qos_request
287  * handle.  Caller needs to save this handle for later use in updates and
288  * removal.
289  */
290
291 void pm_qos_add_request(struct pm_qos_request *req,
292                         int pm_qos_class, s32 value)
293 {
294         if (!req) /*guard against callers passing in null */
295                 return;
296
297         if (pm_qos_request_active(req)) {
298                 WARN(1, KERN_ERR "pm_qos_add_request() called for already added request\n");
299                 return;
300         }
301         req->pm_qos_class = pm_qos_class;
302         trace_pm_qos_add_request(pm_qos_class, value);
303         pm_qos_update_target(pm_qos_array[pm_qos_class]->constraints,
304                              &req->node, PM_QOS_ADD_REQ, value);
305 }
306 EXPORT_SYMBOL_GPL(pm_qos_add_request);
307
308 /**
309  * pm_qos_update_request - modifies an existing qos request
310  * @req : handle to list element holding a pm_qos request to use
311  * @value: defines the qos request
312  *
313  * Updates an existing qos request for the pm_qos_class of parameters along
314  * with updating the target pm_qos_class value.
315  *
316  * Attempts are made to make this code callable on hot code paths.
317  */
318 void pm_qos_update_request(struct pm_qos_request *req,
319                            s32 new_value)
320 {
321         if (!req) /*guard against callers passing in null */
322                 return;
323
324         if (!pm_qos_request_active(req)) {
325                 WARN(1, KERN_ERR "pm_qos_update_request() called for unknown object\n");
326                 return;
327         }
328
329         __pm_qos_update_request(req, new_value);
330 }
331 EXPORT_SYMBOL_GPL(pm_qos_update_request);
332
333 /**
334  * pm_qos_remove_request - modifies an existing qos request
335  * @req: handle to request list element
336  *
337  * Will remove pm qos request from the list of constraints and
338  * recompute the current target value for the pm_qos_class.  Call this
339  * on slow code paths.
340  */
341 void pm_qos_remove_request(struct pm_qos_request *req)
342 {
343         if (!req) /*guard against callers passing in null */
344                 return;
345                 /* silent return to keep pcm code cleaner */
346
347         if (!pm_qos_request_active(req)) {
348                 WARN(1, KERN_ERR "pm_qos_remove_request() called for unknown object\n");
349                 return;
350         }
351
352         trace_pm_qos_remove_request(req->pm_qos_class, PM_QOS_DEFAULT_VALUE);
353         pm_qos_update_target(pm_qos_array[req->pm_qos_class]->constraints,
354                              &req->node, PM_QOS_REMOVE_REQ,
355                              PM_QOS_DEFAULT_VALUE);
356         memset(req, 0, sizeof(*req));
357 }
358 EXPORT_SYMBOL_GPL(pm_qos_remove_request);
359
360 /**
361  * pm_qos_add_notifier - sets notification entry for changes to target value
362  * @pm_qos_class: identifies which qos target changes should be notified.
363  * @notifier: notifier block managed by caller.
364  *
365  * will register the notifier into a notification chain that gets called
366  * upon changes to the pm_qos_class target value.
367  */
368 int pm_qos_add_notifier(int pm_qos_class, struct notifier_block *notifier)
369 {
370         int retval;
371
372         retval = blocking_notifier_chain_register(
373                         pm_qos_array[pm_qos_class]->constraints->notifiers,
374                         notifier);
375
376         return retval;
377 }
378 EXPORT_SYMBOL_GPL(pm_qos_add_notifier);
379
380 /**
381  * pm_qos_remove_notifier - deletes notification entry from chain.
382  * @pm_qos_class: identifies which qos target changes are notified.
383  * @notifier: notifier block to be removed.
384  *
385  * will remove the notifier from the notification chain that gets called
386  * upon changes to the pm_qos_class target value.
387  */
388 int pm_qos_remove_notifier(int pm_qos_class, struct notifier_block *notifier)
389 {
390         int retval;
391
392         retval = blocking_notifier_chain_unregister(
393                         pm_qos_array[pm_qos_class]->constraints->notifiers,
394                         notifier);
395
396         return retval;
397 }
398 EXPORT_SYMBOL_GPL(pm_qos_remove_notifier);
399
400 /* User space interface to global PM QoS via misc device. */
401
402 static int pm_qos_power_open(struct inode *inode, struct file *filp)
403 {
404         struct pm_qos_request *req;
405
406         req = kzalloc(sizeof(*req), GFP_KERNEL);
407         if (!req)
408                 return -ENOMEM;
409
410         pm_qos_add_request(req, PM_QOS_CPU_DMA_LATENCY, PM_QOS_DEFAULT_VALUE);
411         filp->private_data = req;
412
413         return 0;
414 }
415
416 static int pm_qos_power_release(struct inode *inode, struct file *filp)
417 {
418         struct pm_qos_request *req = filp->private_data;
419
420         filp->private_data = NULL;
421
422         pm_qos_remove_request(req);
423         kfree(req);
424
425         return 0;
426 }
427
428 static ssize_t pm_qos_power_read(struct file *filp, char __user *buf,
429                                  size_t count, loff_t *f_pos)
430 {
431         struct pm_qos_request *req = filp->private_data;
432         unsigned long flags;
433         s32 value;
434
435         if (!req || !pm_qos_request_active(req))
436                 return -EINVAL;
437
438         spin_lock_irqsave(&pm_qos_lock, flags);
439         value = pm_qos_get_value(pm_qos_array[req->pm_qos_class]->constraints);
440         spin_unlock_irqrestore(&pm_qos_lock, flags);
441
442         return simple_read_from_buffer(buf, count, f_pos, &value, sizeof(s32));
443 }
444
445 static ssize_t pm_qos_power_write(struct file *filp, const char __user *buf,
446                                   size_t count, loff_t *f_pos)
447 {
448         s32 value;
449
450         if (count == sizeof(s32)) {
451                 if (copy_from_user(&value, buf, sizeof(s32)))
452                         return -EFAULT;
453         } else {
454                 int ret;
455
456                 ret = kstrtos32_from_user(buf, count, 16, &value);
457                 if (ret)
458                         return ret;
459         }
460
461         pm_qos_update_request(filp->private_data, value);
462
463         return count;
464 }
465
466 static const struct file_operations pm_qos_power_fops = {
467         .write = pm_qos_power_write,
468         .read = pm_qos_power_read,
469         .open = pm_qos_power_open,
470         .release = pm_qos_power_release,
471         .llseek = noop_llseek,
472 };
473
474 static int register_pm_qos_misc(struct pm_qos_object *qos)
475 {
476         qos->pm_qos_power_miscdev.minor = MISC_DYNAMIC_MINOR;
477         qos->pm_qos_power_miscdev.name = qos->name;
478         qos->pm_qos_power_miscdev.fops = &pm_qos_power_fops;
479
480         return misc_register(&qos->pm_qos_power_miscdev);
481 }
482
483 static int __init pm_qos_power_init(void)
484 {
485         int ret;
486
487         BUILD_BUG_ON(ARRAY_SIZE(pm_qos_array) != PM_QOS_NUM_CLASSES);
488
489         ret = register_pm_qos_misc(pm_qos_array[PM_QOS_CPU_DMA_LATENCY]);
490         if (ret < 0)
491                 pr_err("%s: %s setup failed\n", __func__,
492                        pm_qos_array[PM_QOS_CPU_DMA_LATENCY]->name);
493
494         return ret;
495 }
496 late_initcall(pm_qos_power_init);
497
498 /* Definitions related to the frequency QoS below. */
499
500 /**
501  * freq_constraints_init - Initialize frequency QoS constraints.
502  * @qos: Frequency QoS constraints to initialize.
503  */
504 void freq_constraints_init(struct freq_constraints *qos)
505 {
506         struct pm_qos_constraints *c;
507
508         c = &qos->min_freq;
509         plist_head_init(&c->list);
510         c->target_value = FREQ_QOS_MIN_DEFAULT_VALUE;
511         c->default_value = FREQ_QOS_MIN_DEFAULT_VALUE;
512         c->no_constraint_value = FREQ_QOS_MIN_DEFAULT_VALUE;
513         c->type = PM_QOS_MAX;
514         c->notifiers = &qos->min_freq_notifiers;
515         BLOCKING_INIT_NOTIFIER_HEAD(c->notifiers);
516
517         c = &qos->max_freq;
518         plist_head_init(&c->list);
519         c->target_value = FREQ_QOS_MAX_DEFAULT_VALUE;
520         c->default_value = FREQ_QOS_MAX_DEFAULT_VALUE;
521         c->no_constraint_value = FREQ_QOS_MAX_DEFAULT_VALUE;
522         c->type = PM_QOS_MIN;
523         c->notifiers = &qos->max_freq_notifiers;
524         BLOCKING_INIT_NOTIFIER_HEAD(c->notifiers);
525 }
526
527 /**
528  * freq_qos_read_value - Get frequency QoS constraint for a given list.
529  * @qos: Constraints to evaluate.
530  * @type: QoS request type.
531  */
532 s32 freq_qos_read_value(struct freq_constraints *qos,
533                         enum freq_qos_req_type type)
534 {
535         s32 ret;
536
537         switch (type) {
538         case FREQ_QOS_MIN:
539                 ret = IS_ERR_OR_NULL(qos) ?
540                         FREQ_QOS_MIN_DEFAULT_VALUE :
541                         pm_qos_read_value(&qos->min_freq);
542                 break;
543         case FREQ_QOS_MAX:
544                 ret = IS_ERR_OR_NULL(qos) ?
545                         FREQ_QOS_MAX_DEFAULT_VALUE :
546                         pm_qos_read_value(&qos->max_freq);
547                 break;
548         default:
549                 WARN_ON(1);
550                 ret = 0;
551         }
552
553         return ret;
554 }
555
556 /**
557  * freq_qos_apply - Add/modify/remove frequency QoS request.
558  * @req: Constraint request to apply.
559  * @action: Action to perform (add/update/remove).
560  * @value: Value to assign to the QoS request.
561  *
562  * This is only meant to be called from inside pm_qos, not drivers.
563  */
564 int freq_qos_apply(struct freq_qos_request *req,
565                           enum pm_qos_req_action action, s32 value)
566 {
567         int ret;
568
569         switch(req->type) {
570         case FREQ_QOS_MIN:
571                 ret = pm_qos_update_target(&req->qos->min_freq, &req->pnode,
572                                            action, value);
573                 break;
574         case FREQ_QOS_MAX:
575                 ret = pm_qos_update_target(&req->qos->max_freq, &req->pnode,
576                                            action, value);
577                 break;
578         default:
579                 ret = -EINVAL;
580         }
581
582         return ret;
583 }
584
585 /**
586  * freq_qos_add_request - Insert new frequency QoS request into a given list.
587  * @qos: Constraints to update.
588  * @req: Preallocated request object.
589  * @type: Request type.
590  * @value: Request value.
591  *
592  * Insert a new entry into the @qos list of requests, recompute the effective
593  * QoS constraint value for that list and initialize the @req object.  The
594  * caller needs to save that object for later use in updates and removal.
595  *
596  * Return 1 if the effective constraint value has changed, 0 if the effective
597  * constraint value has not changed, or a negative error code on failures.
598  */
599 int freq_qos_add_request(struct freq_constraints *qos,
600                          struct freq_qos_request *req,
601                          enum freq_qos_req_type type, s32 value)
602 {
603         int ret;
604
605         if (IS_ERR_OR_NULL(qos) || !req)
606                 return -EINVAL;
607
608         if (WARN(freq_qos_request_active(req),
609                  "%s() called for active request\n", __func__))
610                 return -EINVAL;
611
612         req->qos = qos;
613         req->type = type;
614         ret = freq_qos_apply(req, PM_QOS_ADD_REQ, value);
615         if (ret < 0) {
616                 req->qos = NULL;
617                 req->type = 0;
618         }
619
620         return ret;
621 }
622 EXPORT_SYMBOL_GPL(freq_qos_add_request);
623
624 /**
625  * freq_qos_update_request - Modify existing frequency QoS request.
626  * @req: Request to modify.
627  * @new_value: New request value.
628  *
629  * Update an existing frequency QoS request along with the effective constraint
630  * value for the list of requests it belongs to.
631  *
632  * Return 1 if the effective constraint value has changed, 0 if the effective
633  * constraint value has not changed, or a negative error code on failures.
634  */
635 int freq_qos_update_request(struct freq_qos_request *req, s32 new_value)
636 {
637         if (!req)
638                 return -EINVAL;
639
640         if (WARN(!freq_qos_request_active(req),
641                  "%s() called for unknown object\n", __func__))
642                 return -EINVAL;
643
644         if (req->pnode.prio == new_value)
645                 return 0;
646
647         return freq_qos_apply(req, PM_QOS_UPDATE_REQ, new_value);
648 }
649 EXPORT_SYMBOL_GPL(freq_qos_update_request);
650
651 /**
652  * freq_qos_remove_request - Remove frequency QoS request from its list.
653  * @req: Request to remove.
654  *
655  * Remove the given frequency QoS request from the list of constraints it
656  * belongs to and recompute the effective constraint value for that list.
657  *
658  * Return 1 if the effective constraint value has changed, 0 if the effective
659  * constraint value has not changed, or a negative error code on failures.
660  */
661 int freq_qos_remove_request(struct freq_qos_request *req)
662 {
663         int ret;
664
665         if (!req)
666                 return -EINVAL;
667
668         if (WARN(!freq_qos_request_active(req),
669                  "%s() called for unknown object\n", __func__))
670                 return -EINVAL;
671
672         ret = freq_qos_apply(req, PM_QOS_REMOVE_REQ, PM_QOS_DEFAULT_VALUE);
673         req->qos = NULL;
674         req->type = 0;
675
676         return ret;
677 }
678 EXPORT_SYMBOL_GPL(freq_qos_remove_request);
679
680 /**
681  * freq_qos_add_notifier - Add frequency QoS change notifier.
682  * @qos: List of requests to add the notifier to.
683  * @type: Request type.
684  * @notifier: Notifier block to add.
685  */
686 int freq_qos_add_notifier(struct freq_constraints *qos,
687                           enum freq_qos_req_type type,
688                           struct notifier_block *notifier)
689 {
690         int ret;
691
692         if (IS_ERR_OR_NULL(qos) || !notifier)
693                 return -EINVAL;
694
695         switch (type) {
696         case FREQ_QOS_MIN:
697                 ret = blocking_notifier_chain_register(qos->min_freq.notifiers,
698                                                        notifier);
699                 break;
700         case FREQ_QOS_MAX:
701                 ret = blocking_notifier_chain_register(qos->max_freq.notifiers,
702                                                        notifier);
703                 break;
704         default:
705                 WARN_ON(1);
706                 ret = -EINVAL;
707         }
708
709         return ret;
710 }
711 EXPORT_SYMBOL_GPL(freq_qos_add_notifier);
712
713 /**
714  * freq_qos_remove_notifier - Remove frequency QoS change notifier.
715  * @qos: List of requests to remove the notifier from.
716  * @type: Request type.
717  * @notifier: Notifier block to remove.
718  */
719 int freq_qos_remove_notifier(struct freq_constraints *qos,
720                              enum freq_qos_req_type type,
721                              struct notifier_block *notifier)
722 {
723         int ret;
724
725         if (IS_ERR_OR_NULL(qos) || !notifier)
726                 return -EINVAL;
727
728         switch (type) {
729         case FREQ_QOS_MIN:
730                 ret = blocking_notifier_chain_unregister(qos->min_freq.notifiers,
731                                                          notifier);
732                 break;
733         case FREQ_QOS_MAX:
734                 ret = blocking_notifier_chain_unregister(qos->max_freq.notifiers,
735                                                          notifier);
736                 break;
737         default:
738                 WARN_ON(1);
739                 ret = -EINVAL;
740         }
741
742         return ret;
743 }
744 EXPORT_SYMBOL_GPL(freq_qos_remove_notifier);