Orange Pi5 kernel

Deprecated Linux kernel 5.10.110 for OrangePi 5/5B/5+ boards

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