^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);