~ [ source navigation ] ~ [ diff markup ] ~ [ identifier search ] ~

TOMOYO Linux Cross Reference
Linux/tools/power/cpupower/utils/helpers/sysfs.c

Version: ~ [ linux-5.5 ] ~ [ linux-5.4.15 ] ~ [ linux-5.3.18 ] ~ [ linux-5.2.21 ] ~ [ linux-5.1.21 ] ~ [ linux-5.0.21 ] ~ [ linux-4.20.17 ] ~ [ linux-4.19.98 ] ~ [ linux-4.18.20 ] ~ [ linux-4.17.19 ] ~ [ linux-4.16.18 ] ~ [ linux-4.15.18 ] ~ [ linux-4.14.167 ] ~ [ linux-4.13.16 ] ~ [ linux-4.12.14 ] ~ [ linux-4.11.12 ] ~ [ linux-4.10.17 ] ~ [ linux-4.9.211 ] ~ [ linux-4.8.17 ] ~ [ linux-4.7.10 ] ~ [ linux-4.6.7 ] ~ [ linux-4.5.7 ] ~ [ linux-4.4.211 ] ~ [ linux-4.3.6 ] ~ [ linux-4.2.8 ] ~ [ linux-4.1.52 ] ~ [ linux-4.0.9 ] ~ [ linux-3.19.8 ] ~ [ linux-3.18.140 ] ~ [ linux-3.17.8 ] ~ [ linux-3.16.81 ] ~ [ linux-3.15.10 ] ~ [ linux-3.14.79 ] ~ [ linux-3.13.11 ] ~ [ linux-3.12.74 ] ~ [ linux-3.11.10 ] ~ [ linux-3.10.108 ] ~ [ linux-3.9.11 ] ~ [ linux-3.8.13 ] ~ [ linux-3.7.10 ] ~ [ linux-3.6.11 ] ~ [ linux-3.5.7 ] ~ [ linux-3.4.113 ] ~ [ linux-3.3.8 ] ~ [ linux-3.2.102 ] ~ [ linux-3.1.10 ] ~ [ linux-3.0.101 ] ~ [ linux-2.6.32.71 ] ~ [ linux-2.6.0 ] ~ [ linux-2.4.37.11 ] ~ [ unix-v6-master ] ~ [ ccs-tools-1.8.5 ] ~ [ policy-sample ] ~
Architecture: ~ [ i386 ] ~ [ alpha ] ~ [ m68k ] ~ [ mips ] ~ [ ppc ] ~ [ sparc ] ~ [ sparc64 ] ~

  1 /*
  2  *  (C) 2004-2009  Dominik Brodowski <linux@dominikbrodowski.de>
  3  *  (C) 2011       Thomas Renninger <trenn@novell.com> Novell Inc.
  4  *
  5  *  Licensed under the terms of the GNU GPL License version 2.
  6  */
  7 
  8 #include <stdio.h>
  9 #include <errno.h>
 10 #include <stdlib.h>
 11 #include <string.h>
 12 #include <sys/types.h>
 13 #include <sys/stat.h>
 14 #include <fcntl.h>
 15 #include <unistd.h>
 16 
 17 #include "helpers/sysfs.h"
 18 
 19 unsigned int sysfs_read_file(const char *path, char *buf, size_t buflen)
 20 {
 21         int fd;
 22         ssize_t numread;
 23 
 24         fd = open(path, O_RDONLY);
 25         if (fd == -1)
 26                 return 0;
 27 
 28         numread = read(fd, buf, buflen - 1);
 29         if (numread < 1) {
 30                 close(fd);
 31                 return 0;
 32         }
 33 
 34         buf[numread] = '\0';
 35         close(fd);
 36 
 37         return (unsigned int) numread;
 38 }
 39 
 40 /*
 41  * Detect whether a CPU is online
 42  *
 43  * Returns:
 44  *     1 -> if CPU is online
 45  *     0 -> if CPU is offline
 46  *     negative errno values in error case
 47  */
 48 int sysfs_is_cpu_online(unsigned int cpu)
 49 {
 50         char path[SYSFS_PATH_MAX];
 51         int fd;
 52         ssize_t numread;
 53         unsigned long long value;
 54         char linebuf[MAX_LINE_LEN];
 55         char *endp;
 56         struct stat statbuf;
 57 
 58         snprintf(path, sizeof(path), PATH_TO_CPU "cpu%u", cpu);
 59 
 60         if (stat(path, &statbuf) != 0)
 61                 return 0;
 62 
 63         /*
 64          * kernel without CONFIG_HOTPLUG_CPU
 65          * -> cpuX directory exists, but not cpuX/online file
 66          */
 67         snprintf(path, sizeof(path), PATH_TO_CPU "cpu%u/online", cpu);
 68         if (stat(path, &statbuf) != 0)
 69                 return 1;
 70 
 71         fd = open(path, O_RDONLY);
 72         if (fd == -1)
 73                 return -errno;
 74 
 75         numread = read(fd, linebuf, MAX_LINE_LEN - 1);
 76         if (numread < 1) {
 77                 close(fd);
 78                 return -EIO;
 79         }
 80         linebuf[numread] = '\0';
 81         close(fd);
 82 
 83         value = strtoull(linebuf, &endp, 0);
 84         if (value > 1)
 85                 return -EINVAL;
 86 
 87         return value;
 88 }
 89 
 90 /* CPUidle idlestate specific /sys/devices/system/cpu/cpuX/cpuidle/ access */
 91 
 92 
 93 /* CPUidle idlestate specific /sys/devices/system/cpu/cpuX/cpuidle/ access */
 94 
 95 /*
 96  * helper function to check whether a file under "../cpuX/cpuidle/stateX/" dir
 97  * exists.
 98  * For example the functionality to disable c-states was introduced in later
 99  * kernel versions, this function can be used to explicitly check for this
100  * feature.
101  *
102  * returns 1 if the file exists, 0 otherwise.
103  */
104 unsigned int sysfs_idlestate_file_exists(unsigned int cpu,
105                                          unsigned int idlestate,
106                                          const char *fname)
107 {
108         char path[SYSFS_PATH_MAX];
109         struct stat statbuf;
110 
111 
112         snprintf(path, sizeof(path), PATH_TO_CPU "cpu%u/cpuidle/state%u/%s",
113                  cpu, idlestate, fname);
114         if (stat(path, &statbuf) != 0)
115                 return 0;
116         return 1;
117 }
118 
119 /*
120  * helper function to read file from /sys into given buffer
121  * fname is a relative path under "cpuX/cpuidle/stateX/" dir
122  * cstates starting with 0, C0 is not counted as cstate.
123  * This means if you want C1 info, pass 0 as idlestate param
124  */
125 unsigned int sysfs_idlestate_read_file(unsigned int cpu, unsigned int idlestate,
126                              const char *fname, char *buf, size_t buflen)
127 {
128         char path[SYSFS_PATH_MAX];
129         int fd;
130         ssize_t numread;
131 
132         snprintf(path, sizeof(path), PATH_TO_CPU "cpu%u/cpuidle/state%u/%s",
133                  cpu, idlestate, fname);
134 
135         fd = open(path, O_RDONLY);
136         if (fd == -1)
137                 return 0;
138 
139         numread = read(fd, buf, buflen - 1);
140         if (numread < 1) {
141                 close(fd);
142                 return 0;
143         }
144 
145         buf[numread] = '\0';
146         close(fd);
147 
148         return (unsigned int) numread;
149 }
150 
151 /* 
152  * helper function to write a new value to a /sys file
153  * fname is a relative path under "../cpuX/cpuidle/cstateY/" dir
154  *
155  * Returns the number of bytes written or 0 on error
156  */
157 static
158 unsigned int sysfs_idlestate_write_file(unsigned int cpu,
159                                         unsigned int idlestate,
160                                         const char *fname,
161                                         const char *value, size_t len)
162 {
163         char path[SYSFS_PATH_MAX];
164         int fd;
165         ssize_t numwrite;
166 
167         snprintf(path, sizeof(path), PATH_TO_CPU "cpu%u/cpuidle/state%u/%s",
168                  cpu, idlestate, fname);
169 
170         fd = open(path, O_WRONLY);
171         if (fd == -1)
172                 return 0;
173 
174         numwrite = write(fd, value, len);
175         if (numwrite < 1) {
176                 close(fd);
177                 return 0;
178         }
179 
180         close(fd);
181 
182         return (unsigned int) numwrite;
183 }
184 
185 /* read access to files which contain one numeric value */
186 
187 enum idlestate_value {
188         IDLESTATE_USAGE,
189         IDLESTATE_POWER,
190         IDLESTATE_LATENCY,
191         IDLESTATE_TIME,
192         IDLESTATE_DISABLE,
193         MAX_IDLESTATE_VALUE_FILES
194 };
195 
196 static const char *idlestate_value_files[MAX_IDLESTATE_VALUE_FILES] = {
197         [IDLESTATE_USAGE] = "usage",
198         [IDLESTATE_POWER] = "power",
199         [IDLESTATE_LATENCY] = "latency",
200         [IDLESTATE_TIME]  = "time",
201         [IDLESTATE_DISABLE]  = "disable",
202 };
203 
204 static unsigned long long sysfs_idlestate_get_one_value(unsigned int cpu,
205                                                      unsigned int idlestate,
206                                                      enum idlestate_value which)
207 {
208         unsigned long long value;
209         unsigned int len;
210         char linebuf[MAX_LINE_LEN];
211         char *endp;
212 
213         if (which >= MAX_IDLESTATE_VALUE_FILES)
214                 return 0;
215 
216         len = sysfs_idlestate_read_file(cpu, idlestate,
217                                         idlestate_value_files[which],
218                                         linebuf, sizeof(linebuf));
219         if (len == 0)
220                 return 0;
221 
222         value = strtoull(linebuf, &endp, 0);
223 
224         if (endp == linebuf || errno == ERANGE)
225                 return 0;
226 
227         return value;
228 }
229 
230 /* read access to files which contain one string */
231 
232 enum idlestate_string {
233         IDLESTATE_DESC,
234         IDLESTATE_NAME,
235         MAX_IDLESTATE_STRING_FILES
236 };
237 
238 static const char *idlestate_string_files[MAX_IDLESTATE_STRING_FILES] = {
239         [IDLESTATE_DESC] = "desc",
240         [IDLESTATE_NAME] = "name",
241 };
242 
243 
244 static char *sysfs_idlestate_get_one_string(unsigned int cpu,
245                                         unsigned int idlestate,
246                                         enum idlestate_string which)
247 {
248         char linebuf[MAX_LINE_LEN];
249         char *result;
250         unsigned int len;
251 
252         if (which >= MAX_IDLESTATE_STRING_FILES)
253                 return NULL;
254 
255         len = sysfs_idlestate_read_file(cpu, idlestate,
256                                         idlestate_string_files[which],
257                                         linebuf, sizeof(linebuf));
258         if (len == 0)
259                 return NULL;
260 
261         result = strdup(linebuf);
262         if (result == NULL)
263                 return NULL;
264 
265         if (result[strlen(result) - 1] == '\n')
266                 result[strlen(result) - 1] = '\0';
267 
268         return result;
269 }
270 
271 /*
272  * Returns:
273  *    1  if disabled
274  *    0  if enabled
275  *    -1 if idlestate is not available
276  *    -2 if disabling is not supported by the kernel
277  */
278 int sysfs_is_idlestate_disabled(unsigned int cpu,
279                                 unsigned int idlestate)
280 {
281         if (sysfs_get_idlestate_count(cpu) <= idlestate)
282                 return -1;
283 
284         if (!sysfs_idlestate_file_exists(cpu, idlestate,
285                                  idlestate_value_files[IDLESTATE_DISABLE]))
286                 return -2;
287         return sysfs_idlestate_get_one_value(cpu, idlestate, IDLESTATE_DISABLE);
288 }
289 
290 /*
291  * Pass 1 as last argument to disable or 0 to enable the state
292  * Returns:
293  *    0  on success
294  *    negative values on error, for example:
295  *      -1 if idlestate is not available
296  *      -2 if disabling is not supported by the kernel
297  *      -3 No write access to disable/enable C-states
298  */
299 int sysfs_idlestate_disable(unsigned int cpu,
300                             unsigned int idlestate,
301                             unsigned int disable)
302 {
303         char value[SYSFS_PATH_MAX];
304         int bytes_written;
305 
306         if (sysfs_get_idlestate_count(cpu) <= idlestate)
307                 return -1;
308 
309         if (!sysfs_idlestate_file_exists(cpu, idlestate,
310                                  idlestate_value_files[IDLESTATE_DISABLE]))
311                 return -2;
312 
313         snprintf(value, SYSFS_PATH_MAX, "%u", disable);
314 
315         bytes_written = sysfs_idlestate_write_file(cpu, idlestate, "disable",
316                                                    value, sizeof(disable));
317         if (bytes_written)
318                 return 0;
319         return -3;
320 }
321 
322 unsigned long sysfs_get_idlestate_latency(unsigned int cpu,
323                                           unsigned int idlestate)
324 {
325         return sysfs_idlestate_get_one_value(cpu, idlestate, IDLESTATE_LATENCY);
326 }
327 
328 unsigned long sysfs_get_idlestate_usage(unsigned int cpu,
329                                         unsigned int idlestate)
330 {
331         return sysfs_idlestate_get_one_value(cpu, idlestate, IDLESTATE_USAGE);
332 }
333 
334 unsigned long long sysfs_get_idlestate_time(unsigned int cpu,
335                                         unsigned int idlestate)
336 {
337         return sysfs_idlestate_get_one_value(cpu, idlestate, IDLESTATE_TIME);
338 }
339 
340 char *sysfs_get_idlestate_name(unsigned int cpu, unsigned int idlestate)
341 {
342         return sysfs_idlestate_get_one_string(cpu, idlestate, IDLESTATE_NAME);
343 }
344 
345 char *sysfs_get_idlestate_desc(unsigned int cpu, unsigned int idlestate)
346 {
347         return sysfs_idlestate_get_one_string(cpu, idlestate, IDLESTATE_DESC);
348 }
349 
350 /*
351  * Returns number of supported C-states of CPU core cpu
352  * Negativ in error case
353  * Zero if cpuidle does not export any C-states
354  */
355 unsigned int sysfs_get_idlestate_count(unsigned int cpu)
356 {
357         char file[SYSFS_PATH_MAX];
358         struct stat statbuf;
359         int idlestates = 1;
360 
361 
362         snprintf(file, SYSFS_PATH_MAX, PATH_TO_CPU "cpuidle");
363         if (stat(file, &statbuf) != 0 || !S_ISDIR(statbuf.st_mode))
364                 return -ENODEV;
365 
366         snprintf(file, SYSFS_PATH_MAX, PATH_TO_CPU "cpu%u/cpuidle/state0", cpu);
367         if (stat(file, &statbuf) != 0 || !S_ISDIR(statbuf.st_mode))
368                 return 0;
369 
370         while (stat(file, &statbuf) == 0 && S_ISDIR(statbuf.st_mode)) {
371                 snprintf(file, SYSFS_PATH_MAX, PATH_TO_CPU
372                          "cpu%u/cpuidle/state%d", cpu, idlestates);
373                 idlestates++;
374         }
375         idlestates--;
376         return idlestates;
377 }
378 
379 /* CPUidle general /sys/devices/system/cpu/cpuidle/ sysfs access ********/
380 
381 /*
382  * helper function to read file from /sys into given buffer
383  * fname is a relative path under "cpu/cpuidle/" dir
384  */
385 static unsigned int sysfs_cpuidle_read_file(const char *fname, char *buf,
386                                             size_t buflen)
387 {
388         char path[SYSFS_PATH_MAX];
389 
390         snprintf(path, sizeof(path), PATH_TO_CPU "cpuidle/%s", fname);
391 
392         return sysfs_read_file(path, buf, buflen);
393 }
394 
395 
396 
397 /* read access to files which contain one string */
398 
399 enum cpuidle_string {
400         CPUIDLE_GOVERNOR,
401         CPUIDLE_GOVERNOR_RO,
402         CPUIDLE_DRIVER,
403         MAX_CPUIDLE_STRING_FILES
404 };
405 
406 static const char *cpuidle_string_files[MAX_CPUIDLE_STRING_FILES] = {
407         [CPUIDLE_GOVERNOR]      = "current_governor",
408         [CPUIDLE_GOVERNOR_RO]   = "current_governor_ro",
409         [CPUIDLE_DRIVER]        = "current_driver",
410 };
411 
412 
413 static char *sysfs_cpuidle_get_one_string(enum cpuidle_string which)
414 {
415         char linebuf[MAX_LINE_LEN];
416         char *result;
417         unsigned int len;
418 
419         if (which >= MAX_CPUIDLE_STRING_FILES)
420                 return NULL;
421 
422         len = sysfs_cpuidle_read_file(cpuidle_string_files[which],
423                                 linebuf, sizeof(linebuf));
424         if (len == 0)
425                 return NULL;
426 
427         result = strdup(linebuf);
428         if (result == NULL)
429                 return NULL;
430 
431         if (result[strlen(result) - 1] == '\n')
432                 result[strlen(result) - 1] = '\0';
433 
434         return result;
435 }
436 
437 char *sysfs_get_cpuidle_governor(void)
438 {
439         char *tmp = sysfs_cpuidle_get_one_string(CPUIDLE_GOVERNOR_RO);
440         if (!tmp)
441                 return sysfs_cpuidle_get_one_string(CPUIDLE_GOVERNOR);
442         else
443                 return tmp;
444 }
445 
446 char *sysfs_get_cpuidle_driver(void)
447 {
448         return sysfs_cpuidle_get_one_string(CPUIDLE_DRIVER);
449 }
450 /* CPUidle idlestate specific /sys/devices/system/cpu/cpuX/cpuidle/ access */
451 
452 /*
453  * Get sched_mc or sched_smt settings
454  * Pass "mc" or "smt" as argument
455  *
456  * Returns negative value on failure
457  */
458 int sysfs_get_sched(const char *smt_mc)
459 {
460         return -ENODEV;
461 }
462 
463 /*
464  * Get sched_mc or sched_smt settings
465  * Pass "mc" or "smt" as argument
466  *
467  * Returns negative value on failure
468  */
469 int sysfs_set_sched(const char *smt_mc, int val)
470 {
471         return -ENODEV;
472 }
473 

~ [ source navigation ] ~ [ diff markup ] ~ [ identifier search ] ~

kernel.org | git.kernel.org | LWN.net | Project Home | Wiki (Japanese) | Wiki (English) | SVN repository | Mail admin

Linux® is a registered trademark of Linus Torvalds in the United States and other countries.
TOMOYO® is a registered trademark of NTT DATA CORPORATION.

osdn.jp