aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorThomas Renninger <trenn@suse.com>2016-04-28 09:24:40 -0400
committerRafael J. Wysocki <rafael.j.wysocki@intel.com>2016-04-28 10:02:29 -0400
commitac5a181d065d74fb6b213d538f743392f27bcdbd (patch)
treece5eab193a80e4514c1ebe931c391af57741a99d
parentfe7656a8e8fcb3a0151b36b2f4c66763fa9553ea (diff)
cpupower: Add cpuidle parts into library
This more or less is a renaming and moving of functions and should not introduce any functional change. cpupower was built from cpufrequtils (which had a C library providing easy access to cpu frequency platform info). In the meantime it got enhanced by quite some neat cpuidle userspace tools. Now the cpu idle functions have been separated and added to the cpupower.so library. So beside an already existing public header file: cpufreq.h cpupower now also exports these cpu idle functions in: cpuidle.h Here again pasted for better review of the interfaces: ====================================== int cpuidle_is_state_disabled(unsigned int cpu, unsigned int idlestate); int cpuidle_state_disable(unsigned int cpu, unsigned int idlestate, unsigned int disable); unsigned long cpuidle_state_latency(unsigned int cpu, unsigned int idlestate); unsigned long cpuidle_state_usage(unsigned int cpu, unsigned int idlestate); unsigned long long cpuidle_state_time(unsigned int cpu, unsigned int idlestate); char *cpuidle_state_name(unsigned int cpu, unsigned int idlestate); char *cpuidle_state_desc(unsigned int cpu, unsigned int idlestate); unsigned int cpuidle_state_count(unsigned int cpu); char *cpuidle_get_governor(void); char *cpuidle_get_driver(void); ====================================== Signed-off-by: Thomas Renninger <trenn@suse.com> Signed-off-by: Rafael J. Wysocki <rafael.j.wysocki@intel.com>
-rw-r--r--tools/power/cpupower/Makefile12
-rw-r--r--tools/power/cpupower/bench/system.c3
-rw-r--r--tools/power/cpupower/lib/cpufreq.c550
-rw-r--r--tools/power/cpupower/lib/cpufreq.h59
-rw-r--r--tools/power/cpupower/lib/cpuidle.c380
-rw-r--r--tools/power/cpupower/lib/cpuidle.h23
-rw-r--r--tools/power/cpupower/lib/cpupower.c192
-rw-r--r--tools/power/cpupower/lib/cpupower.h35
-rw-r--r--tools/power/cpupower/lib/cpupower_intern.h5
-rw-r--r--tools/power/cpupower/lib/sysfs.c672
-rw-r--r--tools/power/cpupower/lib/sysfs.h31
-rw-r--r--tools/power/cpupower/utils/cpufreq-set.c8
-rw-r--r--tools/power/cpupower/utils/cpuidle-info.c32
-rw-r--r--tools/power/cpupower/utils/cpuidle-set.c26
-rw-r--r--tools/power/cpupower/utils/helpers/helpers.h26
-rw-r--r--tools/power/cpupower/utils/helpers/topology.c107
-rw-r--r--tools/power/cpupower/utils/idle_monitor/cpuidle_sysfs.c12
17 files changed, 1242 insertions, 931 deletions
diff --git a/tools/power/cpupower/Makefile b/tools/power/cpupower/Makefile
index 0adaf0c7c03a..8358863259c5 100644
--- a/tools/power/cpupower/Makefile
+++ b/tools/power/cpupower/Makefile
@@ -63,7 +63,7 @@ DESTDIR ?=
63# and _should_ modify the PACKAGE_BUGREPORT definition 63# and _should_ modify the PACKAGE_BUGREPORT definition
64 64
65VERSION= $(shell ./utils/version-gen.sh) 65VERSION= $(shell ./utils/version-gen.sh)
66LIB_MAJ= 0.0.0 66LIB_MAJ= 0.0.1
67LIB_MIN= 0 67LIB_MIN= 0
68 68
69PACKAGE = cpupower 69PACKAGE = cpupower
@@ -129,7 +129,7 @@ WARNINGS += -Wshadow
129CFLAGS += -DVERSION=\"$(VERSION)\" -DPACKAGE=\"$(PACKAGE)\" \ 129CFLAGS += -DVERSION=\"$(VERSION)\" -DPACKAGE=\"$(PACKAGE)\" \
130 -DPACKAGE_BUGREPORT=\"$(PACKAGE_BUGREPORT)\" -D_GNU_SOURCE 130 -DPACKAGE_BUGREPORT=\"$(PACKAGE_BUGREPORT)\" -D_GNU_SOURCE
131 131
132UTIL_OBJS = utils/helpers/amd.o utils/helpers/topology.o utils/helpers/msr.o \ 132UTIL_OBJS = utils/helpers/amd.o utils/helpers/msr.o \
133 utils/helpers/sysfs.o utils/helpers/misc.o utils/helpers/cpuid.o \ 133 utils/helpers/sysfs.o utils/helpers/misc.o utils/helpers/cpuid.o \
134 utils/helpers/pci.o utils/helpers/bitmask.o \ 134 utils/helpers/pci.o utils/helpers/bitmask.o \
135 utils/idle_monitor/nhm_idle.o utils/idle_monitor/snb_idle.o \ 135 utils/idle_monitor/nhm_idle.o utils/idle_monitor/snb_idle.o \
@@ -148,9 +148,9 @@ UTIL_HEADERS = utils/helpers/helpers.h utils/idle_monitor/cpupower-monitor.h \
148 utils/helpers/bitmask.h \ 148 utils/helpers/bitmask.h \
149 utils/idle_monitor/idle_monitors.h utils/idle_monitor/idle_monitors.def 149 utils/idle_monitor/idle_monitors.h utils/idle_monitor/idle_monitors.def
150 150
151LIB_HEADERS = lib/cpufreq.h lib/sysfs.h 151LIB_HEADERS = lib/cpufreq.h lib/cpupower.h lib/cpuidle.h
152LIB_SRC = lib/cpufreq.c lib/sysfs.c 152LIB_SRC = lib/cpufreq.c lib/cpupower.c lib/cpuidle.c
153LIB_OBJS = lib/cpufreq.o lib/sysfs.o 153LIB_OBJS = lib/cpufreq.o lib/cpupower.o lib/cpuidle.o
154LIB_OBJS := $(addprefix $(OUTPUT),$(LIB_OBJS)) 154LIB_OBJS := $(addprefix $(OUTPUT),$(LIB_OBJS))
155 155
156CFLAGS += -pipe 156CFLAGS += -pipe
@@ -280,6 +280,7 @@ install-lib:
280 $(CP) $(OUTPUT)libcpupower.so* $(DESTDIR)${libdir}/ 280 $(CP) $(OUTPUT)libcpupower.so* $(DESTDIR)${libdir}/
281 $(INSTALL) -d $(DESTDIR)${includedir} 281 $(INSTALL) -d $(DESTDIR)${includedir}
282 $(INSTALL_DATA) lib/cpufreq.h $(DESTDIR)${includedir}/cpufreq.h 282 $(INSTALL_DATA) lib/cpufreq.h $(DESTDIR)${includedir}/cpufreq.h
283 $(INSTALL_DATA) lib/cpuidle.h $(DESTDIR)${includedir}/cpuidle.h
283 284
284install-tools: 285install-tools:
285 $(INSTALL) -d $(DESTDIR)${bindir} 286 $(INSTALL) -d $(DESTDIR)${bindir}
@@ -315,6 +316,7 @@ endif
315uninstall: 316uninstall:
316 - rm -f $(DESTDIR)${libdir}/libcpupower.* 317 - rm -f $(DESTDIR)${libdir}/libcpupower.*
317 - rm -f $(DESTDIR)${includedir}/cpufreq.h 318 - rm -f $(DESTDIR)${includedir}/cpufreq.h
319 - rm -f $(DESTDIR)${includedir}/cpuidle.h
318 - rm -f $(DESTDIR)${bindir}/utils/cpupower 320 - rm -f $(DESTDIR)${bindir}/utils/cpupower
319 - rm -f $(DESTDIR)${mandir}/man1/cpupower.1 321 - rm -f $(DESTDIR)${mandir}/man1/cpupower.1
320 - rm -f $(DESTDIR)${mandir}/man1/cpupower-frequency-set.1 322 - rm -f $(DESTDIR)${mandir}/man1/cpupower-frequency-set.1
diff --git a/tools/power/cpupower/bench/system.c b/tools/power/cpupower/bench/system.c
index f01e3f4be84c..c25a74ae51ba 100644
--- a/tools/power/cpupower/bench/system.c
+++ b/tools/power/cpupower/bench/system.c
@@ -26,6 +26,7 @@
26#include <sched.h> 26#include <sched.h>
27 27
28#include <cpufreq.h> 28#include <cpufreq.h>
29#include <cpupower.h>
29 30
30#include "config.h" 31#include "config.h"
31#include "system.h" 32#include "system.h"
@@ -60,7 +61,7 @@ int set_cpufreq_governor(char *governor, unsigned int cpu)
60 61
61 dprintf("set %s as cpufreq governor\n", governor); 62 dprintf("set %s as cpufreq governor\n", governor);
62 63
63 if (cpufreq_cpu_exists(cpu) != 0) { 64 if (cpupower_is_cpu_online(cpu) != 0) {
64 perror("cpufreq_cpu_exists"); 65 perror("cpufreq_cpu_exists");
65 fprintf(stderr, "error: cpu %u does not exist\n", cpu); 66 fprintf(stderr, "error: cpu %u does not exist\n", cpu);
66 return -1; 67 return -1;
diff --git a/tools/power/cpupower/lib/cpufreq.c b/tools/power/cpupower/lib/cpufreq.c
index d961101d1cea..1b993fe1ce23 100644
--- a/tools/power/cpupower/lib/cpufreq.c
+++ b/tools/power/cpupower/lib/cpufreq.c
@@ -9,28 +9,190 @@
9#include <errno.h> 9#include <errno.h>
10#include <stdlib.h> 10#include <stdlib.h>
11#include <string.h> 11#include <string.h>
12#include <sys/types.h>
13#include <sys/stat.h>
14#include <fcntl.h>
15#include <unistd.h>
12 16
13#include "cpufreq.h" 17#include "cpufreq.h"
14#include "sysfs.h" 18#include "cpupower_intern.h"
15 19
16int cpufreq_cpu_exists(unsigned int cpu) 20/* CPUFREQ sysfs access **************************************************/
21
22/* helper function to read file from /sys into given buffer */
23/* fname is a relative path under "cpuX/cpufreq" dir */
24static unsigned int sysfs_cpufreq_read_file(unsigned int cpu, const char *fname,
25 char *buf, size_t buflen)
17{ 26{
18 return sysfs_cpu_exists(cpu); 27 char path[SYSFS_PATH_MAX];
28
29 snprintf(path, sizeof(path), PATH_TO_CPU "cpu%u/cpufreq/%s",
30 cpu, fname);
31 return sysfs_read_file(path, buf, buflen);
19} 32}
20 33
34/* helper function to write a new value to a /sys file */
35/* fname is a relative path under "cpuX/cpufreq" dir */
36static unsigned int sysfs_cpufreq_write_file(unsigned int cpu,
37 const char *fname,
38 const char *value, size_t len)
39{
40 char path[SYSFS_PATH_MAX];
41 int fd;
42 ssize_t numwrite;
43
44 snprintf(path, sizeof(path), PATH_TO_CPU "cpu%u/cpufreq/%s",
45 cpu, fname);
46
47 fd = open(path, O_WRONLY);
48 if (fd == -1)
49 return 0;
50
51 numwrite = write(fd, value, len);
52 if (numwrite < 1) {
53 close(fd);
54 return 0;
55 }
56
57 close(fd);
58
59 return (unsigned int) numwrite;
60}
61
62/* read access to files which contain one numeric value */
63
64enum cpufreq_value {
65 CPUINFO_CUR_FREQ,
66 CPUINFO_MIN_FREQ,
67 CPUINFO_MAX_FREQ,
68 CPUINFO_LATENCY,
69 SCALING_CUR_FREQ,
70 SCALING_MIN_FREQ,
71 SCALING_MAX_FREQ,
72 STATS_NUM_TRANSITIONS,
73 MAX_CPUFREQ_VALUE_READ_FILES
74};
75
76static const char *cpufreq_value_files[MAX_CPUFREQ_VALUE_READ_FILES] = {
77 [CPUINFO_CUR_FREQ] = "cpuinfo_cur_freq",
78 [CPUINFO_MIN_FREQ] = "cpuinfo_min_freq",
79 [CPUINFO_MAX_FREQ] = "cpuinfo_max_freq",
80 [CPUINFO_LATENCY] = "cpuinfo_transition_latency",
81 [SCALING_CUR_FREQ] = "scaling_cur_freq",
82 [SCALING_MIN_FREQ] = "scaling_min_freq",
83 [SCALING_MAX_FREQ] = "scaling_max_freq",
84 [STATS_NUM_TRANSITIONS] = "stats/total_trans"
85};
86
87
88static unsigned long sysfs_cpufreq_get_one_value(unsigned int cpu,
89 enum cpufreq_value which)
90{
91 unsigned long value;
92 unsigned int len;
93 char linebuf[MAX_LINE_LEN];
94 char *endp;
95
96 if (which >= MAX_CPUFREQ_VALUE_READ_FILES)
97 return 0;
98
99 len = sysfs_cpufreq_read_file(cpu, cpufreq_value_files[which],
100 linebuf, sizeof(linebuf));
101
102 if (len == 0)
103 return 0;
104
105 value = strtoul(linebuf, &endp, 0);
106
107 if (endp == linebuf || errno == ERANGE)
108 return 0;
109
110 return value;
111}
112
113/* read access to files which contain one string */
114
115enum cpufreq_string {
116 SCALING_DRIVER,
117 SCALING_GOVERNOR,
118 MAX_CPUFREQ_STRING_FILES
119};
120
121static const char *cpufreq_string_files[MAX_CPUFREQ_STRING_FILES] = {
122 [SCALING_DRIVER] = "scaling_driver",
123 [SCALING_GOVERNOR] = "scaling_governor",
124};
125
126
127static char *sysfs_cpufreq_get_one_string(unsigned int cpu,
128 enum cpufreq_string which)
129{
130 char linebuf[MAX_LINE_LEN];
131 char *result;
132 unsigned int len;
133
134 if (which >= MAX_CPUFREQ_STRING_FILES)
135 return NULL;
136
137 len = sysfs_cpufreq_read_file(cpu, cpufreq_string_files[which],
138 linebuf, sizeof(linebuf));
139 if (len == 0)
140 return NULL;
141
142 result = strdup(linebuf);
143 if (result == NULL)
144 return NULL;
145
146 if (result[strlen(result) - 1] == '\n')
147 result[strlen(result) - 1] = '\0';
148
149 return result;
150}
151
152/* write access */
153
154enum cpufreq_write {
155 WRITE_SCALING_MIN_FREQ,
156 WRITE_SCALING_MAX_FREQ,
157 WRITE_SCALING_GOVERNOR,
158 WRITE_SCALING_SET_SPEED,
159 MAX_CPUFREQ_WRITE_FILES
160};
161
162static const char *cpufreq_write_files[MAX_CPUFREQ_WRITE_FILES] = {
163 [WRITE_SCALING_MIN_FREQ] = "scaling_min_freq",
164 [WRITE_SCALING_MAX_FREQ] = "scaling_max_freq",
165 [WRITE_SCALING_GOVERNOR] = "scaling_governor",
166 [WRITE_SCALING_SET_SPEED] = "scaling_setspeed",
167};
168
169static int sysfs_cpufreq_write_one_value(unsigned int cpu,
170 enum cpufreq_write which,
171 const char *new_value, size_t len)
172{
173 if (which >= MAX_CPUFREQ_WRITE_FILES)
174 return 0;
175
176 if (sysfs_cpufreq_write_file(cpu, cpufreq_write_files[which],
177 new_value, len) != len)
178 return -ENODEV;
179
180 return 0;
181};
182
21unsigned long cpufreq_get_freq_kernel(unsigned int cpu) 183unsigned long cpufreq_get_freq_kernel(unsigned int cpu)
22{ 184{
23 return sysfs_get_freq_kernel(cpu); 185 return sysfs_cpufreq_get_one_value(cpu, SCALING_CUR_FREQ);
24} 186}
25 187
26unsigned long cpufreq_get_freq_hardware(unsigned int cpu) 188unsigned long cpufreq_get_freq_hardware(unsigned int cpu)
27{ 189{
28 return sysfs_get_freq_hardware(cpu); 190 return sysfs_cpufreq_get_one_value(cpu, CPUINFO_CUR_FREQ);
29} 191}
30 192
31unsigned long cpufreq_get_transition_latency(unsigned int cpu) 193unsigned long cpufreq_get_transition_latency(unsigned int cpu)
32{ 194{
33 return sysfs_get_freq_transition_latency(cpu); 195 return sysfs_cpufreq_get_one_value(cpu, CPUINFO_LATENCY);
34} 196}
35 197
36int cpufreq_get_hardware_limits(unsigned int cpu, 198int cpufreq_get_hardware_limits(unsigned int cpu,
@@ -39,12 +201,21 @@ int cpufreq_get_hardware_limits(unsigned int cpu,
39{ 201{
40 if ((!min) || (!max)) 202 if ((!min) || (!max))
41 return -EINVAL; 203 return -EINVAL;
42 return sysfs_get_freq_hardware_limits(cpu, min, max); 204
205 *min = sysfs_cpufreq_get_one_value(cpu, CPUINFO_MIN_FREQ);
206 if (!*min)
207 return -ENODEV;
208
209 *max = sysfs_cpufreq_get_one_value(cpu, CPUINFO_MAX_FREQ);
210 if (!*max)
211 return -ENODEV;
212
213 return 0;
43} 214}
44 215
45char *cpufreq_get_driver(unsigned int cpu) 216char *cpufreq_get_driver(unsigned int cpu)
46{ 217{
47 return sysfs_get_freq_driver(cpu); 218 return sysfs_cpufreq_get_one_string(cpu, SCALING_DRIVER);
48} 219}
49 220
50void cpufreq_put_driver(char *ptr) 221void cpufreq_put_driver(char *ptr)
@@ -56,7 +227,26 @@ void cpufreq_put_driver(char *ptr)
56 227
57struct cpufreq_policy *cpufreq_get_policy(unsigned int cpu) 228struct cpufreq_policy *cpufreq_get_policy(unsigned int cpu)
58{ 229{
59 return sysfs_get_freq_policy(cpu); 230 struct cpufreq_policy *policy;
231
232 policy = malloc(sizeof(struct cpufreq_policy));
233 if (!policy)
234 return NULL;
235
236 policy->governor = sysfs_cpufreq_get_one_string(cpu, SCALING_GOVERNOR);
237 if (!policy->governor) {
238 free(policy);
239 return NULL;
240 }
241 policy->min = sysfs_cpufreq_get_one_value(cpu, SCALING_MIN_FREQ);
242 policy->max = sysfs_cpufreq_get_one_value(cpu, SCALING_MAX_FREQ);
243 if ((!policy->min) || (!policy->max)) {
244 free(policy->governor);
245 free(policy);
246 return NULL;
247 }
248
249 return policy;
60} 250}
61 251
62void cpufreq_put_policy(struct cpufreq_policy *policy) 252void cpufreq_put_policy(struct cpufreq_policy *policy)
@@ -72,7 +262,57 @@ void cpufreq_put_policy(struct cpufreq_policy *policy)
72struct cpufreq_available_governors *cpufreq_get_available_governors(unsigned 262struct cpufreq_available_governors *cpufreq_get_available_governors(unsigned
73 int cpu) 263 int cpu)
74{ 264{
75 return sysfs_get_freq_available_governors(cpu); 265 struct cpufreq_available_governors *first = NULL;
266 struct cpufreq_available_governors *current = NULL;
267 char linebuf[MAX_LINE_LEN];
268 unsigned int pos, i;
269 unsigned int len;
270
271 len = sysfs_cpufreq_read_file(cpu, "scaling_available_governors",
272 linebuf, sizeof(linebuf));
273 if (len == 0)
274 return NULL;
275
276 pos = 0;
277 for (i = 0; i < len; i++) {
278 if (linebuf[i] == ' ' || linebuf[i] == '\n') {
279 if (i - pos < 2)
280 continue;
281 if (current) {
282 current->next = malloc(sizeof(*current));
283 if (!current->next)
284 goto error_out;
285 current = current->next;
286 } else {
287 first = malloc(sizeof(*first));
288 if (!first)
289 goto error_out;
290 current = first;
291 }
292 current->first = first;
293 current->next = NULL;
294
295 current->governor = malloc(i - pos + 1);
296 if (!current->governor)
297 goto error_out;
298
299 memcpy(current->governor, linebuf + pos, i - pos);
300 current->governor[i - pos] = '\0';
301 pos = i + 1;
302 }
303 }
304
305 return first;
306
307 error_out:
308 while (first) {
309 current = first->next;
310 if (first->governor)
311 free(first->governor);
312 free(first);
313 first = current;
314 }
315 return NULL;
76} 316}
77 317
78void cpufreq_put_available_governors(struct cpufreq_available_governors *any) 318void cpufreq_put_available_governors(struct cpufreq_available_governors *any)
@@ -96,7 +336,57 @@ void cpufreq_put_available_governors(struct cpufreq_available_governors *any)
96struct cpufreq_available_frequencies 336struct cpufreq_available_frequencies
97*cpufreq_get_available_frequencies(unsigned int cpu) 337*cpufreq_get_available_frequencies(unsigned int cpu)
98{ 338{
99 return sysfs_get_available_frequencies(cpu); 339 struct cpufreq_available_frequencies *first = NULL;
340 struct cpufreq_available_frequencies *current = NULL;
341 char one_value[SYSFS_PATH_MAX];
342 char linebuf[MAX_LINE_LEN];
343 unsigned int pos, i;
344 unsigned int len;
345
346 len = sysfs_cpufreq_read_file(cpu, "scaling_available_frequencies",
347 linebuf, sizeof(linebuf));
348 if (len == 0)
349 return NULL;
350
351 pos = 0;
352 for (i = 0; i < len; i++) {
353 if (linebuf[i] == ' ' || linebuf[i] == '\n') {
354 if (i - pos < 2)
355 continue;
356 if (i - pos >= SYSFS_PATH_MAX)
357 goto error_out;
358 if (current) {
359 current->next = malloc(sizeof(*current));
360 if (!current->next)
361 goto error_out;
362 current = current->next;
363 } else {
364 first = malloc(sizeof(*first));
365 if (!first)
366 goto error_out;
367 current = first;
368 }
369 current->first = first;
370 current->next = NULL;
371
372 memcpy(one_value, linebuf + pos, i - pos);
373 one_value[i - pos] = '\0';
374 if (sscanf(one_value, "%lu", &current->frequency) != 1)
375 goto error_out;
376
377 pos = i + 1;
378 }
379 }
380
381 return first;
382
383 error_out:
384 while (first) {
385 current = first->next;
386 free(first);
387 first = current;
388 }
389 return NULL;
100} 390}
101 391
102void cpufreq_put_available_frequencies(struct cpufreq_available_frequencies 392void cpufreq_put_available_frequencies(struct cpufreq_available_frequencies
@@ -114,10 +404,65 @@ void cpufreq_put_available_frequencies(struct cpufreq_available_frequencies
114 } 404 }
115} 405}
116 406
407static struct cpufreq_affected_cpus *sysfs_get_cpu_list(unsigned int cpu,
408 const char *file)
409{
410 struct cpufreq_affected_cpus *first = NULL;
411 struct cpufreq_affected_cpus *current = NULL;
412 char one_value[SYSFS_PATH_MAX];
413 char linebuf[MAX_LINE_LEN];
414 unsigned int pos, i;
415 unsigned int len;
416
417 len = sysfs_cpufreq_read_file(cpu, file, linebuf, sizeof(linebuf));
418 if (len == 0)
419 return NULL;
420
421 pos = 0;
422 for (i = 0; i < len; i++) {
423 if (i == len || linebuf[i] == ' ' || linebuf[i] == '\n') {
424 if (i - pos < 1)
425 continue;
426 if (i - pos >= SYSFS_PATH_MAX)
427 goto error_out;
428 if (current) {
429 current->next = malloc(sizeof(*current));
430 if (!current->next)
431 goto error_out;
432 current = current->next;
433 } else {
434 first = malloc(sizeof(*first));
435 if (!first)
436 goto error_out;
437 current = first;
438 }
439 current->first = first;
440 current->next = NULL;
441
442 memcpy(one_value, linebuf + pos, i - pos);
443 one_value[i - pos] = '\0';
444
445 if (sscanf(one_value, "%u", &current->cpu) != 1)
446 goto error_out;
447
448 pos = i + 1;
449 }
450 }
451
452 return first;
453
454 error_out:
455 while (first) {
456 current = first->next;
457 free(first);
458 first = current;
459 }
460 return NULL;
461}
117 462
118struct cpufreq_affected_cpus *cpufreq_get_affected_cpus(unsigned int cpu) 463struct cpufreq_affected_cpus *cpufreq_get_affected_cpus(unsigned int cpu)
119{ 464{
120 return sysfs_get_freq_affected_cpus(cpu); 465 return sysfs_get_cpu_list(cpu, "affected_cpus");
121} 466}
122 467
123void cpufreq_put_affected_cpus(struct cpufreq_affected_cpus *any) 468void cpufreq_put_affected_cpus(struct cpufreq_affected_cpus *any)
@@ -138,7 +483,7 @@ void cpufreq_put_affected_cpus(struct cpufreq_affected_cpus *any)
138 483
139struct cpufreq_affected_cpus *cpufreq_get_related_cpus(unsigned int cpu) 484struct cpufreq_affected_cpus *cpufreq_get_related_cpus(unsigned int cpu)
140{ 485{
141 return sysfs_get_freq_related_cpus(cpu); 486 return sysfs_get_cpu_list(cpu, "related_cpus");
142} 487}
143 488
144void cpufreq_put_related_cpus(struct cpufreq_affected_cpus *any) 489void cpufreq_put_related_cpus(struct cpufreq_affected_cpus *any)
@@ -146,45 +491,208 @@ void cpufreq_put_related_cpus(struct cpufreq_affected_cpus *any)
146 cpufreq_put_affected_cpus(any); 491 cpufreq_put_affected_cpus(any);
147} 492}
148 493
494static int verify_gov(char *new_gov, char *passed_gov)
495{
496 unsigned int i, j = 0;
497
498 if (!passed_gov || (strlen(passed_gov) > 19))
499 return -EINVAL;
500
501 strncpy(new_gov, passed_gov, 20);
502 for (i = 0; i < 20; i++) {
503 if (j) {
504 new_gov[i] = '\0';
505 continue;
506 }
507 if ((new_gov[i] >= 'a') && (new_gov[i] <= 'z'))
508 continue;
509
510 if ((new_gov[i] >= 'A') && (new_gov[i] <= 'Z'))
511 continue;
512
513 if (new_gov[i] == '-')
514 continue;
515
516 if (new_gov[i] == '_')
517 continue;
518
519 if (new_gov[i] == '\0') {
520 j = 1;
521 continue;
522 }
523 return -EINVAL;
524 }
525 new_gov[19] = '\0';
526 return 0;
527}
149 528
150int cpufreq_set_policy(unsigned int cpu, struct cpufreq_policy *policy) 529int cpufreq_set_policy(unsigned int cpu, struct cpufreq_policy *policy)
151{ 530{
531 char min[SYSFS_PATH_MAX];
532 char max[SYSFS_PATH_MAX];
533 char gov[SYSFS_PATH_MAX];
534 int ret;
535 unsigned long old_min;
536 int write_max_first;
537
152 if (!policy || !(policy->governor)) 538 if (!policy || !(policy->governor))
153 return -EINVAL; 539 return -EINVAL;
154 540
155 return sysfs_set_freq_policy(cpu, policy); 541 if (policy->max < policy->min)
542 return -EINVAL;
543
544 if (verify_gov(gov, policy->governor))
545 return -EINVAL;
546
547 snprintf(min, SYSFS_PATH_MAX, "%lu", policy->min);
548 snprintf(max, SYSFS_PATH_MAX, "%lu", policy->max);
549
550 old_min = sysfs_cpufreq_get_one_value(cpu, SCALING_MIN_FREQ);
551 write_max_first = (old_min && (policy->max < old_min) ? 0 : 1);
552
553 if (write_max_first) {
554 ret = sysfs_cpufreq_write_one_value(cpu, WRITE_SCALING_MAX_FREQ,
555 max, strlen(max));
556 if (ret)
557 return ret;
558 }
559
560 ret = sysfs_cpufreq_write_one_value(cpu, WRITE_SCALING_MIN_FREQ, min,
561 strlen(min));
562 if (ret)
563 return ret;
564
565 if (!write_max_first) {
566 ret = sysfs_cpufreq_write_one_value(cpu, WRITE_SCALING_MAX_FREQ,
567 max, strlen(max));
568 if (ret)
569 return ret;
570 }
571
572 return sysfs_cpufreq_write_one_value(cpu, WRITE_SCALING_GOVERNOR,
573 gov, strlen(gov));
156} 574}
157 575
158 576
159int cpufreq_modify_policy_min(unsigned int cpu, unsigned long min_freq) 577int cpufreq_modify_policy_min(unsigned int cpu, unsigned long min_freq)
160{ 578{
161 return sysfs_modify_freq_policy_min(cpu, min_freq); 579 char value[SYSFS_PATH_MAX];
580
581 snprintf(value, SYSFS_PATH_MAX, "%lu", min_freq);
582
583 return sysfs_cpufreq_write_one_value(cpu, WRITE_SCALING_MIN_FREQ,
584 value, strlen(value));
162} 585}
163 586
164 587
165int cpufreq_modify_policy_max(unsigned int cpu, unsigned long max_freq) 588int cpufreq_modify_policy_max(unsigned int cpu, unsigned long max_freq)
166{ 589{
167 return sysfs_modify_freq_policy_max(cpu, max_freq); 590 char value[SYSFS_PATH_MAX];
168} 591
592 snprintf(value, SYSFS_PATH_MAX, "%lu", max_freq);
169 593
594 return sysfs_cpufreq_write_one_value(cpu, WRITE_SCALING_MAX_FREQ,
595 value, strlen(value));
596}
170 597
171int cpufreq_modify_policy_governor(unsigned int cpu, char *governor) 598int cpufreq_modify_policy_governor(unsigned int cpu, char *governor)
172{ 599{
600 char new_gov[SYSFS_PATH_MAX];
601
173 if ((!governor) || (strlen(governor) > 19)) 602 if ((!governor) || (strlen(governor) > 19))
174 return -EINVAL; 603 return -EINVAL;
175 604
176 return sysfs_modify_freq_policy_governor(cpu, governor); 605 if (verify_gov(new_gov, governor))
606 return -EINVAL;
607
608 return sysfs_cpufreq_write_one_value(cpu, WRITE_SCALING_GOVERNOR,
609 new_gov, strlen(new_gov));
177} 610}
178 611
179int cpufreq_set_frequency(unsigned int cpu, unsigned long target_frequency) 612int cpufreq_set_frequency(unsigned int cpu, unsigned long target_frequency)
180{ 613{
181 return sysfs_set_frequency(cpu, target_frequency); 614 struct cpufreq_policy *pol = cpufreq_get_policy(cpu);
615 char userspace_gov[] = "userspace";
616 char freq[SYSFS_PATH_MAX];
617 int ret;
618
619 if (!pol)
620 return -ENODEV;
621
622 if (strncmp(pol->governor, userspace_gov, 9) != 0) {
623 ret = cpufreq_modify_policy_governor(cpu, userspace_gov);
624 if (ret) {
625 cpufreq_put_policy(pol);
626 return ret;
627 }
628 }
629
630 cpufreq_put_policy(pol);
631
632 snprintf(freq, SYSFS_PATH_MAX, "%lu", target_frequency);
633
634 return sysfs_cpufreq_write_one_value(cpu, WRITE_SCALING_SET_SPEED,
635 freq, strlen(freq));
182} 636}
183 637
184struct cpufreq_stats *cpufreq_get_stats(unsigned int cpu, 638struct cpufreq_stats *cpufreq_get_stats(unsigned int cpu,
185 unsigned long long *total_time) 639 unsigned long long *total_time)
186{ 640{
187 return sysfs_get_freq_stats(cpu, total_time); 641 struct cpufreq_stats *first = NULL;
642 struct cpufreq_stats *current = NULL;
643 char one_value[SYSFS_PATH_MAX];
644 char linebuf[MAX_LINE_LEN];
645 unsigned int pos, i;
646 unsigned int len;
647
648 len = sysfs_cpufreq_read_file(cpu, "stats/time_in_state",
649 linebuf, sizeof(linebuf));
650 if (len == 0)
651 return NULL;
652
653 *total_time = 0;
654 pos = 0;
655 for (i = 0; i < len; i++) {
656 if (i == strlen(linebuf) || linebuf[i] == '\n') {
657 if (i - pos < 2)
658 continue;
659 if ((i - pos) >= SYSFS_PATH_MAX)
660 goto error_out;
661 if (current) {
662 current->next = malloc(sizeof(*current));
663 if (!current->next)
664 goto error_out;
665 current = current->next;
666 } else {
667 first = malloc(sizeof(*first));
668 if (!first)
669 goto error_out;
670 current = first;
671 }
672 current->first = first;
673 current->next = NULL;
674
675 memcpy(one_value, linebuf + pos, i - pos);
676 one_value[i - pos] = '\0';
677 if (sscanf(one_value, "%lu %llu",
678 &current->frequency,
679 &current->time_in_state) != 2)
680 goto error_out;
681
682 *total_time = *total_time + current->time_in_state;
683 pos = i + 1;
684 }
685 }
686
687 return first;
688
689 error_out:
690 while (first) {
691 current = first->next;
692 free(first);
693 first = current;
694 }
695 return NULL;
188} 696}
189 697
190void cpufreq_put_stats(struct cpufreq_stats *any) 698void cpufreq_put_stats(struct cpufreq_stats *any)
@@ -204,5 +712,5 @@ void cpufreq_put_stats(struct cpufreq_stats *any)
204 712
205unsigned long cpufreq_get_transitions(unsigned int cpu) 713unsigned long cpufreq_get_transitions(unsigned int cpu)
206{ 714{
207 return sysfs_get_freq_transitions(cpu); 715 return sysfs_cpufreq_get_one_value(cpu, STATS_NUM_TRANSITIONS);
208} 716}
diff --git a/tools/power/cpupower/lib/cpufreq.h b/tools/power/cpupower/lib/cpufreq.h
index 3aae8e7a0839..3b005c39f068 100644
--- a/tools/power/cpupower/lib/cpufreq.h
+++ b/tools/power/cpupower/lib/cpufreq.h
@@ -17,8 +17,8 @@
17 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA 17 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
18 */ 18 */
19 19
20#ifndef _CPUFREQ_H 20#ifndef __CPUPOWER_CPUFREQ_H__
21#define _CPUFREQ_H 1 21#define __CPUPOWER_CPUFREQ_H__
22 22
23struct cpufreq_policy { 23struct cpufreq_policy {
24 unsigned long min; 24 unsigned long min;
@@ -58,13 +58,6 @@ struct cpufreq_stats {
58extern "C" { 58extern "C" {
59#endif 59#endif
60 60
61/*
62 * returns 0 if the specified CPU is present (it doesn't say
63 * whether it is online!), and an error value if not.
64 */
65
66extern int cpufreq_cpu_exists(unsigned int cpu);
67
68/* determine current CPU frequency 61/* determine current CPU frequency
69 * - _kernel variant means kernel's opinion of CPU frequency 62 * - _kernel variant means kernel's opinion of CPU frequency
70 * - _hardware variant means actual hardware CPU frequency, 63 * - _hardware variant means actual hardware CPU frequency,
@@ -73,9 +66,9 @@ extern int cpufreq_cpu_exists(unsigned int cpu);
73 * returns 0 on failure, else frequency in kHz. 66 * returns 0 on failure, else frequency in kHz.
74 */ 67 */
75 68
76extern unsigned long cpufreq_get_freq_kernel(unsigned int cpu); 69unsigned long cpufreq_get_freq_kernel(unsigned int cpu);
77 70
78extern unsigned long cpufreq_get_freq_hardware(unsigned int cpu); 71unsigned long cpufreq_get_freq_hardware(unsigned int cpu);
79 72
80#define cpufreq_get(cpu) cpufreq_get_freq_kernel(cpu); 73#define cpufreq_get(cpu) cpufreq_get_freq_kernel(cpu);
81 74
@@ -84,7 +77,7 @@ extern unsigned long cpufreq_get_freq_hardware(unsigned int cpu);
84 * 77 *
85 * returns 0 on failure, else transition latency in 10^(-9) s = nanoseconds 78 * returns 0 on failure, else transition latency in 10^(-9) s = nanoseconds
86 */ 79 */
87extern unsigned long cpufreq_get_transition_latency(unsigned int cpu); 80unsigned long cpufreq_get_transition_latency(unsigned int cpu);
88 81
89 82
90/* determine hardware CPU frequency limits 83/* determine hardware CPU frequency limits
@@ -93,7 +86,7 @@ extern unsigned long cpufreq_get_transition_latency(unsigned int cpu);
93 * considerations by cpufreq policy notifiers in the kernel. 86 * considerations by cpufreq policy notifiers in the kernel.
94 */ 87 */
95 88
96extern int cpufreq_get_hardware_limits(unsigned int cpu, 89int cpufreq_get_hardware_limits(unsigned int cpu,
97 unsigned long *min, 90 unsigned long *min,
98 unsigned long *max); 91 unsigned long *max);
99 92
@@ -104,9 +97,9 @@ extern int cpufreq_get_hardware_limits(unsigned int cpu,
104 * to avoid memory leakage, please. 97 * to avoid memory leakage, please.
105 */ 98 */
106 99
107extern char *cpufreq_get_driver(unsigned int cpu); 100char *cpufreq_get_driver(unsigned int cpu);
108 101
109extern void cpufreq_put_driver(char *ptr); 102void cpufreq_put_driver(char *ptr);
110 103
111 104
112/* determine CPUfreq policy currently used 105/* determine CPUfreq policy currently used
@@ -116,9 +109,9 @@ extern void cpufreq_put_driver(char *ptr);
116 */ 109 */
117 110
118 111
119extern struct cpufreq_policy *cpufreq_get_policy(unsigned int cpu); 112struct cpufreq_policy *cpufreq_get_policy(unsigned int cpu);
120 113
121extern void cpufreq_put_policy(struct cpufreq_policy *policy); 114void cpufreq_put_policy(struct cpufreq_policy *policy);
122 115
123 116
124/* determine CPUfreq governors currently available 117/* determine CPUfreq governors currently available
@@ -129,10 +122,10 @@ extern void cpufreq_put_policy(struct cpufreq_policy *policy);
129 */ 122 */
130 123
131 124
132extern struct cpufreq_available_governors 125struct cpufreq_available_governors
133*cpufreq_get_available_governors(unsigned int cpu); 126*cpufreq_get_available_governors(unsigned int cpu);
134 127
135extern void cpufreq_put_available_governors( 128void cpufreq_put_available_governors(
136 struct cpufreq_available_governors *first); 129 struct cpufreq_available_governors *first);
137 130
138 131
@@ -143,10 +136,10 @@ extern void cpufreq_put_available_governors(
143 * cpufreq_put_available_frequencies after use. 136 * cpufreq_put_available_frequencies after use.
144 */ 137 */
145 138
146extern struct cpufreq_available_frequencies 139struct cpufreq_available_frequencies
147*cpufreq_get_available_frequencies(unsigned int cpu); 140*cpufreq_get_available_frequencies(unsigned int cpu);
148 141
149extern void cpufreq_put_available_frequencies( 142void cpufreq_put_available_frequencies(
150 struct cpufreq_available_frequencies *first); 143 struct cpufreq_available_frequencies *first);
151 144
152 145
@@ -156,10 +149,10 @@ extern void cpufreq_put_available_frequencies(
156 * to avoid memory leakage, please. 149 * to avoid memory leakage, please.
157 */ 150 */
158 151
159extern struct cpufreq_affected_cpus *cpufreq_get_affected_cpus(unsigned 152struct cpufreq_affected_cpus *cpufreq_get_affected_cpus(unsigned
160 int cpu); 153 int cpu);
161 154
162extern void cpufreq_put_affected_cpus(struct cpufreq_affected_cpus *first); 155void cpufreq_put_affected_cpus(struct cpufreq_affected_cpus *first);
163 156
164 157
165/* determine related CPUs 158/* determine related CPUs
@@ -168,10 +161,10 @@ extern void cpufreq_put_affected_cpus(struct cpufreq_affected_cpus *first);
168 * to avoid memory leakage, please. 161 * to avoid memory leakage, please.
169 */ 162 */
170 163
171extern struct cpufreq_affected_cpus *cpufreq_get_related_cpus(unsigned 164struct cpufreq_affected_cpus *cpufreq_get_related_cpus(unsigned
172 int cpu); 165 int cpu);
173 166
174extern void cpufreq_put_related_cpus(struct cpufreq_affected_cpus *first); 167void cpufreq_put_related_cpus(struct cpufreq_affected_cpus *first);
175 168
176 169
177/* determine stats for cpufreq subsystem 170/* determine stats for cpufreq subsystem
@@ -179,12 +172,12 @@ extern void cpufreq_put_related_cpus(struct cpufreq_affected_cpus *first);
179 * This is not available in all kernel versions or configurations. 172 * This is not available in all kernel versions or configurations.
180 */ 173 */
181 174
182extern struct cpufreq_stats *cpufreq_get_stats(unsigned int cpu, 175struct cpufreq_stats *cpufreq_get_stats(unsigned int cpu,
183 unsigned long long *total_time); 176 unsigned long long *total_time);
184 177
185extern void cpufreq_put_stats(struct cpufreq_stats *stats); 178void cpufreq_put_stats(struct cpufreq_stats *stats);
186 179
187extern unsigned long cpufreq_get_transitions(unsigned int cpu); 180unsigned long cpufreq_get_transitions(unsigned int cpu);
188 181
189 182
190/* set new cpufreq policy 183/* set new cpufreq policy
@@ -193,7 +186,7 @@ extern unsigned long cpufreq_get_transitions(unsigned int cpu);
193 * but results may differ depending e.g. on governors being available. 186 * but results may differ depending e.g. on governors being available.
194 */ 187 */
195 188
196extern int cpufreq_set_policy(unsigned int cpu, struct cpufreq_policy *policy); 189int cpufreq_set_policy(unsigned int cpu, struct cpufreq_policy *policy);
197 190
198 191
199/* modify a policy by only changing min/max freq or governor 192/* modify a policy by only changing min/max freq or governor
@@ -201,9 +194,9 @@ extern int cpufreq_set_policy(unsigned int cpu, struct cpufreq_policy *policy);
201 * Does not check whether result is what was intended. 194 * Does not check whether result is what was intended.
202 */ 195 */
203 196
204extern int cpufreq_modify_policy_min(unsigned int cpu, unsigned long min_freq); 197int cpufreq_modify_policy_min(unsigned int cpu, unsigned long min_freq);
205extern int cpufreq_modify_policy_max(unsigned int cpu, unsigned long max_freq); 198int cpufreq_modify_policy_max(unsigned int cpu, unsigned long max_freq);
206extern int cpufreq_modify_policy_governor(unsigned int cpu, char *governor); 199int cpufreq_modify_policy_governor(unsigned int cpu, char *governor);
207 200
208 201
209/* set a specific frequency 202/* set a specific frequency
@@ -213,7 +206,7 @@ extern int cpufreq_modify_policy_governor(unsigned int cpu, char *governor);
213 * occurs. Also does not work on ->range() cpufreq drivers. 206 * occurs. Also does not work on ->range() cpufreq drivers.
214 */ 207 */
215 208
216extern int cpufreq_set_frequency(unsigned int cpu, 209int cpufreq_set_frequency(unsigned int cpu,
217 unsigned long target_frequency); 210 unsigned long target_frequency);
218 211
219#ifdef __cplusplus 212#ifdef __cplusplus
diff --git a/tools/power/cpupower/lib/cpuidle.c b/tools/power/cpupower/lib/cpuidle.c
new file mode 100644
index 000000000000..9bd4c7655fdb
--- /dev/null
+++ b/tools/power/cpupower/lib/cpuidle.c
@@ -0,0 +1,380 @@
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 "cpuidle.h"
18#include "cpupower_intern.h"
19
20/*
21 * helper function to check whether a file under "../cpuX/cpuidle/stateX/" dir
22 * exists.
23 * For example the functionality to disable c-states was introduced in later
24 * kernel versions, this function can be used to explicitly check for this
25 * feature.
26 *
27 * returns 1 if the file exists, 0 otherwise.
28 */
29static
30unsigned int cpuidle_state_file_exists(unsigned int cpu,
31 unsigned int idlestate,
32 const char *fname)
33{
34 char path[SYSFS_PATH_MAX];
35 struct stat statbuf;
36
37
38 snprintf(path, sizeof(path), PATH_TO_CPU "cpu%u/cpuidle/state%u/%s",
39 cpu, idlestate, fname);
40 if (stat(path, &statbuf) != 0)
41 return 0;
42 return 1;
43}
44
45/*
46 * helper function to read file from /sys into given buffer
47 * fname is a relative path under "cpuX/cpuidle/stateX/" dir
48 * cstates starting with 0, C0 is not counted as cstate.
49 * This means if you want C1 info, pass 0 as idlestate param
50 */
51static
52unsigned int cpuidle_state_read_file(unsigned int cpu,
53 unsigned int idlestate,
54 const char *fname, char *buf,
55 size_t buflen)
56{
57 char path[SYSFS_PATH_MAX];
58 int fd;
59 ssize_t numread;
60
61 snprintf(path, sizeof(path), PATH_TO_CPU "cpu%u/cpuidle/state%u/%s",
62 cpu, idlestate, fname);
63
64 fd = open(path, O_RDONLY);
65 if (fd == -1)
66 return 0;
67
68 numread = read(fd, buf, buflen - 1);
69 if (numread < 1) {
70 close(fd);
71 return 0;
72 }
73
74 buf[numread] = '\0';
75 close(fd);
76
77 return (unsigned int) numread;
78}
79
80/*
81 * helper function to write a new value to a /sys file
82 * fname is a relative path under "../cpuX/cpuidle/cstateY/" dir
83 *
84 * Returns the number of bytes written or 0 on error
85 */
86static
87unsigned int cpuidle_state_write_file(unsigned int cpu,
88 unsigned int idlestate,
89 const char *fname,
90 const char *value, size_t len)
91{
92 char path[SYSFS_PATH_MAX];
93 int fd;
94 ssize_t numwrite;
95
96 snprintf(path, sizeof(path), PATH_TO_CPU "cpu%u/cpuidle/state%u/%s",
97 cpu, idlestate, fname);
98
99 fd = open(path, O_WRONLY);
100 if (fd == -1)
101 return 0;
102
103 numwrite = write(fd, value, len);
104 if (numwrite < 1) {
105 close(fd);
106 return 0;
107 }
108
109 close(fd);
110
111 return (unsigned int) numwrite;
112}
113
114/* read access to files which contain one numeric value */
115
116enum idlestate_value {
117 IDLESTATE_USAGE,
118 IDLESTATE_POWER,
119 IDLESTATE_LATENCY,
120 IDLESTATE_TIME,
121 IDLESTATE_DISABLE,
122 MAX_IDLESTATE_VALUE_FILES
123};
124
125static const char *idlestate_value_files[MAX_IDLESTATE_VALUE_FILES] = {
126 [IDLESTATE_USAGE] = "usage",
127 [IDLESTATE_POWER] = "power",
128 [IDLESTATE_LATENCY] = "latency",
129 [IDLESTATE_TIME] = "time",
130 [IDLESTATE_DISABLE] = "disable",
131};
132
133static
134unsigned long long cpuidle_state_get_one_value(unsigned int cpu,
135 unsigned int idlestate,
136 enum idlestate_value which)
137{
138 unsigned long long value;
139 unsigned int len;
140 char linebuf[MAX_LINE_LEN];
141 char *endp;
142
143 if (which >= MAX_IDLESTATE_VALUE_FILES)
144 return 0;
145
146 len = cpuidle_state_read_file(cpu, idlestate,
147 idlestate_value_files[which],
148 linebuf, sizeof(linebuf));
149 if (len == 0)
150 return 0;
151
152 value = strtoull(linebuf, &endp, 0);
153
154 if (endp == linebuf || errno == ERANGE)
155 return 0;
156
157 return value;
158}
159
160/* read access to files which contain one string */
161
162enum idlestate_string {
163 IDLESTATE_DESC,
164 IDLESTATE_NAME,
165 MAX_IDLESTATE_STRING_FILES
166};
167
168static const char *idlestate_string_files[MAX_IDLESTATE_STRING_FILES] = {
169 [IDLESTATE_DESC] = "desc",
170 [IDLESTATE_NAME] = "name",
171};
172
173
174static char *cpuidle_state_get_one_string(unsigned int cpu,
175 unsigned int idlestate,
176 enum idlestate_string which)
177{
178 char linebuf[MAX_LINE_LEN];
179 char *result;
180 unsigned int len;
181
182 if (which >= MAX_IDLESTATE_STRING_FILES)
183 return NULL;
184
185 len = cpuidle_state_read_file(cpu, idlestate,
186 idlestate_string_files[which],
187 linebuf, sizeof(linebuf));
188 if (len == 0)
189 return NULL;
190
191 result = strdup(linebuf);
192 if (result == NULL)
193 return NULL;
194
195 if (result[strlen(result) - 1] == '\n')
196 result[strlen(result) - 1] = '\0';
197
198 return result;
199}
200
201/*
202 * Returns:
203 * 1 if disabled
204 * 0 if enabled
205 * -1 if idlestate is not available
206 * -2 if disabling is not supported by the kernel
207 */
208int cpuidle_is_state_disabled(unsigned int cpu,
209 unsigned int idlestate)
210{
211 if (cpuidle_state_count(cpu) <= idlestate)
212 return -1;
213
214 if (!cpuidle_state_file_exists(cpu, idlestate,
215 idlestate_value_files[IDLESTATE_DISABLE]))
216 return -2;
217 return cpuidle_state_get_one_value(cpu, idlestate, IDLESTATE_DISABLE);
218}
219
220/*
221 * Pass 1 as last argument to disable or 0 to enable the state
222 * Returns:
223 * 0 on success
224 * negative values on error, for example:
225 * -1 if idlestate is not available
226 * -2 if disabling is not supported by the kernel
227 * -3 No write access to disable/enable C-states
228 */
229int cpuidle_state_disable(unsigned int cpu,
230 unsigned int idlestate,
231 unsigned int disable)
232{
233 char value[SYSFS_PATH_MAX];
234 int bytes_written;
235
236 if (cpuidle_state_count(cpu) <= idlestate)
237 return -1;
238
239 if (!cpuidle_state_file_exists(cpu, idlestate,
240 idlestate_value_files[IDLESTATE_DISABLE]))
241 return -2;
242
243 snprintf(value, SYSFS_PATH_MAX, "%u", disable);
244
245 bytes_written = cpuidle_state_write_file(cpu, idlestate, "disable",
246 value, sizeof(disable));
247 if (bytes_written)
248 return 0;
249 return -3;
250}
251
252unsigned long cpuidle_state_latency(unsigned int cpu,
253 unsigned int idlestate)
254{
255 return cpuidle_state_get_one_value(cpu, idlestate, IDLESTATE_LATENCY);
256}
257
258unsigned long cpuidle_state_usage(unsigned int cpu,
259 unsigned int idlestate)
260{
261 return cpuidle_state_get_one_value(cpu, idlestate, IDLESTATE_USAGE);
262}
263
264unsigned long long cpuidle_state_time(unsigned int cpu,
265 unsigned int idlestate)
266{
267 return cpuidle_state_get_one_value(cpu, idlestate, IDLESTATE_TIME);
268}
269
270char *cpuidle_state_name(unsigned int cpu, unsigned int idlestate)
271{
272 return cpuidle_state_get_one_string(cpu, idlestate, IDLESTATE_NAME);
273}
274
275char *cpuidle_state_desc(unsigned int cpu, unsigned int idlestate)
276{
277 return cpuidle_state_get_one_string(cpu, idlestate, IDLESTATE_DESC);
278}
279
280/*
281 * Returns number of supported C-states of CPU core cpu
282 * Negativ in error case
283 * Zero if cpuidle does not export any C-states
284 */
285unsigned int cpuidle_state_count(unsigned int cpu)
286{
287 char file[SYSFS_PATH_MAX];
288 struct stat statbuf;
289 int idlestates = 1;
290
291
292 snprintf(file, SYSFS_PATH_MAX, PATH_TO_CPU "cpuidle");
293 if (stat(file, &statbuf) != 0 || !S_ISDIR(statbuf.st_mode))
294 return 0;
295
296 snprintf(file, SYSFS_PATH_MAX, PATH_TO_CPU "cpu%u/cpuidle/state0", cpu);
297 if (stat(file, &statbuf) != 0 || !S_ISDIR(statbuf.st_mode))
298 return 0;
299
300 while (stat(file, &statbuf) == 0 && S_ISDIR(statbuf.st_mode)) {
301 snprintf(file, SYSFS_PATH_MAX, PATH_TO_CPU
302 "cpu%u/cpuidle/state%d", cpu, idlestates);
303 idlestates++;
304 }
305 idlestates--;
306 return idlestates;
307}
308
309/* CPUidle general /sys/devices/system/cpu/cpuidle/ sysfs access ********/
310
311/*
312 * helper function to read file from /sys into given buffer
313 * fname is a relative path under "cpu/cpuidle/" dir
314 */
315static unsigned int sysfs_cpuidle_read_file(const char *fname, char *buf,
316 size_t buflen)
317{
318 char path[SYSFS_PATH_MAX];
319
320 snprintf(path, sizeof(path), PATH_TO_CPU "cpuidle/%s", fname);
321
322 return sysfs_read_file(path, buf, buflen);
323}
324
325
326
327/* read access to files which contain one string */
328
329enum cpuidle_string {
330 CPUIDLE_GOVERNOR,
331 CPUIDLE_GOVERNOR_RO,
332 CPUIDLE_DRIVER,
333 MAX_CPUIDLE_STRING_FILES
334};
335
336static const char *cpuidle_string_files[MAX_CPUIDLE_STRING_FILES] = {
337 [CPUIDLE_GOVERNOR] = "current_governor",
338 [CPUIDLE_GOVERNOR_RO] = "current_governor_ro",
339 [CPUIDLE_DRIVER] = "current_driver",
340};
341
342
343static char *sysfs_cpuidle_get_one_string(enum cpuidle_string which)
344{
345 char linebuf[MAX_LINE_LEN];
346 char *result;
347 unsigned int len;
348
349 if (which >= MAX_CPUIDLE_STRING_FILES)
350 return NULL;
351
352 len = sysfs_cpuidle_read_file(cpuidle_string_files[which],
353 linebuf, sizeof(linebuf));
354 if (len == 0)
355 return NULL;
356
357 result = strdup(linebuf);
358 if (result == NULL)
359 return NULL;
360
361 if (result[strlen(result) - 1] == '\n')
362 result[strlen(result) - 1] = '\0';
363
364 return result;
365}
366
367char *cpuidle_get_governor(void)
368{
369 char *tmp = sysfs_cpuidle_get_one_string(CPUIDLE_GOVERNOR_RO);
370 if (!tmp)
371 return sysfs_cpuidle_get_one_string(CPUIDLE_GOVERNOR);
372 else
373 return tmp;
374}
375
376char *cpuidle_get_driver(void)
377{
378 return sysfs_cpuidle_get_one_string(CPUIDLE_DRIVER);
379}
380/* CPUidle idlestate specific /sys/devices/system/cpu/cpuX/cpuidle/ access */
diff --git a/tools/power/cpupower/lib/cpuidle.h b/tools/power/cpupower/lib/cpuidle.h
new file mode 100644
index 000000000000..04eb3cfa6e42
--- /dev/null
+++ b/tools/power/cpupower/lib/cpuidle.h
@@ -0,0 +1,23 @@
1#ifndef __CPUPOWER_CPUIDLE_H__
2#define __CPUPOWER_CPUIDLE_H__
3
4int cpuidle_is_state_disabled(unsigned int cpu,
5 unsigned int idlestate);
6int cpuidle_state_disable(unsigned int cpu, unsigned int idlestate,
7 unsigned int disable);
8unsigned long cpuidle_state_latency(unsigned int cpu,
9 unsigned int idlestate);
10unsigned long cpuidle_state_usage(unsigned int cpu,
11 unsigned int idlestate);
12unsigned long long cpuidle_state_time(unsigned int cpu,
13 unsigned int idlestate);
14char *cpuidle_state_name(unsigned int cpu,
15 unsigned int idlestate);
16char *cpuidle_state_desc(unsigned int cpu,
17 unsigned int idlestate);
18unsigned int cpuidle_state_count(unsigned int cpu);
19
20char *cpuidle_get_governor(void);
21char *cpuidle_get_driver(void);
22
23#endif /* __CPUPOWER_HELPERS_SYSFS_H__ */
diff --git a/tools/power/cpupower/lib/cpupower.c b/tools/power/cpupower/lib/cpupower.c
new file mode 100644
index 000000000000..9c395ec924de
--- /dev/null
+++ b/tools/power/cpupower/lib/cpupower.c
@@ -0,0 +1,192 @@
1/*
2 * (C) 2004-2009 Dominik Brodowski <linux@dominikbrodowski.de>
3 *
4 * Licensed under the terms of the GNU GPL License version 2.
5 */
6
7#include <sys/types.h>
8#include <sys/stat.h>
9#include <fcntl.h>
10#include <unistd.h>
11#include <stdio.h>
12#include <errno.h>
13#include <stdlib.h>
14
15#include "cpupower.h"
16#include "cpupower_intern.h"
17
18unsigned int sysfs_read_file(const char *path, char *buf, size_t buflen)
19{
20 int fd;
21 ssize_t numread;
22
23 fd = open(path, O_RDONLY);
24 if (fd == -1)
25 return 0;
26
27 numread = read(fd, buf, buflen - 1);
28 if (numread < 1) {
29 close(fd);
30 return 0;
31 }
32
33 buf[numread] = '\0';
34 close(fd);
35
36 return (unsigned int) numread;
37}
38
39/*
40 * Detect whether a CPU is online
41 *
42 * Returns:
43 * 1 -> if CPU is online
44 * 0 -> if CPU is offline
45 * negative errno values in error case
46 */
47int cpupower_is_cpu_online(unsigned int cpu)
48{
49 char path[SYSFS_PATH_MAX];
50 int fd;
51 ssize_t numread;
52 unsigned long long value;
53 char linebuf[MAX_LINE_LEN];
54 char *endp;
55 struct stat statbuf;
56
57 snprintf(path, sizeof(path), PATH_TO_CPU "cpu%u", cpu);
58
59 if (stat(path, &statbuf) != 0)
60 return 0;
61
62 /*
63 * kernel without CONFIG_HOTPLUG_CPU
64 * -> cpuX directory exists, but not cpuX/online file
65 */
66 snprintf(path, sizeof(path), PATH_TO_CPU "cpu%u/online", cpu);
67 if (stat(path, &statbuf) != 0)
68 return 1;
69
70 fd = open(path, O_RDONLY);
71 if (fd == -1)
72 return -errno;
73
74 numread = read(fd, linebuf, MAX_LINE_LEN - 1);
75 if (numread < 1) {
76 close(fd);
77 return -EIO;
78 }
79 linebuf[numread] = '\0';
80 close(fd);
81
82 value = strtoull(linebuf, &endp, 0);
83 if (value > 1)
84 return -EINVAL;
85
86 return value;
87}
88
89/* returns -1 on failure, 0 on success */
90static int sysfs_topology_read_file(unsigned int cpu, const char *fname, int *result)
91{
92 char linebuf[MAX_LINE_LEN];
93 char *endp;
94 char path[SYSFS_PATH_MAX];
95
96 snprintf(path, sizeof(path), PATH_TO_CPU "cpu%u/topology/%s",
97 cpu, fname);
98 if (sysfs_read_file(path, linebuf, MAX_LINE_LEN) == 0)
99 return -1;
100 *result = strtol(linebuf, &endp, 0);
101 if (endp == linebuf || errno == ERANGE)
102 return -1;
103 return 0;
104}
105
106static int __compare(const void *t1, const void *t2)
107{
108 struct cpuid_core_info *top1 = (struct cpuid_core_info *)t1;
109 struct cpuid_core_info *top2 = (struct cpuid_core_info *)t2;
110 if (top1->pkg < top2->pkg)
111 return -1;
112 else if (top1->pkg > top2->pkg)
113 return 1;
114 else if (top1->core < top2->core)
115 return -1;
116 else if (top1->core > top2->core)
117 return 1;
118 else if (top1->cpu < top2->cpu)
119 return -1;
120 else if (top1->cpu > top2->cpu)
121 return 1;
122 else
123 return 0;
124}
125
126/*
127 * Returns amount of cpus, negative on error, cpu_top must be
128 * passed to cpu_topology_release to free resources
129 *
130 * Array is sorted after ->pkg, ->core, then ->cpu
131 */
132int get_cpu_topology(struct cpupower_topology *cpu_top)
133{
134 int cpu, last_pkg, cpus = sysconf(_SC_NPROCESSORS_CONF);
135
136 cpu_top->core_info = malloc(sizeof(struct cpuid_core_info) * cpus);
137 if (cpu_top->core_info == NULL)
138 return -ENOMEM;
139 cpu_top->pkgs = cpu_top->cores = 0;
140 for (cpu = 0; cpu < cpus; cpu++) {
141 cpu_top->core_info[cpu].cpu = cpu;
142 cpu_top->core_info[cpu].is_online = cpupower_is_cpu_online(cpu);
143 if(sysfs_topology_read_file(
144 cpu,
145 "physical_package_id",
146 &(cpu_top->core_info[cpu].pkg)) < 0) {
147 cpu_top->core_info[cpu].pkg = -1;
148 cpu_top->core_info[cpu].core = -1;
149 continue;
150 }
151 if(sysfs_topology_read_file(
152 cpu,
153 "core_id",
154 &(cpu_top->core_info[cpu].core)) < 0) {
155 cpu_top->core_info[cpu].pkg = -1;
156 cpu_top->core_info[cpu].core = -1;
157 continue;
158 }
159 }
160
161 qsort(cpu_top->core_info, cpus, sizeof(struct cpuid_core_info),
162 __compare);
163
164 /* Count the number of distinct pkgs values. This works
165 because the primary sort of the core_info struct was just
166 done by pkg value. */
167 last_pkg = cpu_top->core_info[0].pkg;
168 for(cpu = 1; cpu < cpus; cpu++) {
169 if (cpu_top->core_info[cpu].pkg != last_pkg &&
170 cpu_top->core_info[cpu].pkg != -1) {
171
172 last_pkg = cpu_top->core_info[cpu].pkg;
173 cpu_top->pkgs++;
174 }
175 }
176 if (!(cpu_top->core_info[0].pkg == -1))
177 cpu_top->pkgs++;
178
179 /* Intel's cores count is not consecutively numbered, there may
180 * be a core_id of 3, but none of 2. Assume there always is 0
181 * Get amount of cores by counting duplicates in a package
182 for (cpu = 0; cpu_top->core_info[cpu].pkg = 0 && cpu < cpus; cpu++) {
183 if (cpu_top->core_info[cpu].core == 0)
184 cpu_top->cores++;
185 */
186 return cpus;
187}
188
189void cpu_topology_release(struct cpupower_topology cpu_top)
190{
191 free(cpu_top.core_info);
192}
diff --git a/tools/power/cpupower/lib/cpupower.h b/tools/power/cpupower/lib/cpupower.h
new file mode 100644
index 000000000000..fa031fcc7710
--- /dev/null
+++ b/tools/power/cpupower/lib/cpupower.h
@@ -0,0 +1,35 @@
1#ifndef __CPUPOWER_CPUPOWER_H__
2#define __CPUPOWER_CPUPOWER_H__
3
4struct cpupower_topology {
5 /* Amount of CPU cores, packages and threads per core in the system */
6 unsigned int cores;
7 unsigned int pkgs;
8 unsigned int threads; /* per core */
9
10 /* Array gets mallocated with cores entries, holding per core info */
11 struct cpuid_core_info *core_info;
12};
13
14struct cpuid_core_info {
15 int pkg;
16 int core;
17 int cpu;
18
19 /* flags */
20 unsigned int is_online:1;
21};
22
23#ifdef __cplusplus
24extern "C" {
25#endif
26
27int get_cpu_topology(struct cpupower_topology *cpu_top);
28void cpu_topology_release(struct cpupower_topology cpu_top);
29int cpupower_is_cpu_online(unsigned int cpu);
30
31#ifdef __cplusplus
32}
33#endif
34
35#endif
diff --git a/tools/power/cpupower/lib/cpupower_intern.h b/tools/power/cpupower/lib/cpupower_intern.h
new file mode 100644
index 000000000000..f8ec4009621c
--- /dev/null
+++ b/tools/power/cpupower/lib/cpupower_intern.h
@@ -0,0 +1,5 @@
1#define PATH_TO_CPU "/sys/devices/system/cpu/"
2#define MAX_LINE_LEN 4096
3#define SYSFS_PATH_MAX 255
4
5unsigned int sysfs_read_file(const char *path, char *buf, size_t buflen);
diff --git a/tools/power/cpupower/lib/sysfs.c b/tools/power/cpupower/lib/sysfs.c
deleted file mode 100644
index 870713a75a81..000000000000
--- a/tools/power/cpupower/lib/sysfs.c
+++ /dev/null
@@ -1,672 +0,0 @@
1/*
2 * (C) 2004-2009 Dominik Brodowski <linux@dominikbrodowski.de>
3 *
4 * Licensed under the terms of the GNU GPL License version 2.
5 */
6
7#include <stdio.h>
8#include <errno.h>
9#include <stdlib.h>
10#include <string.h>
11#include <limits.h>
12#include <sys/types.h>
13#include <sys/stat.h>
14#include <fcntl.h>
15#include <unistd.h>
16
17#include "cpufreq.h"
18
19#define PATH_TO_CPU "/sys/devices/system/cpu/"
20#define MAX_LINE_LEN 4096
21#define SYSFS_PATH_MAX 255
22
23
24static unsigned int sysfs_read_file(const char *path, char *buf, size_t buflen)
25{
26 int fd;
27 ssize_t numread;
28
29 fd = open(path, O_RDONLY);
30 if (fd == -1)
31 return 0;
32
33 numread = read(fd, buf, buflen - 1);
34 if (numread < 1) {
35 close(fd);
36 return 0;
37 }
38
39 buf[numread] = '\0';
40 close(fd);
41
42 return (unsigned int) numread;
43}
44
45
46/* CPUFREQ sysfs access **************************************************/
47
48/* helper function to read file from /sys into given buffer */
49/* fname is a relative path under "cpuX/cpufreq" dir */
50static unsigned int sysfs_cpufreq_read_file(unsigned int cpu, const char *fname,
51 char *buf, size_t buflen)
52{
53 char path[SYSFS_PATH_MAX];
54
55 snprintf(path, sizeof(path), PATH_TO_CPU "cpu%u/cpufreq/%s",
56 cpu, fname);
57 return sysfs_read_file(path, buf, buflen);
58}
59
60/* helper function to write a new value to a /sys file */
61/* fname is a relative path under "cpuX/cpufreq" dir */
62static unsigned int sysfs_cpufreq_write_file(unsigned int cpu,
63 const char *fname,
64 const char *value, size_t len)
65{
66 char path[SYSFS_PATH_MAX];
67 int fd;
68 ssize_t numwrite;
69
70 snprintf(path, sizeof(path), PATH_TO_CPU "cpu%u/cpufreq/%s",
71 cpu, fname);
72
73 fd = open(path, O_WRONLY);
74 if (fd == -1)
75 return 0;
76
77 numwrite = write(fd, value, len);
78 if (numwrite < 1) {
79 close(fd);
80 return 0;
81 }
82
83 close(fd);
84
85 return (unsigned int) numwrite;
86}
87
88/* read access to files which contain one numeric value */
89
90enum cpufreq_value {
91 CPUINFO_CUR_FREQ,
92 CPUINFO_MIN_FREQ,
93 CPUINFO_MAX_FREQ,
94 CPUINFO_LATENCY,
95 SCALING_CUR_FREQ,
96 SCALING_MIN_FREQ,
97 SCALING_MAX_FREQ,
98 STATS_NUM_TRANSITIONS,
99 MAX_CPUFREQ_VALUE_READ_FILES
100};
101
102static const char *cpufreq_value_files[MAX_CPUFREQ_VALUE_READ_FILES] = {
103 [CPUINFO_CUR_FREQ] = "cpuinfo_cur_freq",
104 [CPUINFO_MIN_FREQ] = "cpuinfo_min_freq",
105 [CPUINFO_MAX_FREQ] = "cpuinfo_max_freq",
106 [CPUINFO_LATENCY] = "cpuinfo_transition_latency",
107 [SCALING_CUR_FREQ] = "scaling_cur_freq",
108 [SCALING_MIN_FREQ] = "scaling_min_freq",
109 [SCALING_MAX_FREQ] = "scaling_max_freq",
110 [STATS_NUM_TRANSITIONS] = "stats/total_trans"
111};
112
113
114static unsigned long sysfs_cpufreq_get_one_value(unsigned int cpu,
115 enum cpufreq_value which)
116{
117 unsigned long value;
118 unsigned int len;
119 char linebuf[MAX_LINE_LEN];
120 char *endp;
121
122 if (which >= MAX_CPUFREQ_VALUE_READ_FILES)
123 return 0;
124
125 len = sysfs_cpufreq_read_file(cpu, cpufreq_value_files[which],
126 linebuf, sizeof(linebuf));
127
128 if (len == 0)
129 return 0;
130
131 value = strtoul(linebuf, &endp, 0);
132
133 if (endp == linebuf || errno == ERANGE)
134 return 0;
135
136 return value;
137}
138
139/* read access to files which contain one string */
140
141enum cpufreq_string {
142 SCALING_DRIVER,
143 SCALING_GOVERNOR,
144 MAX_CPUFREQ_STRING_FILES
145};
146
147static const char *cpufreq_string_files[MAX_CPUFREQ_STRING_FILES] = {
148 [SCALING_DRIVER] = "scaling_driver",
149 [SCALING_GOVERNOR] = "scaling_governor",
150};
151
152
153static char *sysfs_cpufreq_get_one_string(unsigned int cpu,
154 enum cpufreq_string which)
155{
156 char linebuf[MAX_LINE_LEN];
157 char *result;
158 unsigned int len;
159
160 if (which >= MAX_CPUFREQ_STRING_FILES)
161 return NULL;
162
163 len = sysfs_cpufreq_read_file(cpu, cpufreq_string_files[which],
164 linebuf, sizeof(linebuf));
165 if (len == 0)
166 return NULL;
167
168 result = strdup(linebuf);
169 if (result == NULL)
170 return NULL;
171
172 if (result[strlen(result) - 1] == '\n')
173 result[strlen(result) - 1] = '\0';
174
175 return result;
176}
177
178/* write access */
179
180enum cpufreq_write {
181 WRITE_SCALING_MIN_FREQ,
182 WRITE_SCALING_MAX_FREQ,
183 WRITE_SCALING_GOVERNOR,
184 WRITE_SCALING_SET_SPEED,
185 MAX_CPUFREQ_WRITE_FILES
186};
187
188static const char *cpufreq_write_files[MAX_CPUFREQ_WRITE_FILES] = {
189 [WRITE_SCALING_MIN_FREQ] = "scaling_min_freq",
190 [WRITE_SCALING_MAX_FREQ] = "scaling_max_freq",
191 [WRITE_SCALING_GOVERNOR] = "scaling_governor",
192 [WRITE_SCALING_SET_SPEED] = "scaling_setspeed",
193};
194
195static int sysfs_cpufreq_write_one_value(unsigned int cpu,
196 enum cpufreq_write which,
197 const char *new_value, size_t len)
198{
199 if (which >= MAX_CPUFREQ_WRITE_FILES)
200 return 0;
201
202 if (sysfs_cpufreq_write_file(cpu, cpufreq_write_files[which],
203 new_value, len) != len)
204 return -ENODEV;
205
206 return 0;
207};
208
209unsigned long sysfs_get_freq_kernel(unsigned int cpu)
210{
211 return sysfs_cpufreq_get_one_value(cpu, SCALING_CUR_FREQ);
212}
213
214unsigned long sysfs_get_freq_hardware(unsigned int cpu)
215{
216 return sysfs_cpufreq_get_one_value(cpu, CPUINFO_CUR_FREQ);
217}
218
219unsigned long sysfs_get_freq_transition_latency(unsigned int cpu)
220{
221 return sysfs_cpufreq_get_one_value(cpu, CPUINFO_LATENCY);
222}
223
224int sysfs_get_freq_hardware_limits(unsigned int cpu,
225 unsigned long *min,
226 unsigned long *max)
227{
228 if ((!min) || (!max))
229 return -EINVAL;
230
231 *min = sysfs_cpufreq_get_one_value(cpu, CPUINFO_MIN_FREQ);
232 if (!*min)
233 return -ENODEV;
234
235 *max = sysfs_cpufreq_get_one_value(cpu, CPUINFO_MAX_FREQ);
236 if (!*max)
237 return -ENODEV;
238
239 return 0;
240}
241
242char *sysfs_get_freq_driver(unsigned int cpu)
243{
244 return sysfs_cpufreq_get_one_string(cpu, SCALING_DRIVER);
245}
246
247struct cpufreq_policy *sysfs_get_freq_policy(unsigned int cpu)
248{
249 struct cpufreq_policy *policy;
250
251 policy = malloc(sizeof(struct cpufreq_policy));
252 if (!policy)
253 return NULL;
254
255 policy->governor = sysfs_cpufreq_get_one_string(cpu, SCALING_GOVERNOR);
256 if (!policy->governor) {
257 free(policy);
258 return NULL;
259 }
260 policy->min = sysfs_cpufreq_get_one_value(cpu, SCALING_MIN_FREQ);
261 policy->max = sysfs_cpufreq_get_one_value(cpu, SCALING_MAX_FREQ);
262 if ((!policy->min) || (!policy->max)) {
263 free(policy->governor);
264 free(policy);
265 return NULL;
266 }
267
268 return policy;
269}
270
271struct cpufreq_available_governors *
272sysfs_get_freq_available_governors(unsigned int cpu) {
273 struct cpufreq_available_governors *first = NULL;
274 struct cpufreq_available_governors *current = NULL;
275 char linebuf[MAX_LINE_LEN];
276 unsigned int pos, i;
277 unsigned int len;
278
279 len = sysfs_cpufreq_read_file(cpu, "scaling_available_governors",
280 linebuf, sizeof(linebuf));
281 if (len == 0)
282 return NULL;
283
284 pos = 0;
285 for (i = 0; i < len; i++) {
286 if (linebuf[i] == ' ' || linebuf[i] == '\n') {
287 if (i - pos < 2)
288 continue;
289 if (current) {
290 current->next = malloc(sizeof(*current));
291 if (!current->next)
292 goto error_out;
293 current = current->next;
294 } else {
295 first = malloc(sizeof(*first));
296 if (!first)
297 goto error_out;
298 current = first;
299 }
300 current->first = first;
301 current->next = NULL;
302
303 current->governor = malloc(i - pos + 1);
304 if (!current->governor)
305 goto error_out;
306
307 memcpy(current->governor, linebuf + pos, i - pos);
308 current->governor[i - pos] = '\0';
309 pos = i + 1;
310 }
311 }
312
313 return first;
314
315 error_out:
316 while (first) {
317 current = first->next;
318 if (first->governor)
319 free(first->governor);
320 free(first);
321 first = current;
322 }
323 return NULL;
324}
325
326
327struct cpufreq_available_frequencies *
328sysfs_get_available_frequencies(unsigned int cpu) {
329 struct cpufreq_available_frequencies *first = NULL;
330 struct cpufreq_available_frequencies *current = NULL;
331 char one_value[SYSFS_PATH_MAX];
332 char linebuf[MAX_LINE_LEN];
333 unsigned int pos, i;
334 unsigned int len;
335
336 len = sysfs_cpufreq_read_file(cpu, "scaling_available_frequencies",
337 linebuf, sizeof(linebuf));
338 if (len == 0)
339 return NULL;
340
341 pos = 0;
342 for (i = 0; i < len; i++) {
343 if (linebuf[i] == ' ' || linebuf[i] == '\n') {
344 if (i - pos < 2)
345 continue;
346 if (i - pos >= SYSFS_PATH_MAX)
347 goto error_out;
348 if (current) {
349 current->next = malloc(sizeof(*current));
350 if (!current->next)
351 goto error_out;
352 current = current->next;
353 } else {
354 first = malloc(sizeof(*first));
355 if (!first)
356 goto error_out;
357 current = first;
358 }
359 current->first = first;
360 current->next = NULL;
361
362 memcpy(one_value, linebuf + pos, i - pos);
363 one_value[i - pos] = '\0';
364 if (sscanf(one_value, "%lu", &current->frequency) != 1)
365 goto error_out;
366
367 pos = i + 1;
368 }
369 }
370
371 return first;
372
373 error_out:
374 while (first) {
375 current = first->next;
376 free(first);
377 first = current;
378 }
379 return NULL;
380}
381
382static struct cpufreq_affected_cpus *sysfs_get_cpu_list(unsigned int cpu,
383 const char *file)
384{
385 struct cpufreq_affected_cpus *first = NULL;
386 struct cpufreq_affected_cpus *current = NULL;
387 char one_value[SYSFS_PATH_MAX];
388 char linebuf[MAX_LINE_LEN];
389 unsigned int pos, i;
390 unsigned int len;
391
392 len = sysfs_cpufreq_read_file(cpu, file, linebuf, sizeof(linebuf));
393 if (len == 0)
394 return NULL;
395
396 pos = 0;
397 for (i = 0; i < len; i++) {
398 if (i == len || linebuf[i] == ' ' || linebuf[i] == '\n') {
399 if (i - pos < 1)
400 continue;
401 if (i - pos >= SYSFS_PATH_MAX)
402 goto error_out;
403 if (current) {
404 current->next = malloc(sizeof(*current));
405 if (!current->next)
406 goto error_out;
407 current = current->next;
408 } else {
409 first = malloc(sizeof(*first));
410 if (!first)
411 goto error_out;
412 current = first;
413 }
414 current->first = first;
415 current->next = NULL;
416
417 memcpy(one_value, linebuf + pos, i - pos);
418 one_value[i - pos] = '\0';
419
420 if (sscanf(one_value, "%u", &current->cpu) != 1)
421 goto error_out;
422
423 pos = i + 1;
424 }
425 }
426
427 return first;
428
429 error_out:
430 while (first) {
431 current = first->next;
432 free(first);
433 first = current;
434 }
435 return NULL;
436}
437
438struct cpufreq_affected_cpus *sysfs_get_freq_affected_cpus(unsigned int cpu)
439{
440 return sysfs_get_cpu_list(cpu, "affected_cpus");
441}
442
443struct cpufreq_affected_cpus *sysfs_get_freq_related_cpus(unsigned int cpu)
444{
445 return sysfs_get_cpu_list(cpu, "related_cpus");
446}
447
448struct cpufreq_stats *sysfs_get_freq_stats(unsigned int cpu,
449 unsigned long long *total_time) {
450 struct cpufreq_stats *first = NULL;
451 struct cpufreq_stats *current = NULL;
452 char one_value[SYSFS_PATH_MAX];
453 char linebuf[MAX_LINE_LEN];
454 unsigned int pos, i;
455 unsigned int len;
456
457 len = sysfs_cpufreq_read_file(cpu, "stats/time_in_state",
458 linebuf, sizeof(linebuf));
459 if (len == 0)
460 return NULL;
461
462 *total_time = 0;
463 pos = 0;
464 for (i = 0; i < len; i++) {
465 if (i == strlen(linebuf) || linebuf[i] == '\n') {
466 if (i - pos < 2)
467 continue;
468 if ((i - pos) >= SYSFS_PATH_MAX)
469 goto error_out;
470 if (current) {
471 current->next = malloc(sizeof(*current));
472 if (!current->next)
473 goto error_out;
474 current = current->next;
475 } else {
476 first = malloc(sizeof(*first));
477 if (!first)
478 goto error_out;
479 current = first;
480 }
481 current->first = first;
482 current->next = NULL;
483
484 memcpy(one_value, linebuf + pos, i - pos);
485 one_value[i - pos] = '\0';
486 if (sscanf(one_value, "%lu %llu",
487 &current->frequency,
488 &current->time_in_state) != 2)
489 goto error_out;
490
491 *total_time = *total_time + current->time_in_state;
492 pos = i + 1;
493 }
494 }
495
496 return first;
497
498 error_out:
499 while (first) {
500 current = first->next;
501 free(first);
502 first = current;
503 }
504 return NULL;
505}
506
507unsigned long sysfs_get_freq_transitions(unsigned int cpu)
508{
509 return sysfs_cpufreq_get_one_value(cpu, STATS_NUM_TRANSITIONS);
510}
511
512static int verify_gov(char *new_gov, char *passed_gov)
513{
514 unsigned int i, j = 0;
515
516 if (!passed_gov || (strlen(passed_gov) > 19))
517 return -EINVAL;
518
519 strncpy(new_gov, passed_gov, 20);
520 for (i = 0; i < 20; i++) {
521 if (j) {
522 new_gov[i] = '\0';
523 continue;
524 }
525 if ((new_gov[i] >= 'a') && (new_gov[i] <= 'z'))
526 continue;
527
528 if ((new_gov[i] >= 'A') && (new_gov[i] <= 'Z'))
529 continue;
530
531 if (new_gov[i] == '-')
532 continue;
533
534 if (new_gov[i] == '_')
535 continue;
536
537 if (new_gov[i] == '\0') {
538 j = 1;
539 continue;
540 }
541 return -EINVAL;
542 }
543 new_gov[19] = '\0';
544 return 0;
545}
546
547int sysfs_modify_freq_policy_governor(unsigned int cpu, char *governor)
548{
549 char new_gov[SYSFS_PATH_MAX];
550
551 if (!governor)
552 return -EINVAL;
553
554 if (verify_gov(new_gov, governor))
555 return -EINVAL;
556
557 return sysfs_cpufreq_write_one_value(cpu, WRITE_SCALING_GOVERNOR,
558 new_gov, strlen(new_gov));
559};
560
561int sysfs_modify_freq_policy_max(unsigned int cpu, unsigned long max_freq)
562{
563 char value[SYSFS_PATH_MAX];
564
565 snprintf(value, SYSFS_PATH_MAX, "%lu", max_freq);
566
567 return sysfs_cpufreq_write_one_value(cpu, WRITE_SCALING_MAX_FREQ,
568 value, strlen(value));
569};
570
571
572int sysfs_modify_freq_policy_min(unsigned int cpu, unsigned long min_freq)
573{
574 char value[SYSFS_PATH_MAX];
575
576 snprintf(value, SYSFS_PATH_MAX, "%lu", min_freq);
577
578 return sysfs_cpufreq_write_one_value(cpu, WRITE_SCALING_MIN_FREQ,
579 value, strlen(value));
580};
581
582
583int sysfs_set_freq_policy(unsigned int cpu, struct cpufreq_policy *policy)
584{
585 char min[SYSFS_PATH_MAX];
586 char max[SYSFS_PATH_MAX];
587 char gov[SYSFS_PATH_MAX];
588 int ret;
589 unsigned long old_min;
590 int write_max_first;
591
592 if (!policy || !(policy->governor))
593 return -EINVAL;
594
595 if (policy->max < policy->min)
596 return -EINVAL;
597
598 if (verify_gov(gov, policy->governor))
599 return -EINVAL;
600
601 snprintf(min, SYSFS_PATH_MAX, "%lu", policy->min);
602 snprintf(max, SYSFS_PATH_MAX, "%lu", policy->max);
603
604 old_min = sysfs_cpufreq_get_one_value(cpu, SCALING_MIN_FREQ);
605 write_max_first = (old_min && (policy->max < old_min) ? 0 : 1);
606
607 if (write_max_first) {
608 ret = sysfs_cpufreq_write_one_value(cpu, WRITE_SCALING_MAX_FREQ,
609 max, strlen(max));
610 if (ret)
611 return ret;
612 }
613
614 ret = sysfs_cpufreq_write_one_value(cpu, WRITE_SCALING_MIN_FREQ, min,
615 strlen(min));
616 if (ret)
617 return ret;
618
619 if (!write_max_first) {
620 ret = sysfs_cpufreq_write_one_value(cpu, WRITE_SCALING_MAX_FREQ,
621 max, strlen(max));
622 if (ret)
623 return ret;
624 }
625
626 return sysfs_cpufreq_write_one_value(cpu, WRITE_SCALING_GOVERNOR,
627 gov, strlen(gov));
628}
629
630int sysfs_set_frequency(unsigned int cpu, unsigned long target_frequency)
631{
632 struct cpufreq_policy *pol = sysfs_get_freq_policy(cpu);
633 char userspace_gov[] = "userspace";
634 char freq[SYSFS_PATH_MAX];
635 int ret;
636
637 if (!pol)
638 return -ENODEV;
639
640 if (strncmp(pol->governor, userspace_gov, 9) != 0) {
641 ret = sysfs_modify_freq_policy_governor(cpu, userspace_gov);
642 if (ret) {
643 cpufreq_put_policy(pol);
644 return ret;
645 }
646 }
647
648 cpufreq_put_policy(pol);
649
650 snprintf(freq, SYSFS_PATH_MAX, "%lu", target_frequency);
651
652 return sysfs_cpufreq_write_one_value(cpu, WRITE_SCALING_SET_SPEED,
653 freq, strlen(freq));
654}
655
656/* CPUFREQ sysfs access **************************************************/
657
658/* General sysfs access **************************************************/
659int sysfs_cpu_exists(unsigned int cpu)
660{
661 char file[SYSFS_PATH_MAX];
662 struct stat statbuf;
663
664 snprintf(file, SYSFS_PATH_MAX, PATH_TO_CPU "cpu%u/", cpu);
665
666 if (stat(file, &statbuf) != 0)
667 return -ENOSYS;
668
669 return S_ISDIR(statbuf.st_mode) ? 0 : -ENOSYS;
670}
671
672/* General sysfs access **************************************************/
diff --git a/tools/power/cpupower/lib/sysfs.h b/tools/power/cpupower/lib/sysfs.h
deleted file mode 100644
index c76a5e0af501..000000000000
--- a/tools/power/cpupower/lib/sysfs.h
+++ /dev/null
@@ -1,31 +0,0 @@
1/* General */
2extern unsigned int sysfs_cpu_exists(unsigned int cpu);
3
4/* CPUfreq */
5extern unsigned long sysfs_get_freq_kernel(unsigned int cpu);
6extern unsigned long sysfs_get_freq_hardware(unsigned int cpu);
7extern unsigned long sysfs_get_freq_transition_latency(unsigned int cpu);
8extern int sysfs_get_freq_hardware_limits(unsigned int cpu,
9 unsigned long *min, unsigned long *max);
10extern char *sysfs_get_freq_driver(unsigned int cpu);
11extern struct cpufreq_policy *sysfs_get_freq_policy(unsigned int cpu);
12extern struct cpufreq_available_governors *sysfs_get_freq_available_governors(
13 unsigned int cpu);
14extern struct cpufreq_available_frequencies *sysfs_get_available_frequencies(
15 unsigned int cpu);
16extern struct cpufreq_affected_cpus *sysfs_get_freq_affected_cpus(
17 unsigned int cpu);
18extern struct cpufreq_affected_cpus *sysfs_get_freq_related_cpus(
19 unsigned int cpu);
20extern struct cpufreq_stats *sysfs_get_freq_stats(unsigned int cpu,
21 unsigned long long *total_time);
22extern unsigned long sysfs_get_freq_transitions(unsigned int cpu);
23extern int sysfs_set_freq_policy(unsigned int cpu,
24 struct cpufreq_policy *policy);
25extern int sysfs_modify_freq_policy_min(unsigned int cpu,
26 unsigned long min_freq);
27extern int sysfs_modify_freq_policy_max(unsigned int cpu,
28 unsigned long max_freq);
29extern int sysfs_modify_freq_policy_governor(unsigned int cpu, char *governor);
30extern int sysfs_set_frequency(unsigned int cpu,
31 unsigned long target_frequency);
diff --git a/tools/power/cpupower/utils/cpufreq-set.c b/tools/power/cpupower/utils/cpufreq-set.c
index 0fbd1a22c0a9..b4bf76971dc9 100644
--- a/tools/power/cpupower/utils/cpufreq-set.c
+++ b/tools/power/cpupower/utils/cpufreq-set.c
@@ -16,8 +16,8 @@
16#include <getopt.h> 16#include <getopt.h>
17 17
18#include "cpufreq.h" 18#include "cpufreq.h"
19#include "cpuidle.h"
19#include "helpers/helpers.h" 20#include "helpers/helpers.h"
20#include "helpers/sysfs.h"
21 21
22#define NORM_FREQ_LEN 32 22#define NORM_FREQ_LEN 32
23 23
@@ -296,7 +296,7 @@ int cmd_freq_set(int argc, char **argv)
296 struct cpufreq_affected_cpus *cpus; 296 struct cpufreq_affected_cpus *cpus;
297 297
298 if (!bitmask_isbitset(cpus_chosen, cpu) || 298 if (!bitmask_isbitset(cpus_chosen, cpu) ||
299 cpufreq_cpu_exists(cpu)) 299 cpupower_is_cpu_online(cpu))
300 continue; 300 continue;
301 301
302 cpus = cpufreq_get_related_cpus(cpu); 302 cpus = cpufreq_get_related_cpus(cpu);
@@ -316,10 +316,10 @@ int cmd_freq_set(int argc, char **argv)
316 cpu <= bitmask_last(cpus_chosen); cpu++) { 316 cpu <= bitmask_last(cpus_chosen); cpu++) {
317 317
318 if (!bitmask_isbitset(cpus_chosen, cpu) || 318 if (!bitmask_isbitset(cpus_chosen, cpu) ||
319 cpufreq_cpu_exists(cpu)) 319 cpupower_is_cpu_online(cpu))
320 continue; 320 continue;
321 321
322 if (sysfs_is_cpu_online(cpu) != 1) 322 if (cpupower_is_cpu_online(cpu) != 1)
323 continue; 323 continue;
324 324
325 printf(_("Setting cpu: %d\n"), cpu); 325 printf(_("Setting cpu: %d\n"), cpu);
diff --git a/tools/power/cpupower/utils/cpuidle-info.c b/tools/power/cpupower/utils/cpuidle-info.c
index 8bf8ab5ffa25..b59c85defa05 100644
--- a/tools/power/cpupower/utils/cpuidle-info.c
+++ b/tools/power/cpupower/utils/cpuidle-info.c
@@ -13,8 +13,10 @@
13#include <string.h> 13#include <string.h>
14#include <getopt.h> 14#include <getopt.h>
15 15
16#include "helpers/helpers.h" 16#include <cpuidle.h>
17
17#include "helpers/sysfs.h" 18#include "helpers/sysfs.h"
19#include "helpers/helpers.h"
18#include "helpers/bitmask.h" 20#include "helpers/bitmask.h"
19 21
20#define LINE_LEN 10 22#define LINE_LEN 10
@@ -24,7 +26,7 @@ static void cpuidle_cpu_output(unsigned int cpu, int verbose)
24 unsigned int idlestates, idlestate; 26 unsigned int idlestates, idlestate;
25 char *tmp; 27 char *tmp;
26 28
27 idlestates = sysfs_get_idlestate_count(cpu); 29 idlestates = cpuidle_state_count(cpu);
28 if (idlestates == 0) { 30 if (idlestates == 0) {
29 printf(_("CPU %u: No idle states\n"), cpu); 31 printf(_("CPU %u: No idle states\n"), cpu);
30 return; 32 return;
@@ -33,7 +35,7 @@ static void cpuidle_cpu_output(unsigned int cpu, int verbose)
33 printf(_("Number of idle states: %d\n"), idlestates); 35 printf(_("Number of idle states: %d\n"), idlestates);
34 printf(_("Available idle states:")); 36 printf(_("Available idle states:"));
35 for (idlestate = 0; idlestate < idlestates; idlestate++) { 37 for (idlestate = 0; idlestate < idlestates; idlestate++) {
36 tmp = sysfs_get_idlestate_name(cpu, idlestate); 38 tmp = cpuidle_state_name(cpu, idlestate);
37 if (!tmp) 39 if (!tmp)
38 continue; 40 continue;
39 printf(" %s", tmp); 41 printf(" %s", tmp);
@@ -45,28 +47,28 @@ static void cpuidle_cpu_output(unsigned int cpu, int verbose)
45 return; 47 return;
46 48
47 for (idlestate = 0; idlestate < idlestates; idlestate++) { 49 for (idlestate = 0; idlestate < idlestates; idlestate++) {
48 int disabled = sysfs_is_idlestate_disabled(cpu, idlestate); 50 int disabled = cpuidle_is_state_disabled(cpu, idlestate);
49 /* Disabled interface not supported on older kernels */ 51 /* Disabled interface not supported on older kernels */
50 if (disabled < 0) 52 if (disabled < 0)
51 disabled = 0; 53 disabled = 0;
52 tmp = sysfs_get_idlestate_name(cpu, idlestate); 54 tmp = cpuidle_state_name(cpu, idlestate);
53 if (!tmp) 55 if (!tmp)
54 continue; 56 continue;
55 printf("%s%s:\n", tmp, (disabled) ? " (DISABLED) " : ""); 57 printf("%s%s:\n", tmp, (disabled) ? " (DISABLED) " : "");
56 free(tmp); 58 free(tmp);
57 59
58 tmp = sysfs_get_idlestate_desc(cpu, idlestate); 60 tmp = cpuidle_state_desc(cpu, idlestate);
59 if (!tmp) 61 if (!tmp)
60 continue; 62 continue;
61 printf(_("Flags/Description: %s\n"), tmp); 63 printf(_("Flags/Description: %s\n"), tmp);
62 free(tmp); 64 free(tmp);
63 65
64 printf(_("Latency: %lu\n"), 66 printf(_("Latency: %lu\n"),
65 sysfs_get_idlestate_latency(cpu, idlestate)); 67 cpuidle_state_latency(cpu, idlestate));
66 printf(_("Usage: %lu\n"), 68 printf(_("Usage: %lu\n"),
67 sysfs_get_idlestate_usage(cpu, idlestate)); 69 cpuidle_state_usage(cpu, idlestate));
68 printf(_("Duration: %llu\n"), 70 printf(_("Duration: %llu\n"),
69 sysfs_get_idlestate_time(cpu, idlestate)); 71 cpuidle_state_time(cpu, idlestate));
70 } 72 }
71} 73}
72 74
@@ -74,7 +76,7 @@ static void cpuidle_general_output(void)
74{ 76{
75 char *tmp; 77 char *tmp;
76 78
77 tmp = sysfs_get_cpuidle_driver(); 79 tmp = cpuidle_get_driver();
78 if (!tmp) { 80 if (!tmp) {
79 printf(_("Could not determine cpuidle driver\n")); 81 printf(_("Could not determine cpuidle driver\n"));
80 return; 82 return;
@@ -83,7 +85,7 @@ static void cpuidle_general_output(void)
83 printf(_("CPUidle driver: %s\n"), tmp); 85 printf(_("CPUidle driver: %s\n"), tmp);
84 free(tmp); 86 free(tmp);
85 87
86 tmp = sysfs_get_cpuidle_governor(); 88 tmp = cpuidle_get_governor();
87 if (!tmp) { 89 if (!tmp) {
88 printf(_("Could not determine cpuidle governor\n")); 90 printf(_("Could not determine cpuidle governor\n"));
89 return; 91 return;
@@ -98,7 +100,7 @@ static void proc_cpuidle_cpu_output(unsigned int cpu)
98 long max_allowed_cstate = 2000000000; 100 long max_allowed_cstate = 2000000000;
99 unsigned int cstate, cstates; 101 unsigned int cstate, cstates;
100 102
101 cstates = sysfs_get_idlestate_count(cpu); 103 cstates = cpuidle_state_count(cpu);
102 if (cstates == 0) { 104 if (cstates == 0) {
103 printf(_("CPU %u: No C-states info\n"), cpu); 105 printf(_("CPU %u: No C-states info\n"), cpu);
104 return; 106 return;
@@ -113,11 +115,11 @@ static void proc_cpuidle_cpu_output(unsigned int cpu)
113 "type[C%d] "), cstate, cstate); 115 "type[C%d] "), cstate, cstate);
114 printf(_("promotion[--] demotion[--] ")); 116 printf(_("promotion[--] demotion[--] "));
115 printf(_("latency[%03lu] "), 117 printf(_("latency[%03lu] "),
116 sysfs_get_idlestate_latency(cpu, cstate)); 118 cpuidle_state_latency(cpu, cstate));
117 printf(_("usage[%08lu] "), 119 printf(_("usage[%08lu] "),
118 sysfs_get_idlestate_usage(cpu, cstate)); 120 cpuidle_state_usage(cpu, cstate));
119 printf(_("duration[%020Lu] \n"), 121 printf(_("duration[%020Lu] \n"),
120 sysfs_get_idlestate_time(cpu, cstate)); 122 cpuidle_state_time(cpu, cstate));
121 } 123 }
122} 124}
123 125
diff --git a/tools/power/cpupower/utils/cpuidle-set.c b/tools/power/cpupower/utils/cpuidle-set.c
index d6b6ae44b8c2..691c24d50ef4 100644
--- a/tools/power/cpupower/utils/cpuidle-set.c
+++ b/tools/power/cpupower/utils/cpuidle-set.c
@@ -5,12 +5,12 @@
5#include <limits.h> 5#include <limits.h>
6#include <string.h> 6#include <string.h>
7#include <ctype.h> 7#include <ctype.h>
8
9#include <getopt.h> 8#include <getopt.h>
10 9
11#include "cpufreq.h" 10#include <cpufreq.h>
11#include <cpuidle.h>
12
12#include "helpers/helpers.h" 13#include "helpers/helpers.h"
13#include "helpers/sysfs.h"
14 14
15static struct option info_opts[] = { 15static struct option info_opts[] = {
16 {"disable", required_argument, NULL, 'd'}, 16 {"disable", required_argument, NULL, 'd'},
@@ -104,16 +104,16 @@ int cmd_idle_set(int argc, char **argv)
104 if (!bitmask_isbitset(cpus_chosen, cpu)) 104 if (!bitmask_isbitset(cpus_chosen, cpu))
105 continue; 105 continue;
106 106
107 if (sysfs_is_cpu_online(cpu) != 1) 107 if (cpupower_is_cpu_online(cpu) != 1)
108 continue; 108 continue;
109 109
110 idlestates = sysfs_get_idlestate_count(cpu); 110 idlestates = cpuidle_state_count(cpu);
111 if (idlestates <= 0) 111 if (idlestates <= 0)
112 continue; 112 continue;
113 113
114 switch (param) { 114 switch (param) {
115 case 'd': 115 case 'd':
116 ret = sysfs_idlestate_disable(cpu, idlestate, 1); 116 ret = cpuidle_state_disable(cpu, idlestate, 1);
117 if (ret == 0) 117 if (ret == 0)
118 printf(_("Idlestate %u disabled on CPU %u\n"), idlestate, cpu); 118 printf(_("Idlestate %u disabled on CPU %u\n"), idlestate, cpu);
119 else if (ret == -1) 119 else if (ret == -1)
@@ -126,7 +126,7 @@ int cmd_idle_set(int argc, char **argv)
126 idlestate, cpu); 126 idlestate, cpu);
127 break; 127 break;
128 case 'e': 128 case 'e':
129 ret = sysfs_idlestate_disable(cpu, idlestate, 0); 129 ret = cpuidle_state_disable(cpu, idlestate, 0);
130 if (ret == 0) 130 if (ret == 0)
131 printf(_("Idlestate %u enabled on CPU %u\n"), idlestate, cpu); 131 printf(_("Idlestate %u enabled on CPU %u\n"), idlestate, cpu);
132 else if (ret == -1) 132 else if (ret == -1)
@@ -140,13 +140,13 @@ int cmd_idle_set(int argc, char **argv)
140 break; 140 break;
141 case 'D': 141 case 'D':
142 for (idlestate = 0; idlestate < idlestates; idlestate++) { 142 for (idlestate = 0; idlestate < idlestates; idlestate++) {
143 disabled = sysfs_is_idlestate_disabled 143 disabled = cpuidle_is_state_disabled
144 (cpu, idlestate); 144 (cpu, idlestate);
145 state_latency = sysfs_get_idlestate_latency 145 state_latency = cpuidle_state_latency
146 (cpu, idlestate); 146 (cpu, idlestate);
147 if (disabled == 1) { 147 if (disabled == 1) {
148 if (latency > state_latency){ 148 if (latency > state_latency){
149 ret = sysfs_idlestate_disable 149 ret = cpuidle_state_disable
150 (cpu, idlestate, 0); 150 (cpu, idlestate, 0);
151 if (ret == 0) 151 if (ret == 0)
152 printf(_("Idlestate %u enabled on CPU %u\n"), idlestate, cpu); 152 printf(_("Idlestate %u enabled on CPU %u\n"), idlestate, cpu);
@@ -154,7 +154,7 @@ int cmd_idle_set(int argc, char **argv)
154 continue; 154 continue;
155 } 155 }
156 if (latency <= state_latency){ 156 if (latency <= state_latency){
157 ret = sysfs_idlestate_disable 157 ret = cpuidle_state_disable
158 (cpu, idlestate, 1); 158 (cpu, idlestate, 1);
159 if (ret == 0) 159 if (ret == 0)
160 printf(_("Idlestate %u disabled on CPU %u\n"), idlestate, cpu); 160 printf(_("Idlestate %u disabled on CPU %u\n"), idlestate, cpu);
@@ -163,10 +163,10 @@ int cmd_idle_set(int argc, char **argv)
163 break; 163 break;
164 case 'E': 164 case 'E':
165 for (idlestate = 0; idlestate < idlestates; idlestate++) { 165 for (idlestate = 0; idlestate < idlestates; idlestate++) {
166 disabled = sysfs_is_idlestate_disabled 166 disabled = cpuidle_is_state_disabled
167 (cpu, idlestate); 167 (cpu, idlestate);
168 if (disabled == 1) { 168 if (disabled == 1) {
169 ret = sysfs_idlestate_disable 169 ret = cpuidle_state_disable
170 (cpu, idlestate, 0); 170 (cpu, idlestate, 0);
171 if (ret == 0) 171 if (ret == 0)
172 printf(_("Idlestate %u enabled on CPU %u\n"), idlestate, cpu); 172 printf(_("Idlestate %u enabled on CPU %u\n"), idlestate, cpu);
diff --git a/tools/power/cpupower/utils/helpers/helpers.h b/tools/power/cpupower/utils/helpers/helpers.h
index aa9e95486a2d..afb66f80554e 100644
--- a/tools/power/cpupower/utils/helpers/helpers.h
+++ b/tools/power/cpupower/utils/helpers/helpers.h
@@ -14,6 +14,7 @@
14#include <locale.h> 14#include <locale.h>
15 15
16#include "helpers/bitmask.h" 16#include "helpers/bitmask.h"
17#include <cpupower.h>
17 18
18/* Internationalization ****************************/ 19/* Internationalization ****************************/
19#ifdef NLS 20#ifdef NLS
@@ -92,31 +93,6 @@ extern int get_cpu_info(unsigned int cpu, struct cpupower_cpu_info *cpu_info);
92extern struct cpupower_cpu_info cpupower_cpu_info; 93extern struct cpupower_cpu_info cpupower_cpu_info;
93/* cpuid and cpuinfo helpers **************************/ 94/* cpuid and cpuinfo helpers **************************/
94 95
95struct cpuid_core_info {
96 int pkg;
97 int core;
98 int cpu;
99
100 /* flags */
101 unsigned int is_online:1;
102};
103
104/* CPU topology/hierarchy parsing ******************/
105struct cpupower_topology {
106 /* Amount of CPU cores, packages and threads per core in the system */
107 unsigned int cores;
108 unsigned int pkgs;
109 unsigned int threads; /* per core */
110
111 /* Array gets mallocated with cores entries, holding per core info */
112 struct cpuid_core_info *core_info;
113};
114
115extern int get_cpu_topology(struct cpupower_topology *cpu_top);
116extern void cpu_topology_release(struct cpupower_topology cpu_top);
117
118/* CPU topology/hierarchy parsing ******************/
119
120/* X86 ONLY ****************************************/ 96/* X86 ONLY ****************************************/
121#if defined(__i386__) || defined(__x86_64__) 97#if defined(__i386__) || defined(__x86_64__)
122 98
diff --git a/tools/power/cpupower/utils/helpers/topology.c b/tools/power/cpupower/utils/helpers/topology.c
index 5f9c908f4557..a1a6c6041a1e 100644
--- a/tools/power/cpupower/utils/helpers/topology.c
+++ b/tools/power/cpupower/utils/helpers/topology.c
@@ -16,110 +16,7 @@
16#include <errno.h> 16#include <errno.h>
17#include <fcntl.h> 17#include <fcntl.h>
18 18
19#include <helpers/helpers.h> 19#include <cpuidle.h>
20#include <helpers/sysfs.h>
21 20
22/* returns -1 on failure, 0 on success */ 21/* CPU topology/hierarchy parsing ******************/
23static int sysfs_topology_read_file(unsigned int cpu, const char *fname, int *result)
24{
25 char linebuf[MAX_LINE_LEN];
26 char *endp;
27 char path[SYSFS_PATH_MAX];
28 22
29 snprintf(path, sizeof(path), PATH_TO_CPU "cpu%u/topology/%s",
30 cpu, fname);
31 if (sysfs_read_file(path, linebuf, MAX_LINE_LEN) == 0)
32 return -1;
33 *result = strtol(linebuf, &endp, 0);
34 if (endp == linebuf || errno == ERANGE)
35 return -1;
36 return 0;
37}
38
39static int __compare(const void *t1, const void *t2)
40{
41 struct cpuid_core_info *top1 = (struct cpuid_core_info *)t1;
42 struct cpuid_core_info *top2 = (struct cpuid_core_info *)t2;
43 if (top1->pkg < top2->pkg)
44 return -1;
45 else if (top1->pkg > top2->pkg)
46 return 1;
47 else if (top1->core < top2->core)
48 return -1;
49 else if (top1->core > top2->core)
50 return 1;
51 else if (top1->cpu < top2->cpu)
52 return -1;
53 else if (top1->cpu > top2->cpu)
54 return 1;
55 else
56 return 0;
57}
58
59/*
60 * Returns amount of cpus, negative on error, cpu_top must be
61 * passed to cpu_topology_release to free resources
62 *
63 * Array is sorted after ->pkg, ->core, then ->cpu
64 */
65int get_cpu_topology(struct cpupower_topology *cpu_top)
66{
67 int cpu, last_pkg, cpus = sysconf(_SC_NPROCESSORS_CONF);
68
69 cpu_top->core_info = malloc(sizeof(struct cpuid_core_info) * cpus);
70 if (cpu_top->core_info == NULL)
71 return -ENOMEM;
72 cpu_top->pkgs = cpu_top->cores = 0;
73 for (cpu = 0; cpu < cpus; cpu++) {
74 cpu_top->core_info[cpu].cpu = cpu;
75 cpu_top->core_info[cpu].is_online = sysfs_is_cpu_online(cpu);
76 if(sysfs_topology_read_file(
77 cpu,
78 "physical_package_id",
79 &(cpu_top->core_info[cpu].pkg)) < 0) {
80 cpu_top->core_info[cpu].pkg = -1;
81 cpu_top->core_info[cpu].core = -1;
82 continue;
83 }
84 if(sysfs_topology_read_file(
85 cpu,
86 "core_id",
87 &(cpu_top->core_info[cpu].core)) < 0) {
88 cpu_top->core_info[cpu].pkg = -1;
89 cpu_top->core_info[cpu].core = -1;
90 continue;
91 }
92 }
93
94 qsort(cpu_top->core_info, cpus, sizeof(struct cpuid_core_info),
95 __compare);
96
97 /* Count the number of distinct pkgs values. This works
98 because the primary sort of the core_info struct was just
99 done by pkg value. */
100 last_pkg = cpu_top->core_info[0].pkg;
101 for(cpu = 1; cpu < cpus; cpu++) {
102 if (cpu_top->core_info[cpu].pkg != last_pkg &&
103 cpu_top->core_info[cpu].pkg != -1) {
104
105 last_pkg = cpu_top->core_info[cpu].pkg;
106 cpu_top->pkgs++;
107 }
108 }
109 if (!(cpu_top->core_info[0].pkg == -1))
110 cpu_top->pkgs++;
111
112 /* Intel's cores count is not consecutively numbered, there may
113 * be a core_id of 3, but none of 2. Assume there always is 0
114 * Get amount of cores by counting duplicates in a package
115 for (cpu = 0; cpu_top->core_info[cpu].pkg = 0 && cpu < cpus; cpu++) {
116 if (cpu_top->core_info[cpu].core == 0)
117 cpu_top->cores++;
118 */
119 return cpus;
120}
121
122void cpu_topology_release(struct cpupower_topology cpu_top)
123{
124 free(cpu_top.core_info);
125}
diff --git a/tools/power/cpupower/utils/idle_monitor/cpuidle_sysfs.c b/tools/power/cpupower/utils/idle_monitor/cpuidle_sysfs.c
index bcd22a1a3970..1b5da0066ebf 100644
--- a/tools/power/cpupower/utils/idle_monitor/cpuidle_sysfs.c
+++ b/tools/power/cpupower/utils/idle_monitor/cpuidle_sysfs.c
@@ -10,8 +10,8 @@
10#include <stdint.h> 10#include <stdint.h>
11#include <string.h> 11#include <string.h>
12#include <limits.h> 12#include <limits.h>
13#include <cpuidle.h>
13 14
14#include "helpers/sysfs.h"
15#include "helpers/helpers.h" 15#include "helpers/helpers.h"
16#include "idle_monitor/cpupower-monitor.h" 16#include "idle_monitor/cpupower-monitor.h"
17 17
@@ -51,7 +51,7 @@ static int cpuidle_start(void)
51 for (state = 0; state < cpuidle_sysfs_monitor.hw_states_num; 51 for (state = 0; state < cpuidle_sysfs_monitor.hw_states_num;
52 state++) { 52 state++) {
53 previous_count[cpu][state] = 53 previous_count[cpu][state] =
54 sysfs_get_idlestate_time(cpu, state); 54 cpuidle_state_time(cpu, state);
55 dprint("CPU %d - State: %d - Val: %llu\n", 55 dprint("CPU %d - State: %d - Val: %llu\n",
56 cpu, state, previous_count[cpu][state]); 56 cpu, state, previous_count[cpu][state]);
57 } 57 }
@@ -70,7 +70,7 @@ static int cpuidle_stop(void)
70 for (state = 0; state < cpuidle_sysfs_monitor.hw_states_num; 70 for (state = 0; state < cpuidle_sysfs_monitor.hw_states_num;
71 state++) { 71 state++) {
72 current_count[cpu][state] = 72 current_count[cpu][state] =
73 sysfs_get_idlestate_time(cpu, state); 73 cpuidle_state_time(cpu, state);
74 dprint("CPU %d - State: %d - Val: %llu\n", 74 dprint("CPU %d - State: %d - Val: %llu\n",
75 cpu, state, previous_count[cpu][state]); 75 cpu, state, previous_count[cpu][state]);
76 } 76 }
@@ -132,13 +132,13 @@ static struct cpuidle_monitor *cpuidle_register(void)
132 char *tmp; 132 char *tmp;
133 133
134 /* Assume idle state count is the same for all CPUs */ 134 /* Assume idle state count is the same for all CPUs */
135 cpuidle_sysfs_monitor.hw_states_num = sysfs_get_idlestate_count(0); 135 cpuidle_sysfs_monitor.hw_states_num = cpuidle_state_count(0);
136 136
137 if (cpuidle_sysfs_monitor.hw_states_num <= 0) 137 if (cpuidle_sysfs_monitor.hw_states_num <= 0)
138 return NULL; 138 return NULL;
139 139
140 for (num = 0; num < cpuidle_sysfs_monitor.hw_states_num; num++) { 140 for (num = 0; num < cpuidle_sysfs_monitor.hw_states_num; num++) {
141 tmp = sysfs_get_idlestate_name(0, num); 141 tmp = cpuidle_state_name(0, num);
142 if (tmp == NULL) 142 if (tmp == NULL)
143 continue; 143 continue;
144 144
@@ -146,7 +146,7 @@ static struct cpuidle_monitor *cpuidle_register(void)
146 strncpy(cpuidle_cstates[num].name, tmp, CSTATE_NAME_LEN - 1); 146 strncpy(cpuidle_cstates[num].name, tmp, CSTATE_NAME_LEN - 1);
147 free(tmp); 147 free(tmp);
148 148
149 tmp = sysfs_get_idlestate_desc(0, num); 149 tmp = cpuidle_state_desc(0, num);
150 if (tmp == NULL) 150 if (tmp == NULL)
151 continue; 151 continue;
152 strncpy(cpuidle_cstates[num].desc, tmp, CSTATE_DESC_LEN - 1); 152 strncpy(cpuidle_cstates[num].desc, tmp, CSTATE_DESC_LEN - 1);