File Index
Files and directories
Sign in
FILE

misc.c

File preview with syntax highlighting.

linux-6.19.14/tools/power/cpupower/utils/helpers/misc.c C
  1// SPDX-License-Identifier: GPL-2.0
  2
  3#include <stdio.h>
  4#include <errno.h>
  5#include <stdlib.h>
  6#include <string.h>
  7
  8#include "helpers/helpers.h"
  9#include "helpers/sysfs.h"
 10#include "cpufreq.h"
 11#include "cpupower_intern.h"
 12
 13#if defined(__i386__) || defined(__x86_64__)
 14
 15#define MSR_AMD_HWCR	0xc0010015
 16
 17int cpufreq_has_x86_boost_support(unsigned int cpu, int *support, int *active,
 18				  int *states)
 19{
 20	int ret;
 21	unsigned long long val;
 22
 23	*support = *active = *states = 0;
 24
 25	if (cpupower_cpu_info.caps & CPUPOWER_CAP_AMD_CPB) {
 26		*support = 1;
 27
 28		/* AMD Family 0x17 does not utilize PCI D18F4 like prior
 29		 * families and has no fixed discrete boost states but
 30		 * has Hardware determined variable increments instead.
 31		 */
 32
 33		if (cpupower_cpu_info.caps & CPUPOWER_CAP_AMD_CPB_MSR) {
 34			if (!read_msr(cpu, MSR_AMD_HWCR, &val)) {
 35				if (!(val & CPUPOWER_AMD_CPBDIS))
 36					*active = 1;
 37			}
 38		} else {
 39			ret = amd_pci_get_num_boost_states(active, states);
 40			if (ret)
 41				return ret;
 42		}
 43	} else if (cpupower_cpu_info.caps & CPUPOWER_CAP_AMD_PSTATE) {
 44		amd_pstate_boost_init(cpu, support, active);
 45	} else if (cpupower_cpu_info.caps & CPUPOWER_CAP_INTEL_IDA)
 46		*support = *active = 1;
 47	return 0;
 48}
 49
 50int cpupower_intel_get_perf_bias(unsigned int cpu)
 51{
 52	char linebuf[MAX_LINE_LEN];
 53	char path[SYSFS_PATH_MAX];
 54	unsigned long val;
 55	char *endp;
 56
 57	if (!(cpupower_cpu_info.caps & CPUPOWER_CAP_PERF_BIAS))
 58		return -1;
 59
 60	snprintf(path, sizeof(path), PATH_TO_CPU "cpu%u/power/energy_perf_bias", cpu);
 61
 62	if (cpupower_read_sysfs(path, linebuf, MAX_LINE_LEN) == 0)
 63		return -1;
 64
 65	val = strtol(linebuf, &endp, 0);
 66	if (endp == linebuf || errno == ERANGE)
 67		return -1;
 68
 69	return val;
 70}
 71
 72int cpupower_intel_set_perf_bias(unsigned int cpu, unsigned int val)
 73{
 74	char path[SYSFS_PATH_MAX];
 75	char linebuf[3] = {};
 76
 77	if (!(cpupower_cpu_info.caps & CPUPOWER_CAP_PERF_BIAS))
 78		return -1;
 79
 80	snprintf(path, sizeof(path), PATH_TO_CPU "cpu%u/power/energy_perf_bias", cpu);
 81	snprintf(linebuf, sizeof(linebuf), "%d", val);
 82
 83	if (cpupower_write_sysfs(path, linebuf, 3) <= 0)
 84		return -1;
 85
 86	return 0;
 87}
 88
 89int cpupower_set_epp(unsigned int cpu, char *epp)
 90{
 91	char path[SYSFS_PATH_MAX];
 92	char linebuf[30] = {};
 93
 94	snprintf(path, sizeof(path),
 95		PATH_TO_CPU "cpu%u/cpufreq/energy_performance_preference", cpu);
 96
 97	if (!is_valid_path(path))
 98		return -1;
 99
100	snprintf(linebuf, sizeof(linebuf), "%s", epp);
101
102	if (cpupower_write_sysfs(path, linebuf, 30) <= 0)
103		return -1;
104
105	return 0;
106}
107
108int cpupower_set_amd_pstate_mode(char *mode)
109{
110	char path[SYSFS_PATH_MAX];
111	char linebuf[20] = {};
112
113	snprintf(path, sizeof(path), PATH_TO_CPU "amd_pstate/status");
114
115	if (!is_valid_path(path))
116		return -1;
117
118	snprintf(linebuf, sizeof(linebuf), "%s\n", mode);
119
120	if (cpupower_write_sysfs(path, linebuf, 20) <= 0)
121		return -1;
122
123	return 0;
124}
125
126bool cpupower_amd_pstate_enabled(void)
127{
128	char *driver = cpufreq_get_driver(0);
129	bool ret = false;
130
131	if (!driver)
132		return ret;
133
134	if (!strncmp(driver, "amd", 3))
135		ret = true;
136
137	cpufreq_put_driver(driver);
138
139	return ret;
140}
141
142#endif /* #if defined(__i386__) || defined(__x86_64__) */
143
144int cpufreq_has_generic_boost_support(bool *active)
145{
146	char path[SYSFS_PATH_MAX];
147	char linebuf[2] = {};
148	unsigned long val;
149	char *endp;
150
151	snprintf(path, sizeof(path), PATH_TO_CPU "cpufreq/boost");
152
153	if (!is_valid_path(path))
154		return -EACCES;
155
156	if (cpupower_read_sysfs(path, linebuf, 2) <= 0)
157		return -EINVAL;
158
159	val = strtoul(linebuf, &endp, 0);
160	if (endp == linebuf || errno == ERANGE)
161		return -EINVAL;
162
163	switch (val) {
164	case 0:
165		*active = false;
166		break;
167	case 1:
168		*active = true;
169		break;
170	default:
171		return -EINVAL;
172	}
173
174	return 0;
175}
176
177/* get_cpustate
178 *
179 * Gather the information of all online CPUs into bitmask struct
180 */
181void get_cpustate(void)
182{
183	unsigned int cpu = 0;
184
185	bitmask_clearall(online_cpus);
186	bitmask_clearall(offline_cpus);
187
188	for (cpu = bitmask_first(cpus_chosen);
189		cpu <= bitmask_last(cpus_chosen); cpu++) {
190
191		if (cpupower_is_cpu_online(cpu) == 1)
192			bitmask_setbit(online_cpus, cpu);
193		else
194			bitmask_setbit(offline_cpus, cpu);
195
196		continue;
197	}
198}
199
200/* print_online_cpus
201 *
202 * Print the CPU numbers of all CPUs that are online currently
203 */
204void print_online_cpus(void)
205{
206	int str_len = 0;
207	char *online_cpus_str = NULL;
208
209	str_len = online_cpus->size * 5;
210	online_cpus_str = (void *)malloc(sizeof(char) * str_len);
211
212	if (!bitmask_isallclear(online_cpus)) {
213		bitmask_displaylist(online_cpus_str, str_len, online_cpus);
214		printf(_("Following CPUs are online:\n%s\n"), online_cpus_str);
215	}
216}
217
218/* print_offline_cpus
219 *
220 * Print the CPU numbers of all CPUs that are offline currently
221 */
222void print_offline_cpus(void)
223{
224	int str_len = 0;
225	char *offline_cpus_str = NULL;
226
227	str_len = offline_cpus->size * 5;
228	offline_cpus_str = (void *)malloc(sizeof(char) * str_len);
229
230	if (!bitmask_isallclear(offline_cpus)) {
231		bitmask_displaylist(offline_cpus_str, str_len, offline_cpus);
232		printf(_("Following CPUs are offline:\n%s\n"), offline_cpus_str);
233		printf(_("cpupower set operation was not performed on them\n"));
234	}
235}
236
237/*
238 * print_speed
239 *
240 * Print the exact CPU frequency with appropriate unit
241 */
242void print_speed(unsigned long speed, int no_rounding)
243{
244	unsigned long tmp;
245
246	if (no_rounding) {
247		if (speed > 1000000)
248			printf("%u.%06u GHz", ((unsigned int)speed / 1000000),
249			       ((unsigned int)speed % 1000000));
250		else if (speed > 1000)
251			printf("%u.%03u MHz", ((unsigned int)speed / 1000),
252			       (unsigned int)(speed % 1000));
253		else
254			printf("%lu kHz", speed);
255	} else {
256		if (speed > 1000000) {
257			tmp = speed % 10000;
258			if (tmp >= 5000)
259				speed += 10000;
260			printf("%u.%02u GHz", ((unsigned int)speed / 1000000),
261			       ((unsigned int)(speed % 1000000) / 10000));
262		} else if (speed > 100000) {
263			tmp = speed % 1000;
264			if (tmp >= 500)
265				speed += 1000;
266			printf("%u MHz", ((unsigned int)speed / 1000));
267		} else if (speed > 1000) {
268			tmp = speed % 100;
269			if (tmp >= 50)
270				speed += 100;
271			printf("%u.%01u MHz", ((unsigned int)speed / 1000),
272			       ((unsigned int)(speed % 1000) / 100));
273		}
274	}
275}
276
277int cpupower_set_turbo_boost(int turbo_boost)
278{
279	char path[SYSFS_PATH_MAX];
280	char linebuf[2] = {};
281
282	snprintf(path, sizeof(path), PATH_TO_CPU "cpufreq/boost");
283
284	if (!is_valid_path(path))
285		return -1;
286
287	snprintf(linebuf, sizeof(linebuf), "%d", turbo_boost);
288
289	if (cpupower_write_sysfs(path, linebuf, 2) <= 0)
290		return -1;
291
292	return 0;
293}
~/ Read-only file preview.