2 * (C) 2004-2009 Dominik Brodowski <linux@dominikbrodowski.de>
3 * (C) 2011 Thomas Renninger <trenn@novell.com> Novell Inc.
5 * Licensed under the terms of the GNU GPL License version 2.
12 #include <sys/types.h>
17 #include "helpers/sysfs.h"
19 unsigned int sysfs_read_file(const char *path, char *buf, size_t buflen)
24 fd = open(path, O_RDONLY);
28 numread = read(fd, buf, buflen - 1);
37 return (unsigned int) numread;
41 * Detect whether a CPU is online
44 * 1 -> if CPU is online
45 * 0 -> if CPU is offline
46 * negative errno values in error case
48 int sysfs_is_cpu_online(unsigned int cpu)
50 char path[SYSFS_PATH_MAX];
53 unsigned long long value;
54 char linebuf[MAX_LINE_LEN];
58 snprintf(path, sizeof(path), PATH_TO_CPU "cpu%u", cpu);
60 if (stat(path, &statbuf) != 0)
64 * kernel without CONFIG_HOTPLUG_CPU
65 * -> cpuX directory exists, but not cpuX/online file
67 snprintf(path, sizeof(path), PATH_TO_CPU "cpu%u/online", cpu);
68 if (stat(path, &statbuf) != 0)
71 fd = open(path, O_RDONLY);
75 numread = read(fd, linebuf, MAX_LINE_LEN - 1);
80 linebuf[numread] = '\0';
83 value = strtoull(linebuf, &endp, 0);
84 if (value > 1 || value < 0)
90 /* CPUidle idlestate specific /sys/devices/system/cpu/cpuX/cpuidle/ access */
93 * helper function to read file from /sys into given buffer
94 * fname is a relative path under "cpuX/cpuidle/stateX/" dir
95 * cstates starting with 0, C0 is not counted as cstate.
96 * This means if you want C1 info, pass 0 as idlestate param
98 unsigned int sysfs_idlestate_read_file(unsigned int cpu, unsigned int idlestate,
99 const char *fname, char *buf, size_t buflen)
101 char path[SYSFS_PATH_MAX];
105 snprintf(path, sizeof(path), PATH_TO_CPU "cpu%u/cpuidle/state%u/%s",
106 cpu, idlestate, fname);
108 fd = open(path, O_RDONLY);
112 numread = read(fd, buf, buflen - 1);
121 return (unsigned int) numread;
124 /* read access to files which contain one numeric value */
126 enum idlestate_value {
131 MAX_IDLESTATE_VALUE_FILES
134 static const char *idlestate_value_files[MAX_IDLESTATE_VALUE_FILES] = {
135 [IDLESTATE_USAGE] = "usage",
136 [IDLESTATE_POWER] = "power",
137 [IDLESTATE_LATENCY] = "latency",
138 [IDLESTATE_TIME] = "time",
141 static unsigned long long sysfs_idlestate_get_one_value(unsigned int cpu,
142 unsigned int idlestate,
143 enum idlestate_value which)
145 unsigned long long value;
147 char linebuf[MAX_LINE_LEN];
150 if (which >= MAX_IDLESTATE_VALUE_FILES)
153 len = sysfs_idlestate_read_file(cpu, idlestate,
154 idlestate_value_files[which],
155 linebuf, sizeof(linebuf));
159 value = strtoull(linebuf, &endp, 0);
161 if (endp == linebuf || errno == ERANGE)
167 /* read access to files which contain one string */
169 enum idlestate_string {
172 MAX_IDLESTATE_STRING_FILES
175 static const char *idlestate_string_files[MAX_IDLESTATE_STRING_FILES] = {
176 [IDLESTATE_DESC] = "desc",
177 [IDLESTATE_NAME] = "name",
181 static char *sysfs_idlestate_get_one_string(unsigned int cpu,
182 unsigned int idlestate,
183 enum idlestate_string which)
185 char linebuf[MAX_LINE_LEN];
189 if (which >= MAX_IDLESTATE_STRING_FILES)
192 len = sysfs_idlestate_read_file(cpu, idlestate,
193 idlestate_string_files[which],
194 linebuf, sizeof(linebuf));
198 result = strdup(linebuf);
202 if (result[strlen(result) - 1] == '\n')
203 result[strlen(result) - 1] = '\0';
208 unsigned long sysfs_get_idlestate_latency(unsigned int cpu,
209 unsigned int idlestate)
211 return sysfs_idlestate_get_one_value(cpu, idlestate, IDLESTATE_LATENCY);
214 unsigned long sysfs_get_idlestate_usage(unsigned int cpu,
215 unsigned int idlestate)
217 return sysfs_idlestate_get_one_value(cpu, idlestate, IDLESTATE_USAGE);
220 unsigned long long sysfs_get_idlestate_time(unsigned int cpu,
221 unsigned int idlestate)
223 return sysfs_idlestate_get_one_value(cpu, idlestate, IDLESTATE_TIME);
226 char *sysfs_get_idlestate_name(unsigned int cpu, unsigned int idlestate)
228 return sysfs_idlestate_get_one_string(cpu, idlestate, IDLESTATE_NAME);
231 char *sysfs_get_idlestate_desc(unsigned int cpu, unsigned int idlestate)
233 return sysfs_idlestate_get_one_string(cpu, idlestate, IDLESTATE_DESC);
237 * Returns number of supported C-states of CPU core cpu
238 * Negativ in error case
239 * Zero if cpuidle does not export any C-states
241 unsigned int sysfs_get_idlestate_count(unsigned int cpu)
243 char file[SYSFS_PATH_MAX];
248 snprintf(file, SYSFS_PATH_MAX, PATH_TO_CPU "cpuidle");
249 if (stat(file, &statbuf) != 0 || !S_ISDIR(statbuf.st_mode))
252 snprintf(file, SYSFS_PATH_MAX, PATH_TO_CPU "cpu%u/cpuidle/state0", cpu);
253 if (stat(file, &statbuf) != 0 || !S_ISDIR(statbuf.st_mode))
256 while (stat(file, &statbuf) == 0 && S_ISDIR(statbuf.st_mode)) {
257 snprintf(file, SYSFS_PATH_MAX, PATH_TO_CPU
258 "cpu%u/cpuidle/state%d", cpu, idlestates);
265 /* CPUidle general /sys/devices/system/cpu/cpuidle/ sysfs access ********/
268 * helper function to read file from /sys into given buffer
269 * fname is a relative path under "cpu/cpuidle/" dir
271 static unsigned int sysfs_cpuidle_read_file(const char *fname, char *buf,
274 char path[SYSFS_PATH_MAX];
276 snprintf(path, sizeof(path), PATH_TO_CPU "cpuidle/%s", fname);
278 return sysfs_read_file(path, buf, buflen);
283 /* read access to files which contain one string */
285 enum cpuidle_string {
289 MAX_CPUIDLE_STRING_FILES
292 static const char *cpuidle_string_files[MAX_CPUIDLE_STRING_FILES] = {
293 [CPUIDLE_GOVERNOR] = "current_governor",
294 [CPUIDLE_GOVERNOR_RO] = "current_governor_ro",
295 [CPUIDLE_DRIVER] = "current_driver",
299 static char *sysfs_cpuidle_get_one_string(enum cpuidle_string which)
301 char linebuf[MAX_LINE_LEN];
305 if (which >= MAX_CPUIDLE_STRING_FILES)
308 len = sysfs_cpuidle_read_file(cpuidle_string_files[which],
309 linebuf, sizeof(linebuf));
313 result = strdup(linebuf);
317 if (result[strlen(result) - 1] == '\n')
318 result[strlen(result) - 1] = '\0';
323 char *sysfs_get_cpuidle_governor(void)
325 char *tmp = sysfs_cpuidle_get_one_string(CPUIDLE_GOVERNOR_RO);
327 return sysfs_cpuidle_get_one_string(CPUIDLE_GOVERNOR);
332 char *sysfs_get_cpuidle_driver(void)
334 return sysfs_cpuidle_get_one_string(CPUIDLE_DRIVER);
336 /* CPUidle idlestate specific /sys/devices/system/cpu/cpuX/cpuidle/ access */
339 * Get sched_mc or sched_smt settings
340 * Pass "mc" or "smt" as argument
342 * Returns negative value on failure
344 int sysfs_get_sched(const char *smt_mc)
350 * Get sched_mc or sched_smt settings
351 * Pass "mc" or "smt" as argument
353 * Returns negative value on failure
355 int sysfs_set_sched(const char *smt_mc, int val)