dtpm.c (d0034a7a4ac7fae708146ac0059b9c47a1543f0d) dtpm.c (4570ddda43387e5a130dd85e71a1947b0c11da77)
1// SPDX-License-Identifier: GPL-2.0-only
2/*
3 * Copyright 2020 Linaro Limited
4 *
5 * Author: Daniel Lezcano <daniel.lezcano@linaro.org>
6 *
7 * The powercap based Dynamic Thermal Power Management framework
8 * provides to the userspace a consistent API to set the power limit

--- 102 unchanged lines hidden (view full) ---

111 struct dtpm *parent = dtpm->parent;
112
113 while (parent) {
114 parent->power_min -= dtpm->power_min;
115 parent->power_max -= dtpm->power_max;
116 parent->power_limit -= dtpm->power_limit;
117 parent = parent->parent;
118 }
1// SPDX-License-Identifier: GPL-2.0-only
2/*
3 * Copyright 2020 Linaro Limited
4 *
5 * Author: Daniel Lezcano <daniel.lezcano@linaro.org>
6 *
7 * The powercap based Dynamic Thermal Power Management framework
8 * provides to the userspace a consistent API to set the power limit

--- 102 unchanged lines hidden (view full) ---

111 struct dtpm *parent = dtpm->parent;
112
113 while (parent) {
114 parent->power_min -= dtpm->power_min;
115 parent->power_max -= dtpm->power_max;
116 parent->power_limit -= dtpm->power_limit;
117 parent = parent->parent;
118 }
119
120 __dtpm_rebalance_weight(root);
121}
122
123static void __dtpm_add_power(struct dtpm *dtpm)
124{
125 struct dtpm *parent = dtpm->parent;
126
127 while (parent) {
128 parent->power_min += dtpm->power_min;
129 parent->power_max += dtpm->power_max;
130 parent->power_limit += dtpm->power_limit;
131 parent = parent->parent;
132 }
119}
120
121static void __dtpm_add_power(struct dtpm *dtpm)
122{
123 struct dtpm *parent = dtpm->parent;
124
125 while (parent) {
126 parent->power_min += dtpm->power_min;
127 parent->power_max += dtpm->power_max;
128 parent->power_limit += dtpm->power_limit;
129 parent = parent->parent;
130 }
131}
133
132
134 __dtpm_rebalance_weight(root);
133static int __dtpm_update_power(struct dtpm *dtpm)
134{
135 int ret;
136
137 __dtpm_sub_power(dtpm);
138
139 ret = dtpm->ops->update_power_uw(dtpm);
140 if (ret)
141 pr_err("Failed to update power for '%s': %d\n",
142 dtpm->zone.name, ret);
143
144 if (!test_bit(DTPM_POWER_LIMIT_FLAG, &dtpm->flags))
145 dtpm->power_limit = dtpm->power_max;
146
147 __dtpm_add_power(dtpm);
148
149 if (root)
150 __dtpm_rebalance_weight(root);
151
152 return ret;
135}
136
137/**
138 * dtpm_update_power - Update the power on the dtpm
139 * @dtpm: a pointer to a dtpm structure to update
153}
154
155/**
156 * dtpm_update_power - Update the power on the dtpm
157 * @dtpm: a pointer to a dtpm structure to update
140 * @power_min: a u64 representing the new power_min value
141 * @power_max: a u64 representing the new power_max value
142 *
143 * Function to update the power values of the dtpm node specified in
144 * parameter. These new values will be propagated to the tree.
145 *
146 * Return: zero on success, -EINVAL if the values are inconsistent
147 */
158 *
159 * Function to update the power values of the dtpm node specified in
160 * parameter. These new values will be propagated to the tree.
161 *
162 * Return: zero on success, -EINVAL if the values are inconsistent
163 */
148int dtpm_update_power(struct dtpm *dtpm, u64 power_min, u64 power_max)
164int dtpm_update_power(struct dtpm *dtpm)
149{
165{
150 int ret = 0;
166 int ret;
151
152 mutex_lock(&dtpm_lock);
167
168 mutex_lock(&dtpm_lock);
153
154 if (power_min == dtpm->power_min && power_max == dtpm->power_max)
155 goto unlock;
156
157 if (power_max < power_min) {
158 ret = -EINVAL;
159 goto unlock;
160 }
161
162 __dtpm_sub_power(dtpm);
163
164 dtpm->power_min = power_min;
165 dtpm->power_max = power_max;
166 if (!test_bit(DTPM_POWER_LIMIT_FLAG, &dtpm->flags))
167 dtpm->power_limit = power_max;
168
169 __dtpm_add_power(dtpm);
170
171unlock:
169 ret = __dtpm_update_power(dtpm);
172 mutex_unlock(&dtpm_lock);
173
174 return ret;
175}
176
177/**
178 * dtpm_release_zone - Cleanup when the node is released
179 * @pcz: a pointer to a powercap_zone structure

--- 251 unchanged lines hidden (view full) ---

431 if (parent && parent->ops)
432 return -EINVAL;
433
434 if (!dtpm)
435 return -EINVAL;
436
437 if (dtpm->ops && !(dtpm->ops->set_power_uw &&
438 dtpm->ops->get_power_uw &&
170 mutex_unlock(&dtpm_lock);
171
172 return ret;
173}
174
175/**
176 * dtpm_release_zone - Cleanup when the node is released
177 * @pcz: a pointer to a powercap_zone structure

--- 251 unchanged lines hidden (view full) ---

429 if (parent && parent->ops)
430 return -EINVAL;
431
432 if (!dtpm)
433 return -EINVAL;
434
435 if (dtpm->ops && !(dtpm->ops->set_power_uw &&
436 dtpm->ops->get_power_uw &&
437 dtpm->ops->update_power_uw &&
439 dtpm->ops->release))
440 return -EINVAL;
441
442 pcz = powercap_register_zone(&dtpm->zone, pct, name,
443 parent ? &parent->zone : NULL,
444 &zone_ops, MAX_DTPM_CONSTRAINTS,
445 &constraint_ops);
446 if (IS_ERR(pcz))
447 return PTR_ERR(pcz);
448
449 mutex_lock(&dtpm_lock);
450
451 if (parent) {
452 list_add_tail(&dtpm->sibling, &parent->children);
453 dtpm->parent = parent;
454 } else {
455 root = dtpm;
456 }
457
438 dtpm->ops->release))
439 return -EINVAL;
440
441 pcz = powercap_register_zone(&dtpm->zone, pct, name,
442 parent ? &parent->zone : NULL,
443 &zone_ops, MAX_DTPM_CONSTRAINTS,
444 &constraint_ops);
445 if (IS_ERR(pcz))
446 return PTR_ERR(pcz);
447
448 mutex_lock(&dtpm_lock);
449
450 if (parent) {
451 list_add_tail(&dtpm->sibling, &parent->children);
452 dtpm->parent = parent;
453 } else {
454 root = dtpm;
455 }
456
458 __dtpm_add_power(dtpm);
457 if (dtpm->ops && !dtpm->ops->update_power_uw(dtpm))
458 __dtpm_add_power(dtpm);
459
460 pr_info("Registered dtpm node '%s' / %llu-%llu uW, \n",
461 dtpm->zone.name, dtpm->power_min, dtpm->power_max);
462
463 mutex_unlock(&dtpm_lock);
464
465 return 0;
466}

--- 17 unchanged lines hidden ---
459
460 pr_info("Registered dtpm node '%s' / %llu-%llu uW, \n",
461 dtpm->zone.name, dtpm->power_min, dtpm->power_max);
462
463 mutex_unlock(&dtpm_lock);
464
465 return 0;
466}

--- 17 unchanged lines hidden ---