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 if ( ( fd
= open(path
, O_RDONLY
) ) == -1 )
27 numread
= read(fd
, buf
, buflen
- 1);
40 static unsigned int sysfs_write_file(const char *path
,
41 const char *value
, size_t len
)
46 if ( ( fd
= open(path
, O_WRONLY
) ) == -1 )
49 numwrite
= write(fd
, value
, len
);
59 /* CPUidle idlestate specific /sys/devices/system/cpu/cpuX/cpuidle/ access */
62 * helper function to read file from /sys into given buffer
63 * fname is a relative path under "cpuX/cpuidle/stateX/" dir
64 * cstates starting with 0, C0 is not counted as cstate.
65 * This means if you want C1 info, pass 0 as idlestate param
67 unsigned int sysfs_idlestate_read_file(unsigned int cpu
, unsigned int idlestate
,
68 const char *fname
, char *buf
, size_t buflen
)
70 char path
[SYSFS_PATH_MAX
];
74 snprintf(path
, sizeof(path
), PATH_TO_CPU
"cpu%u/cpuidle/state%u/%s",
75 cpu
, idlestate
, fname
);
77 if ( ( fd
= open(path
, O_RDONLY
) ) == -1 )
80 numread
= read(fd
, buf
, buflen
- 1);
93 /* read access to files which contain one numeric value */
95 enum idlestate_value
{
100 MAX_IDLESTATE_VALUE_FILES
103 static const char *idlestate_value_files
[MAX_IDLESTATE_VALUE_FILES
] = {
104 [IDLESTATE_USAGE
] = "usage",
105 [IDLESTATE_POWER
] = "power",
106 [IDLESTATE_LATENCY
] = "latency",
107 [IDLESTATE_TIME
] = "time",
110 static unsigned long long sysfs_idlestate_get_one_value(unsigned int cpu
,
111 unsigned int idlestate
,
112 enum idlestate_value which
)
114 unsigned long long value
;
116 char linebuf
[MAX_LINE_LEN
];
119 if ( which
>= MAX_IDLESTATE_VALUE_FILES
)
122 if ( ( len
= sysfs_idlestate_read_file(cpu
, idlestate
,
123 idlestate_value_files
[which
],
124 linebuf
, sizeof(linebuf
))) == 0 )
129 value
= strtoull(linebuf
, &endp
, 0);
131 if ( endp
== linebuf
|| errno
== ERANGE
)
137 /* read access to files which contain one string */
139 enum idlestate_string
{
142 MAX_IDLESTATE_STRING_FILES
145 static const char *idlestate_string_files
[MAX_IDLESTATE_STRING_FILES
] = {
146 [IDLESTATE_DESC
] = "desc",
147 [IDLESTATE_NAME
] = "name",
151 static char * sysfs_idlestate_get_one_string(unsigned int cpu
,
152 unsigned int idlestate
,
153 enum idlestate_string which
)
155 char linebuf
[MAX_LINE_LEN
];
159 if (which
>= MAX_IDLESTATE_STRING_FILES
)
162 if ( ( len
= sysfs_idlestate_read_file(cpu
, idlestate
,
163 idlestate_string_files
[which
],
164 linebuf
, sizeof(linebuf
))) == 0 )
167 if ( ( result
= strdup(linebuf
) ) == NULL
)
170 if (result
[strlen(result
) - 1] == '\n')
171 result
[strlen(result
) - 1] = '\0';
176 unsigned long sysfs_get_idlestate_latency(unsigned int cpu
, unsigned int idlestate
)
178 return sysfs_idlestate_get_one_value(cpu
, idlestate
, IDLESTATE_LATENCY
);
181 unsigned long sysfs_get_idlestate_usage(unsigned int cpu
, unsigned int idlestate
)
183 return sysfs_idlestate_get_one_value(cpu
, idlestate
, IDLESTATE_USAGE
);
186 unsigned long long sysfs_get_idlestate_time(unsigned int cpu
, unsigned int idlestate
)
188 return sysfs_idlestate_get_one_value(cpu
, idlestate
, IDLESTATE_TIME
);
191 char * sysfs_get_idlestate_name(unsigned int cpu
, unsigned int idlestate
)
193 return sysfs_idlestate_get_one_string(cpu
, idlestate
, IDLESTATE_NAME
);
196 char * sysfs_get_idlestate_desc(unsigned int cpu
, unsigned int idlestate
)
198 return sysfs_idlestate_get_one_string(cpu
, idlestate
, IDLESTATE_DESC
);
202 * Returns number of supported C-states of CPU core cpu
203 * Negativ in error case
204 * Zero if cpuidle does not export any C-states
206 int sysfs_get_idlestate_count(unsigned int cpu
)
208 char file
[SYSFS_PATH_MAX
];
213 snprintf(file
, SYSFS_PATH_MAX
, PATH_TO_CPU
"cpuidle");
214 if ( stat(file
, &statbuf
) != 0 || !S_ISDIR(statbuf
.st_mode
))
217 snprintf(file
, SYSFS_PATH_MAX
, PATH_TO_CPU
"cpu%u/cpuidle/state0", cpu
);
218 if ( stat(file
, &statbuf
) != 0 || !S_ISDIR(statbuf
.st_mode
))
221 while(stat(file
, &statbuf
) == 0 && S_ISDIR(statbuf
.st_mode
)) {
222 snprintf(file
, SYSFS_PATH_MAX
, PATH_TO_CPU
223 "cpu%u/cpuidle/state%d", cpu
, idlestates
);
230 /* CPUidle general /sys/devices/system/cpu/cpuidle/ sysfs access ********/
233 * helper function to read file from /sys into given buffer
234 * fname is a relative path under "cpu/cpuidle/" dir
236 static unsigned int sysfs_cpuidle_read_file(const char *fname
, char *buf
,
239 char path
[SYSFS_PATH_MAX
];
241 snprintf(path
, sizeof(path
), PATH_TO_CPU
"cpuidle/%s", fname
);
243 return sysfs_read_file(path
, buf
, buflen
);
248 /* read access to files which contain one string */
250 enum cpuidle_string
{
254 MAX_CPUIDLE_STRING_FILES
257 static const char *cpuidle_string_files
[MAX_CPUIDLE_STRING_FILES
] = {
258 [CPUIDLE_GOVERNOR
] = "current_governor",
259 [CPUIDLE_GOVERNOR_RO
] = "current_governor_ro",
260 [CPUIDLE_DRIVER
] = "current_driver",
264 static char * sysfs_cpuidle_get_one_string(enum cpuidle_string which
)
266 char linebuf
[MAX_LINE_LEN
];
270 if (which
>= MAX_CPUIDLE_STRING_FILES
)
273 if ( ( len
= sysfs_cpuidle_read_file(cpuidle_string_files
[which
],
274 linebuf
, sizeof(linebuf
))) == 0 )
277 if ( ( result
= strdup(linebuf
) ) == NULL
)
280 if (result
[strlen(result
) - 1] == '\n')
281 result
[strlen(result
) - 1] = '\0';
286 char * sysfs_get_cpuidle_governor(void)
288 char *tmp
= sysfs_cpuidle_get_one_string(CPUIDLE_GOVERNOR_RO
);
290 return sysfs_cpuidle_get_one_string(CPUIDLE_GOVERNOR
);
295 char * sysfs_get_cpuidle_driver(void)
297 return sysfs_cpuidle_get_one_string(CPUIDLE_DRIVER
);
299 /* CPUidle idlestate specific /sys/devices/system/cpu/cpuX/cpuidle/ access */
302 * Get sched_mc or sched_smt settings
303 * Pass "mc" or "smt" as argument
305 * Returns negative value on failure
307 int sysfs_get_sched(const char* smt_mc
)
310 char linebuf
[MAX_LINE_LEN
];
312 char path
[SYSFS_PATH_MAX
];
314 if (strcmp("mc", smt_mc
) && strcmp("smt", smt_mc
))
317 snprintf(path
, sizeof(path
), PATH_TO_CPU
"sched_%s_power_savings", smt_mc
);
318 if (sysfs_read_file(path
, linebuf
, MAX_LINE_LEN
) == 0 )
320 value
= strtoul(linebuf
, &endp
, 0);
321 if ( endp
== linebuf
|| errno
== ERANGE
)
327 * Get sched_mc or sched_smt settings
328 * Pass "mc" or "smt" as argument
330 * Returns negative value on failure
332 int sysfs_set_sched(const char* smt_mc
, int val
)
334 char linebuf
[MAX_LINE_LEN
];
335 char path
[SYSFS_PATH_MAX
];
338 if (strcmp("mc", smt_mc
) && strcmp("smt", smt_mc
))
341 snprintf(path
, sizeof(path
), PATH_TO_CPU
"sched_%s_power_savings", smt_mc
);
342 sprintf(linebuf
, "%d", val
);
344 if ( stat(path
, &statbuf
) != 0 )
347 if (sysfs_write_file(path
, linebuf
, MAX_LINE_LEN
) == 0 )