LCOV - code coverage report
Current view: top level - kernel/power - qos.c (source / functions) Hit Total Coverage
Test: coverage.info Lines: 37 123 30.1 %
Date: 2023-08-24 13:40:31 Functions: 3 12 25.0 %

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

Generated by: LCOV version 1.14