cpufreq Archive on lore.kernel.org
 help / color / mirror / Atom feed
* Rename cpufrequtils into cpupowerutils and provide some basic cpuidle functionality
@ 2010-09-23 15:30 Thomas Renninger
  2010-09-23 15:30 ` [PATCH 1/4] cpufrequtils: Prepare for non-cpufreq related power features by renaming files Thomas Renninger
                   ` (4 more replies)
  0 siblings, 5 replies; 13+ messages in thread
From: Thomas Renninger @ 2010-09-23 15:30 UTC (permalink / raw)
  To: cpufreq, linux; +Cc: trenn

Hi Dominik,

here my latest patchset.
If this isn't totally wrong, I'd appreciate if you could
push these already (into a separate branch for now?)
and I can provide on-top patches/fix-ups.

I do not want to pollute other lists for now.
If you accept this and I did some further testing, packaging,
cleanup, etc., I'd like to announce this work on some more lists
(lesswatts, linux-pm, acpi, ...).

Thanks a lot,

      Thomas



^ permalink raw reply	[flat|nested] 13+ messages in thread

* [PATCH 1/4] cpufrequtils: Prepare for non-cpufreq related power features by renaming files
  2010-09-23 15:30 Rename cpufrequtils into cpupowerutils and provide some basic cpuidle functionality Thomas Renninger
@ 2010-09-23 15:30 ` Thomas Renninger
  2010-09-23 15:30 ` [PATCH 2/4] cpufrequtils: Add cpuidle-info tool with some cstate library functions Thomas Renninger
                   ` (3 subsequent siblings)
  4 siblings, 0 replies; 13+ messages in thread
From: Thomas Renninger @ 2010-09-23 15:30 UTC (permalink / raw)
  To: cpufreq, linux; +Cc: trenn

aperf.c -> cpufreq-aperf.c
info.c  -> cpufreq-info.c
set.c   -> cpufreq-set.c

Creating UTIL_BINS variable in the Makefile seem to have the effect that all
util binaries are rebuild, even if only one got modified.
This still was the nicest way I found, could get cleaned up by someone who
is more familiar with Makefiles than I am.

Signed-off-by: Thomas Renninger <trenn@suse.de>
CC: linux@dominikbrodowski.net
CC: cpufreq@vger.kernel.org
---
 Makefile              |   17 +-
 utils/aperf.c         |  431 ---------------------------------
 utils/cpufreq-aperf.c |  431 +++++++++++++++++++++++++++++++++
 utils/cpufreq-info.c  |  629 +++++++++++++++++++++++++++++++++++++++++++++++++
 utils/cpufreq-set.c   |  375 +++++++++++++++++++++++++++++
 utils/info.c          |  629 -------------------------------------------------
 utils/set.c           |  375 -----------------------------
 7 files changed, 1443 insertions(+), 1444 deletions(-)
 delete mode 100644 utils/aperf.c
 create mode 100644 utils/cpufreq-aperf.c
 create mode 100644 utils/cpufreq-info.c
 create mode 100644 utils/cpufreq-set.c
 delete mode 100644 utils/info.c
 delete mode 100644 utils/set.c

diff --git a/Makefile b/Makefile
index e23c644..aa4b9ff 100644
--- a/Makefile
+++ b/Makefile
@@ -111,7 +111,8 @@ WARNINGS += -Wshadow
 CPPFLAGS += -DVERSION=\"$(VERSION)\" -DPACKAGE=\"$(PACKAGE)\" \
 		-DPACKAGE_BUGREPORT=\"$(PACKAGE_BUGREPORT)\" -D_GNU_SOURCE
 
-UTIL_SRC = 	utils/info.c utils/set.c utils/aperf.c utils/cpuid.h
+UTIL_SRC = 	utils/cpufreq-info.c utils/cpufreq-set.c utils/cpufreq-aperf.c utils/cpuid.h
+UTIL_BINS = 	utils/cpufreq-info utils/cpufreq-set utils/cpufreq-aperf
 LIB_HEADERS = 	lib/cpufreq.h lib/sysfs.h
 LIB_SRC = 	lib/cpufreq.c lib/sysfs.c
 LIB_OBJS = 	lib/cpufreq.o lib/sysfs.o
@@ -171,12 +172,12 @@ libcpufreq.so.$(LIB_MAJ): $(LIB_OBJS)
 
 libcpufreq: libcpufreq.so.$(LIB_MAJ)
 
-cpufreq-%: libcpufreq.so.$(LIB_MAJ) $(UTIL_SRC)
-	$(QUIET) $(CC) $(CPPFLAGS) $(CFLAGS) -I. -I./lib/ -c -o utils/$@.o utils/$*.c
-	$(QUIET) $(CC) $(CFLAGS) $(LDFLAGS) -L. -o $@ utils/$@.o -lcpufreq
+$(UTIL_BINS): libcpufreq.so.$(LIB_MAJ) $(UTIL_SRC)
+	$(QUIET) $(CC) $(CPPFLAGS) $(CFLAGS) -I. -I./lib/ -c $@.c -o $@.o
+	$(QUIET) $(CC) $(CFLAGS) $(LDFLAGS) -L. -o $@ $@.o -lcpufreq
 	$(QUIET) $(STRIPCMD) $@
 
-utils: cpufreq-info cpufreq-set cpufreq-aperf
+utils: $(UTIL_BINS)
 
 po/$(PACKAGE).pot: $(UTIL_SRC)
 	@xgettext --default-domain=$(PACKAGE) --add-comments \
@@ -203,7 +204,7 @@ compile-bench: libcpufreq
 clean:
 	-find . \( -not -type d \) -and \( -name '*~' -o -name '*.[oas]' \) -type f -print \
 	 | xargs rm -f
-	-rm -f cpufreq-info cpufreq-set cpufreq-aperf
+	-rm -f $(UTIL_BINS)
 	-rm -f libcpufreq.so*
 	-rm -f build/ccdv
 	-rm -rf po/*.gmo po/*.pot
@@ -218,9 +219,7 @@ install-lib:
 
 install-tools:
 	$(INSTALL) -d $(DESTDIR)${bindir}
-	$(INSTALL_PROGRAM) cpufreq-set $(DESTDIR)${bindir}/cpufreq-set
-	$(INSTALL_PROGRAM) cpufreq-info $(DESTDIR)${bindir}/cpufreq-info
-	$(INSTALL_PROGRAM) cpufreq-aperf $(DESTDIR)${bindir}/cpufreq-aperf
+	$(INSTALL_PROGRAM) $(UTIL_BINS) $(DESTDIR)${bindir}
 
 install-man:
 	$(INSTALL_DATA) -D man/cpufreq-set.1 $(DESTDIR)${mandir}/man1/cpufreq-set.1
diff --git a/utils/aperf.c b/utils/aperf.c
deleted file mode 100644
index 1c64501..0000000
--- a/utils/aperf.c
+++ /dev/null
@@ -1,431 +0,0 @@
-/*
- *  Copyright (C) 2009  Thomas Renninger <trenn@suse.de>, Novell Inc.
- *
- *  Inspired by these projects:
- *    cpuid (by Todd Allen)
- *    msr-tools (by H. Peter Anvin <hpa@zytor.com>)
- *
- *  Licensed under the terms of the GNU GPL License version 2.
- *
- *
- *  What does this program do:
- *
- *  On latest processors exist two MSR registers refered to as:
- *    - MPERF increasing with maxium (P0) frequency in C0
- *    - APERF increasing with current/actual frequency in C0
- *
- *  From this information the average frequency over a time period can be
- *  calculated and this is what this tool does.
- *
- *  A nice falloff feature beside the average frequency is the time
- *  a processor core remained in C0 (working state) or any CX (sleep state)
- *  processor sleep state during the measured time period. This information
- *  can be determined from the fact that MPERF only increases in C0 state.
- *
- *  Note: There were kernels which reset MPERF/APERF registers to 0.
- *        This got reverted by git commit
- *                  18b2646fe3babeb40b34a0c1751e0bf5adfdc64c
- *        which was commited to 2.6.30-rcX mainline kernels
- *        For kernels where the kernel rests MPERF/APERF registers to 0,
- *        this tool will not work. It cannot be detected whether this happened.
- *
- * Possible ToDos/Enhancments:
- *
- *  - Refresh the screen when mulitple cpus are poked and display results
- *    on one screen
- *    -This would introduce a lot more complexity, not sure whether it's
- *       wanted/needed. I'd vote to better not do that.
- *  - Manpage
- *  - Translations
- *  - ...
- */
-
-
-#include <stdio.h>
-#include <stdlib.h>
-#include <unistd.h>
-#include <getopt.h>
-#include <sys/time.h>
-#include <sys/types.h>
-#include <stdint.h>
-#include <errno.h>
-#include <fcntl.h>
-#include <string.h>
-
-#include "cpufreq.h"
-#include "cpuid.h"
-
-#define MSR_IA32_APERF 0x000000E8
-#define MSR_IA32_MPERF 0x000000E7
-
-struct avg_perf_cpu_info
-{
-	unsigned long max_freq;
-	uint64_t saved_aperf;
-	uint64_t saved_mperf;
-	uint32_t is_valid:1;
-};
-
-static int cpu_has_effective_freq()
-{
-#if defined(__i386__) || defined(__x86_64__)
-	/* largest base level */
-	if (cpuid_eax(0) < 6)
-		return 0;
-
-	return cpuid_ecx(6) & 0x1;
-#else
-	return 0;
-#endif
-}
-
-/*
- * read_msr
- *
- * Will return 0 on success and -1 on failure.
- * Possible errno values could be:
- * EFAULT -If the read/write did not fully complete
- * EIO    -If the CPU does not support MSRs
- * ENXIO  -If the CPU does not exist
- */
-
-static int read_msr(int cpu, unsigned int idx, unsigned long long *val)
-{
-	int fd;
-	char msr_file_name[64];
-
-	sprintf(msr_file_name, "/dev/cpu/%d/msr", cpu);
-	fd = open(msr_file_name, O_RDONLY);
-	if (fd < 0)
-		return -1;
-	if (lseek(fd, idx, SEEK_CUR) == -1)
-		goto err;
-	if (read(fd, val, sizeof val) != sizeof *val)
-		goto err;
-	close(fd);
-	return 0;
- err:
-	close(fd);
-	return -1;
-}
-
-/*
- * get_aperf_mperf()
- *
- * Returns the current aperf/mperf MSR values of cpu
- */
-static int get_aperf_mperf(unsigned int cpu, uint64_t *aperf, uint64_t *mperf)
-{
-	int retval;
-
-	retval = read_msr(cpu, MSR_IA32_APERF, (unsigned long long*)aperf);
-	if (retval < 0)
-		return retval;
-
-	retval = read_msr(cpu, MSR_IA32_MPERF, (unsigned long long*)mperf);
-	if (retval < 0)
-		return retval;
-	return 0;
-}
-
-/*
- * get_average_perf()
- *
- * Returns the average performance (also considers boosted frequencies)
- * 
- * Input:
- *   aperf_diff: Difference of the aperf register over a time period
- *   mperf_diff: Difference of the mperf register over the same time period
- *   max_freq:   Maximum frequency (P0)
- *
- * Returns:
- *   Average performance over the time period
- */
-static unsigned long get_average_perf(unsigned long max_freq,
-				      uint64_t aperf_diff,
-				      uint64_t mperf_diff)
-{
-	unsigned int perf_percent = 0;
-	if (((unsigned long)(-1) / 100) < aperf_diff) {
-		int shift_count = 7;
-		aperf_diff >>= shift_count;
-		mperf_diff >>= shift_count;
-	}
-	perf_percent = (aperf_diff * 100) / mperf_diff;
-	return (max_freq * perf_percent) / 100;
-}
-
-/*
- * get_C_state_time()
- *
- * Calculates the time the processor was in C0 and Cx processor sleep states
- *
- * As mperf does only tick in C0 at maximum frequency, this is a nice "falloff"
- * functionality and more accurate than powertop or other kernel timer based
- * C-state measurings (and can be used to verify whether they are correct.
- *
- * Input:
- *   time_diff:  The time passed for which the mperf_diff was calulcated on
- *   mperf_diff: The value the mperf register increased during time_diff
- *   max_freq:   Maximum frequency of the processor (P0) in kHz
- *
- * Output:
- *   C0_time:    The time the processor was in C0
- *   CX_time:    The time the processor was in CX
- *   percent:    Percentage the processor stayed in C0
- */
-static int get_C_state_time(struct timeval time_diff, uint64_t mperf_diff,
-		     unsigned long max_freq,
-		     struct timeval *C0_time, struct timeval *CX_time,
-		     unsigned int *percent)
-{
-	unsigned long long overall_msecs, expected_ticks, c0_time, cx_time;
-
-	overall_msecs = (time_diff.tv_sec * 1000 * 1000  + time_diff.tv_usec)
-		/ 1000;
-
-	expected_ticks = max_freq * overall_msecs;
-	*percent = (mperf_diff * 100) / expected_ticks;
-
-	cx_time = (expected_ticks - mperf_diff) / max_freq;
-	c0_time = mperf_diff / max_freq;
-
-	CX_time->tv_sec  = cx_time / 1000;
-	CX_time->tv_usec = cx_time % 1000;
-	C0_time->tv_sec  = c0_time / 1000;
-	C0_time->tv_usec = c0_time % 1000;
-	return 0;
-}
-
-static int get_measure_start_info(unsigned int cpu,
-				  struct avg_perf_cpu_info *cpu_info)
-{
-	unsigned long min, max;
-	uint64_t aperf, mperf;
-	int ret;
-
-	cpu_info->is_valid = 0;
-
-	if (cpufreq_get_hardware_limits(cpu, &min, &max))
-		return -EINVAL;
-
-	cpu_info->max_freq = max;
-	
-	ret = get_aperf_mperf(cpu, &aperf, &mperf);
-	if (ret < 0)
-		return -EINVAL;
-
-	cpu_info->saved_aperf = aperf;
-	cpu_info->saved_mperf = mperf;
-	cpu_info->is_valid = 1;
-
-	return 0;
-}
-
-static void print_cpu_stats(unsigned long average, struct timeval c0_time,
-			    struct timeval cx_time, unsigned int c0_percent)
-{
-	printf("%.7lu\t\t\t", average);
-	printf("%.2lu sec %.3lu ms\t", c0_time.tv_sec, c0_time.tv_usec);
-	printf("%.2lu sec %.3lu ms\t", cx_time.tv_sec, cx_time.tv_usec);
-	printf("%.2u", c0_percent);
-}
-
-static int do_measuring_on_cpu(int sleep_time, int once, int cpu)
-{
-	int ret;
-	unsigned long average;
-	unsigned int c0_percent;
-	struct timeval start_time, current_time, diff_time, C0_time, CX_time;
-	uint64_t current_aperf, current_mperf, mperf_diff, aperf_diff;
-	struct avg_perf_cpu_info cpu_info;
-
-	ret = get_measure_start_info(cpu, &cpu_info);
-	if (ret)
-		return ret;
-
-	while(1) {
-		gettimeofday(&start_time, NULL);
-		sleep(sleep_time);
-		/* ToDo: just add a second on the timeval struct? */
-		gettimeofday(&current_time, NULL);
-		timersub(&current_time, &start_time, &diff_time);
-		memcpy(&start_time, &current_time,
-		       sizeof(struct timeval));
-
-		if (!cpu_info.is_valid)
-			continue;
-
-		printf("%.3u\t", cpu);
-
-		ret = get_aperf_mperf(cpu, &current_aperf, &current_mperf);
-		if (ret < 0) {
-			printf("[offline]\n");
-			continue;
-		}
-
-		mperf_diff = current_mperf - cpu_info.saved_mperf;
-		aperf_diff = current_aperf - cpu_info.saved_aperf;
-
-		get_C_state_time(diff_time, mperf_diff,
-				 cpu_info.max_freq,
-				 &C0_time, &CX_time,
-				 &c0_percent);
-		average = get_average_perf(cpu_info.max_freq,
-					   aperf_diff, mperf_diff);
-		cpu_info.saved_mperf = current_mperf;
-		cpu_info.saved_aperf = current_aperf;
-		print_cpu_stats(average, C0_time, CX_time, c0_percent);
-
-		if (once) {
-			printf("\n");
-			break;
-		} else {
-			printf("\r");
-			fflush(stdout);
-		}
-	}
-	return 0;
-}
-
-static int do_measure_all_cpus(int sleep_time, int once)
-{
-	int ret;
-	unsigned long average;
-	unsigned int c0_percent, cpus, cpu;
-	struct timeval start_time, current_time, diff_time, C0_time, CX_time;
-	uint64_t current_aperf, current_mperf, mperf_diff, aperf_diff;
-	struct avg_perf_cpu_info *cpu_list;
-
-	cpus = sysconf(_SC_NPROCESSORS_CONF);
-
-	cpu_list = (struct avg_perf_cpu_info*)
-		malloc(cpus * sizeof (struct avg_perf_cpu_info));
-
-	for (cpu = 0; cpu < cpus; cpu++) {
-		ret = get_measure_start_info(cpu, &cpu_list[cpu]);
-		if   (ret)
-		continue;
-	}
-
-	while(1) {
-		gettimeofday(&start_time, NULL);
-		sleep(sleep_time);
-		/* ToDo: Just add a second on the timeval struct?
-		         Would save one gettimeofday, but would not
-			 be that accurate anymore
-		*/
-		gettimeofday(&current_time, NULL);
-		timersub(&current_time, &start_time, &diff_time);
-		memcpy(&start_time, &current_time,
-		       sizeof(struct timeval));
-
-		for (cpu = 0; cpu < cpus; cpu++) {
-
-			printf("%.3u\t", cpu);
-
-			ret = get_aperf_mperf(cpu, &current_aperf,
-					      &current_mperf);
-
-			if ((ret < 0) || !cpu_list[cpu].is_valid) {
-				printf("[offline]\n");
-				continue;
-			}
-
-			mperf_diff = current_mperf - cpu_list[cpu].saved_mperf;
-			aperf_diff = current_aperf - cpu_list[cpu].saved_aperf;
-
-			get_C_state_time(diff_time, mperf_diff,
-					 cpu_list[cpu].max_freq,
-					 &C0_time, &CX_time,
-					 &c0_percent);
-			average = get_average_perf(cpu_list[cpu].max_freq,
-						   aperf_diff, mperf_diff);
-			cpu_list[cpu].saved_mperf = current_mperf;
-			cpu_list[cpu].saved_aperf = current_aperf;
-			print_cpu_stats(average, C0_time, CX_time, c0_percent);
-			printf("\n");
-		}
-		if (once)
-			break;
-		printf("\n");
-	}
-	return 0;
-}
-
-
-/******* Options parsing, main ********/
-
-static struct option long_options[] = {
-  { "help",		0, 0, 'h' },
-  { "intervall",	1, 0, 'i' },
-  { "cpu",		1, 0, 'c' },
-  { "once",		0, 0, 'o' },
-  { 0, 0, 0, 0 }
-};
-
-static void usage(void) {
-	printf("cpufreq-aperf [OPTIONS]\n\n"
-	       "-c [ --cpu ] CPU               "
-	       "The CPU core to measure - default all cores\n"
-	       "-i [ --intervall ] seconds     "
-	       "Refresh rate - default 1 second\n"
-	       "-o [ --once ]                  "
-	       "Exit after one intervall\n"
-	       "-h [ --help ]                  "
-	       "This help text\n"
-	       "The msr driver must be loaded for this command to work\n");
-}
-
-int main(int argc, char *argv[])
-{
-	int c, ret, cpu = -1;
-	int sleep_time = 1, once = 0;
-	const char *msr_path = "/dev/cpu/0/msr";
-
-	while ( (c = getopt_long(argc,argv,"c:ohi:",long_options,
-				 NULL)) != -1 ) {
-		switch ( c ) {
-		case 'o':
-			once = 1;
-			break;
-		case 'c':
-			cpu = atoi(optarg);
-			break;
-		case 'h':
-			usage();
-			exit(0);
-		case 'i':
-			sleep_time = atoi(optarg);
-			break;
-		}
-	}
-
-	if (getuid() != 0) {
-		fprintf(stderr, "You must be root\n");
-		return EXIT_FAILURE;
-	}
-
-	if (!cpu_has_effective_freq()) {
-		fprintf(stderr, "CPU doesn't support APERF/MPERF\n");
-		return EXIT_FAILURE;
-	}
-
-	ret = access(msr_path, R_OK);
-	if (ret < 0) {
-		fprintf(stderr, "Error reading %s, load/enable msr.ko\n", msr_path);
-		goto out;
-	}
-
-	printf("CPU\tAverage freq(KHz)\tTime in C0\tTime in"
-	       " Cx\tC0 percentage\n");
-
-	if (cpu == -1)
-		ret = do_measure_all_cpus(sleep_time, once);
-	else
-		ret = do_measuring_on_cpu(sleep_time, once, cpu);
-
-out:
-	return ret;
-}
-/******* Options parsing, main ********/
diff --git a/utils/cpufreq-aperf.c b/utils/cpufreq-aperf.c
new file mode 100644
index 0000000..1c64501
--- /dev/null
+++ b/utils/cpufreq-aperf.c
@@ -0,0 +1,431 @@
+/*
+ *  Copyright (C) 2009  Thomas Renninger <trenn@suse.de>, Novell Inc.
+ *
+ *  Inspired by these projects:
+ *    cpuid (by Todd Allen)
+ *    msr-tools (by H. Peter Anvin <hpa@zytor.com>)
+ *
+ *  Licensed under the terms of the GNU GPL License version 2.
+ *
+ *
+ *  What does this program do:
+ *
+ *  On latest processors exist two MSR registers refered to as:
+ *    - MPERF increasing with maxium (P0) frequency in C0
+ *    - APERF increasing with current/actual frequency in C0
+ *
+ *  From this information the average frequency over a time period can be
+ *  calculated and this is what this tool does.
+ *
+ *  A nice falloff feature beside the average frequency is the time
+ *  a processor core remained in C0 (working state) or any CX (sleep state)
+ *  processor sleep state during the measured time period. This information
+ *  can be determined from the fact that MPERF only increases in C0 state.
+ *
+ *  Note: There were kernels which reset MPERF/APERF registers to 0.
+ *        This got reverted by git commit
+ *                  18b2646fe3babeb40b34a0c1751e0bf5adfdc64c
+ *        which was commited to 2.6.30-rcX mainline kernels
+ *        For kernels where the kernel rests MPERF/APERF registers to 0,
+ *        this tool will not work. It cannot be detected whether this happened.
+ *
+ * Possible ToDos/Enhancments:
+ *
+ *  - Refresh the screen when mulitple cpus are poked and display results
+ *    on one screen
+ *    -This would introduce a lot more complexity, not sure whether it's
+ *       wanted/needed. I'd vote to better not do that.
+ *  - Manpage
+ *  - Translations
+ *  - ...
+ */
+
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <unistd.h>
+#include <getopt.h>
+#include <sys/time.h>
+#include <sys/types.h>
+#include <stdint.h>
+#include <errno.h>
+#include <fcntl.h>
+#include <string.h>
+
+#include "cpufreq.h"
+#include "cpuid.h"
+
+#define MSR_IA32_APERF 0x000000E8
+#define MSR_IA32_MPERF 0x000000E7
+
+struct avg_perf_cpu_info
+{
+	unsigned long max_freq;
+	uint64_t saved_aperf;
+	uint64_t saved_mperf;
+	uint32_t is_valid:1;
+};
+
+static int cpu_has_effective_freq()
+{
+#if defined(__i386__) || defined(__x86_64__)
+	/* largest base level */
+	if (cpuid_eax(0) < 6)
+		return 0;
+
+	return cpuid_ecx(6) & 0x1;
+#else
+	return 0;
+#endif
+}
+
+/*
+ * read_msr
+ *
+ * Will return 0 on success and -1 on failure.
+ * Possible errno values could be:
+ * EFAULT -If the read/write did not fully complete
+ * EIO    -If the CPU does not support MSRs
+ * ENXIO  -If the CPU does not exist
+ */
+
+static int read_msr(int cpu, unsigned int idx, unsigned long long *val)
+{
+	int fd;
+	char msr_file_name[64];
+
+	sprintf(msr_file_name, "/dev/cpu/%d/msr", cpu);
+	fd = open(msr_file_name, O_RDONLY);
+	if (fd < 0)
+		return -1;
+	if (lseek(fd, idx, SEEK_CUR) == -1)
+		goto err;
+	if (read(fd, val, sizeof val) != sizeof *val)
+		goto err;
+	close(fd);
+	return 0;
+ err:
+	close(fd);
+	return -1;
+}
+
+/*
+ * get_aperf_mperf()
+ *
+ * Returns the current aperf/mperf MSR values of cpu
+ */
+static int get_aperf_mperf(unsigned int cpu, uint64_t *aperf, uint64_t *mperf)
+{
+	int retval;
+
+	retval = read_msr(cpu, MSR_IA32_APERF, (unsigned long long*)aperf);
+	if (retval < 0)
+		return retval;
+
+	retval = read_msr(cpu, MSR_IA32_MPERF, (unsigned long long*)mperf);
+	if (retval < 0)
+		return retval;
+	return 0;
+}
+
+/*
+ * get_average_perf()
+ *
+ * Returns the average performance (also considers boosted frequencies)
+ * 
+ * Input:
+ *   aperf_diff: Difference of the aperf register over a time period
+ *   mperf_diff: Difference of the mperf register over the same time period
+ *   max_freq:   Maximum frequency (P0)
+ *
+ * Returns:
+ *   Average performance over the time period
+ */
+static unsigned long get_average_perf(unsigned long max_freq,
+				      uint64_t aperf_diff,
+				      uint64_t mperf_diff)
+{
+	unsigned int perf_percent = 0;
+	if (((unsigned long)(-1) / 100) < aperf_diff) {
+		int shift_count = 7;
+		aperf_diff >>= shift_count;
+		mperf_diff >>= shift_count;
+	}
+	perf_percent = (aperf_diff * 100) / mperf_diff;
+	return (max_freq * perf_percent) / 100;
+}
+
+/*
+ * get_C_state_time()
+ *
+ * Calculates the time the processor was in C0 and Cx processor sleep states
+ *
+ * As mperf does only tick in C0 at maximum frequency, this is a nice "falloff"
+ * functionality and more accurate than powertop or other kernel timer based
+ * C-state measurings (and can be used to verify whether they are correct.
+ *
+ * Input:
+ *   time_diff:  The time passed for which the mperf_diff was calulcated on
+ *   mperf_diff: The value the mperf register increased during time_diff
+ *   max_freq:   Maximum frequency of the processor (P0) in kHz
+ *
+ * Output:
+ *   C0_time:    The time the processor was in C0
+ *   CX_time:    The time the processor was in CX
+ *   percent:    Percentage the processor stayed in C0
+ */
+static int get_C_state_time(struct timeval time_diff, uint64_t mperf_diff,
+		     unsigned long max_freq,
+		     struct timeval *C0_time, struct timeval *CX_time,
+		     unsigned int *percent)
+{
+	unsigned long long overall_msecs, expected_ticks, c0_time, cx_time;
+
+	overall_msecs = (time_diff.tv_sec * 1000 * 1000  + time_diff.tv_usec)
+		/ 1000;
+
+	expected_ticks = max_freq * overall_msecs;
+	*percent = (mperf_diff * 100) / expected_ticks;
+
+	cx_time = (expected_ticks - mperf_diff) / max_freq;
+	c0_time = mperf_diff / max_freq;
+
+	CX_time->tv_sec  = cx_time / 1000;
+	CX_time->tv_usec = cx_time % 1000;
+	C0_time->tv_sec  = c0_time / 1000;
+	C0_time->tv_usec = c0_time % 1000;
+	return 0;
+}
+
+static int get_measure_start_info(unsigned int cpu,
+				  struct avg_perf_cpu_info *cpu_info)
+{
+	unsigned long min, max;
+	uint64_t aperf, mperf;
+	int ret;
+
+	cpu_info->is_valid = 0;
+
+	if (cpufreq_get_hardware_limits(cpu, &min, &max))
+		return -EINVAL;
+
+	cpu_info->max_freq = max;
+	
+	ret = get_aperf_mperf(cpu, &aperf, &mperf);
+	if (ret < 0)
+		return -EINVAL;
+
+	cpu_info->saved_aperf = aperf;
+	cpu_info->saved_mperf = mperf;
+	cpu_info->is_valid = 1;
+
+	return 0;
+}
+
+static void print_cpu_stats(unsigned long average, struct timeval c0_time,
+			    struct timeval cx_time, unsigned int c0_percent)
+{
+	printf("%.7lu\t\t\t", average);
+	printf("%.2lu sec %.3lu ms\t", c0_time.tv_sec, c0_time.tv_usec);
+	printf("%.2lu sec %.3lu ms\t", cx_time.tv_sec, cx_time.tv_usec);
+	printf("%.2u", c0_percent);
+}
+
+static int do_measuring_on_cpu(int sleep_time, int once, int cpu)
+{
+	int ret;
+	unsigned long average;
+	unsigned int c0_percent;
+	struct timeval start_time, current_time, diff_time, C0_time, CX_time;
+	uint64_t current_aperf, current_mperf, mperf_diff, aperf_diff;
+	struct avg_perf_cpu_info cpu_info;
+
+	ret = get_measure_start_info(cpu, &cpu_info);
+	if (ret)
+		return ret;
+
+	while(1) {
+		gettimeofday(&start_time, NULL);
+		sleep(sleep_time);
+		/* ToDo: just add a second on the timeval struct? */
+		gettimeofday(&current_time, NULL);
+		timersub(&current_time, &start_time, &diff_time);
+		memcpy(&start_time, &current_time,
+		       sizeof(struct timeval));
+
+		if (!cpu_info.is_valid)
+			continue;
+
+		printf("%.3u\t", cpu);
+
+		ret = get_aperf_mperf(cpu, &current_aperf, &current_mperf);
+		if (ret < 0) {
+			printf("[offline]\n");
+			continue;
+		}
+
+		mperf_diff = current_mperf - cpu_info.saved_mperf;
+		aperf_diff = current_aperf - cpu_info.saved_aperf;
+
+		get_C_state_time(diff_time, mperf_diff,
+				 cpu_info.max_freq,
+				 &C0_time, &CX_time,
+				 &c0_percent);
+		average = get_average_perf(cpu_info.max_freq,
+					   aperf_diff, mperf_diff);
+		cpu_info.saved_mperf = current_mperf;
+		cpu_info.saved_aperf = current_aperf;
+		print_cpu_stats(average, C0_time, CX_time, c0_percent);
+
+		if (once) {
+			printf("\n");
+			break;
+		} else {
+			printf("\r");
+			fflush(stdout);
+		}
+	}
+	return 0;
+}
+
+static int do_measure_all_cpus(int sleep_time, int once)
+{
+	int ret;
+	unsigned long average;
+	unsigned int c0_percent, cpus, cpu;
+	struct timeval start_time, current_time, diff_time, C0_time, CX_time;
+	uint64_t current_aperf, current_mperf, mperf_diff, aperf_diff;
+	struct avg_perf_cpu_info *cpu_list;
+
+	cpus = sysconf(_SC_NPROCESSORS_CONF);
+
+	cpu_list = (struct avg_perf_cpu_info*)
+		malloc(cpus * sizeof (struct avg_perf_cpu_info));
+
+	for (cpu = 0; cpu < cpus; cpu++) {
+		ret = get_measure_start_info(cpu, &cpu_list[cpu]);
+		if   (ret)
+		continue;
+	}
+
+	while(1) {
+		gettimeofday(&start_time, NULL);
+		sleep(sleep_time);
+		/* ToDo: Just add a second on the timeval struct?
+		         Would save one gettimeofday, but would not
+			 be that accurate anymore
+		*/
+		gettimeofday(&current_time, NULL);
+		timersub(&current_time, &start_time, &diff_time);
+		memcpy(&start_time, &current_time,
+		       sizeof(struct timeval));
+
+		for (cpu = 0; cpu < cpus; cpu++) {
+
+			printf("%.3u\t", cpu);
+
+			ret = get_aperf_mperf(cpu, &current_aperf,
+					      &current_mperf);
+
+			if ((ret < 0) || !cpu_list[cpu].is_valid) {
+				printf("[offline]\n");
+				continue;
+			}
+
+			mperf_diff = current_mperf - cpu_list[cpu].saved_mperf;
+			aperf_diff = current_aperf - cpu_list[cpu].saved_aperf;
+
+			get_C_state_time(diff_time, mperf_diff,
+					 cpu_list[cpu].max_freq,
+					 &C0_time, &CX_time,
+					 &c0_percent);
+			average = get_average_perf(cpu_list[cpu].max_freq,
+						   aperf_diff, mperf_diff);
+			cpu_list[cpu].saved_mperf = current_mperf;
+			cpu_list[cpu].saved_aperf = current_aperf;
+			print_cpu_stats(average, C0_time, CX_time, c0_percent);
+			printf("\n");
+		}
+		if (once)
+			break;
+		printf("\n");
+	}
+	return 0;
+}
+
+
+/******* Options parsing, main ********/
+
+static struct option long_options[] = {
+  { "help",		0, 0, 'h' },
+  { "intervall",	1, 0, 'i' },
+  { "cpu",		1, 0, 'c' },
+  { "once",		0, 0, 'o' },
+  { 0, 0, 0, 0 }
+};
+
+static void usage(void) {
+	printf("cpufreq-aperf [OPTIONS]\n\n"
+	       "-c [ --cpu ] CPU               "
+	       "The CPU core to measure - default all cores\n"
+	       "-i [ --intervall ] seconds     "
+	       "Refresh rate - default 1 second\n"
+	       "-o [ --once ]                  "
+	       "Exit after one intervall\n"
+	       "-h [ --help ]                  "
+	       "This help text\n"
+	       "The msr driver must be loaded for this command to work\n");
+}
+
+int main(int argc, char *argv[])
+{
+	int c, ret, cpu = -1;
+	int sleep_time = 1, once = 0;
+	const char *msr_path = "/dev/cpu/0/msr";
+
+	while ( (c = getopt_long(argc,argv,"c:ohi:",long_options,
+				 NULL)) != -1 ) {
+		switch ( c ) {
+		case 'o':
+			once = 1;
+			break;
+		case 'c':
+			cpu = atoi(optarg);
+			break;
+		case 'h':
+			usage();
+			exit(0);
+		case 'i':
+			sleep_time = atoi(optarg);
+			break;
+		}
+	}
+
+	if (getuid() != 0) {
+		fprintf(stderr, "You must be root\n");
+		return EXIT_FAILURE;
+	}
+
+	if (!cpu_has_effective_freq()) {
+		fprintf(stderr, "CPU doesn't support APERF/MPERF\n");
+		return EXIT_FAILURE;
+	}
+
+	ret = access(msr_path, R_OK);
+	if (ret < 0) {
+		fprintf(stderr, "Error reading %s, load/enable msr.ko\n", msr_path);
+		goto out;
+	}
+
+	printf("CPU\tAverage freq(KHz)\tTime in C0\tTime in"
+	       " Cx\tC0 percentage\n");
+
+	if (cpu == -1)
+		ret = do_measure_all_cpus(sleep_time, once);
+	else
+		ret = do_measuring_on_cpu(sleep_time, once, cpu);
+
+out:
+	return ret;
+}
+/******* Options parsing, main ********/
diff --git a/utils/cpufreq-info.c b/utils/cpufreq-info.c
new file mode 100644
index 0000000..38d906a
--- /dev/null
+++ b/utils/cpufreq-info.c
@@ -0,0 +1,629 @@
+/*
+ *  (C) 2004-2009  Dominik Brodowski <linux@dominikbrodowski.de>
+ *
+ *  Licensed under the terms of the GNU GPL License version 2.
+ */
+
+
+#include <unistd.h>
+#include <stdio.h>
+#include <errno.h>
+#include <stdlib.h>
+#include <string.h>
+#include <libintl.h>
+#include <locale.h>
+
+#include <getopt.h>
+
+#include "cpufreq.h"
+
+
+#define _(String) gettext (String)
+#define gettext_noop(String) String
+#define N_(String) gettext_noop (String)
+
+#define LINE_LEN 10
+
+static unsigned int count_cpus(void)
+{
+	FILE *fp;
+	char value[LINE_LEN];
+	unsigned int ret = 0;
+	unsigned int cpunr = 0;
+
+	fp = fopen("/proc/stat", "r");
+	if(!fp) {
+		printf(gettext("Couldn't count the number of CPUs (%s: %s), assuming 1\n"), "/proc/stat", strerror(errno));
+		return 1;
+	}
+
+	while (!feof(fp)) {
+		if (!fgets(value, LINE_LEN, fp))
+			continue;
+		value[LINE_LEN - 1] = '\0';
+		if (strlen(value) < (LINE_LEN - 2))
+			continue;
+		if (strstr(value, "cpu "))
+			continue;
+		if (sscanf(value, "cpu%d ", &cpunr) != 1)
+			continue;
+		if (cpunr > ret)
+			ret = cpunr;
+	}
+	fclose(fp);
+
+	/* cpu count starts from 0, on error return 1 (UP) */
+	return (ret+1);
+}
+
+
+static void proc_cpufreq_output(void)
+{
+	unsigned int cpu, nr_cpus;
+	struct cpufreq_policy *policy;
+	unsigned int min_pctg = 0;
+	unsigned int max_pctg = 0;
+	unsigned long min, max;
+
+	printf(gettext("          minimum CPU frequency  -  maximum CPU frequency  -  governor\n"));
+
+	nr_cpus = count_cpus();
+	for (cpu=0; cpu < nr_cpus; cpu++) {
+		policy = cpufreq_get_policy(cpu);
+		if (!policy)
+			continue;
+
+		if (cpufreq_get_hardware_limits(cpu, &min, &max)) {
+			max = 0;
+		} else {
+			min_pctg = (policy->min * 100) / max;
+			max_pctg = (policy->max * 100) / max;
+		}
+		printf("CPU%3d    %9lu kHz (%3d %%)  -  %9lu kHz (%3d %%)  -  %s\n",
+		       cpu , policy->min, max ? min_pctg : 0, policy->max, max ? max_pctg : 0, policy->governor);
+
+		cpufreq_put_policy(policy);
+	}
+}
+
+static void print_speed(unsigned long speed)
+{
+	unsigned long tmp;
+
+	if (speed > 1000000) {
+		tmp = speed % 10000;
+		if (tmp >= 5000)
+			speed += 10000;
+		printf ("%u.%02u GHz", ((unsigned int) speed/1000000),
+			((unsigned int) (speed%1000000)/10000));
+	} else if (speed > 100000) {
+		tmp = speed % 1000;
+		if (tmp >= 500)
+			speed += 1000;
+		printf ("%u MHz", ((unsigned int) speed / 1000));
+	} else if (speed > 1000) {
+		tmp = speed % 100;
+		if (tmp >= 50)
+			speed += 100;
+		printf ("%u.%01u MHz", ((unsigned int) speed/1000),
+			((unsigned int) (speed%1000)/100));
+	} else
+		printf ("%lu kHz", speed);
+
+	return;
+}
+
+static void print_duration(unsigned long duration)
+{
+	unsigned long tmp;
+
+	if (duration > 1000000) {
+		tmp = duration % 10000;
+		if (tmp >= 5000)
+			duration += 10000;
+		printf ("%u.%02u ms", ((unsigned int) duration/1000000),
+			((unsigned int) (duration%1000000)/10000));
+	} else if (duration > 100000) {
+		tmp = duration % 1000;
+		if (tmp >= 500)
+			duration += 1000;
+		printf ("%u us", ((unsigned int) duration / 1000));
+	} else if (duration > 1000) {
+		tmp = duration % 100;
+		if (tmp >= 50)
+			duration += 100;
+		printf ("%u.%01u us", ((unsigned int) duration/1000),
+			((unsigned int) (duration%1000)/100));
+	} else
+		printf ("%lu ns", duration);
+
+	return;
+}
+
+static void debug_output_one(unsigned int cpu)
+{
+	char *driver;
+	struct cpufreq_affected_cpus *cpus;
+	struct cpufreq_available_frequencies *freqs;
+	unsigned long min, max, freq_kernel, freq_hardware;
+	unsigned long total_trans, latency;
+	unsigned long long total_time;
+	struct cpufreq_policy *policy;
+	struct cpufreq_available_governors * governors;
+	struct cpufreq_stats *stats;
+
+	if (cpufreq_cpu_exists(cpu)) {
+		printf(gettext ("couldn't analyze CPU %d as it doesn't seem to be present\n"), cpu);
+		return;
+	}
+
+	printf(gettext ("analyzing CPU %d:\n"), cpu);
+
+	freq_kernel = cpufreq_get_freq_kernel(cpu);
+	freq_hardware = cpufreq_get_freq_hardware(cpu);
+
+	driver = cpufreq_get_driver(cpu);
+	if (!driver) {
+		printf(gettext ("  no or unknown cpufreq driver is active on this CPU\n"));
+	} else {
+		printf(gettext ("  driver: %s\n"), driver);
+		cpufreq_put_driver(driver);
+	}
+
+	cpus = cpufreq_get_related_cpus(cpu);
+	if (cpus) {
+		printf(gettext ("  CPUs which run at the same hardware frequency: "));
+		while (cpus->next) {
+			printf("%d ", cpus->cpu);
+			cpus = cpus->next;
+		}
+		printf("%d\n", cpus->cpu);
+		cpufreq_put_related_cpus(cpus);
+	}
+
+	cpus = cpufreq_get_affected_cpus(cpu);
+	if (cpus) {
+		printf(gettext ("  CPUs which need to have their frequency coordinated by software: "));
+		while (cpus->next) {
+			printf("%d ", cpus->cpu);
+			cpus = cpus->next;
+		}
+		printf("%d\n", cpus->cpu);
+		cpufreq_put_affected_cpus(cpus);
+	}
+
+	latency = cpufreq_get_transition_latency(cpu);
+	if (latency) {
+		printf(gettext ("  maximum transition latency: "));
+		print_duration(latency);
+		printf(".\n");
+	}
+
+	if (!(cpufreq_get_hardware_limits(cpu, &min, &max))) {
+		printf(gettext ("  hardware limits: "));
+		print_speed(min);
+		printf(" - ");
+		print_speed(max);
+		printf("\n");
+	}
+
+	freqs = cpufreq_get_available_frequencies(cpu);
+	if (freqs) {
+		printf(gettext ("  available frequency steps: "));
+		while (freqs->next) {
+			print_speed(freqs->frequency);
+			printf(", ");
+			freqs = freqs->next;
+		}
+		print_speed(freqs->frequency);
+		printf("\n");
+		cpufreq_put_available_frequencies(freqs);
+	}
+
+	governors = cpufreq_get_available_governors(cpu);
+	if (governors) {
+		printf(gettext ("  available cpufreq governors: "));
+		while (governors->next) {
+			printf("%s, ", governors->governor);
+			governors = governors->next;
+		}
+		printf("%s\n", governors->governor);
+		cpufreq_put_available_governors(governors);
+	}
+
+	policy = cpufreq_get_policy(cpu);
+	if (policy) {
+		printf(gettext ("  current policy: frequency should be within "));
+		print_speed(policy->min);
+		printf(gettext (" and "));
+		print_speed(policy->max);
+
+		printf(".\n                  ");
+		printf(gettext ("The governor \"%s\" may"
+		       " decide which speed to use\n                  within this range.\n"),
+		       policy->governor);
+		cpufreq_put_policy(policy);
+	}
+
+	if (freq_kernel || freq_hardware) {
+		printf(gettext ("  current CPU frequency is "));
+		if (freq_hardware) {
+			print_speed(freq_hardware);
+			printf(gettext (" (asserted by call to hardware)"));
+		}
+		else
+			print_speed(freq_kernel);
+		printf(".\n");
+	}
+	stats = cpufreq_get_stats(cpu, &total_time);
+	if (stats) {
+		printf(gettext ("  cpufreq stats: "));
+		while (stats) {
+			print_speed(stats->frequency);
+			printf(":%.2f%%", (100.0 * stats->time_in_state) / total_time);
+			stats = stats->next;
+			if (stats)
+				printf(", ");
+		}
+		cpufreq_put_stats(stats);
+		total_trans = cpufreq_get_transitions(cpu);
+		if (total_trans)
+			printf("  (%lu)\n", total_trans);
+		else
+			printf("\n");
+	}
+}
+
+static void debug_output(unsigned int cpu, unsigned int all) {
+	if (all) {
+		unsigned int nr_cpus = count_cpus();
+		for (cpu=0; cpu < nr_cpus; cpu++) {
+			if (cpufreq_cpu_exists(cpu))
+				continue;
+			debug_output_one(cpu);
+		}
+	} else
+		debug_output_one(cpu);
+}
+
+
+/* --freq / -f */
+
+static int get_freq_kernel(unsigned int cpu, unsigned int human) {
+	unsigned long freq = cpufreq_get_freq_kernel(cpu);
+	if (!freq)
+		return -EINVAL;
+	if (human) {
+		print_speed(freq);
+		printf("\n");
+	} else
+		printf("%lu\n", freq);
+	return 0;
+}
+
+
+/* --hwfreq / -w */
+
+static int get_freq_hardware(unsigned int cpu, unsigned int human) {
+	unsigned long freq = cpufreq_get_freq_hardware(cpu);
+	if (!freq)
+		return -EINVAL;
+	if (human) {
+		print_speed(freq);
+		printf("\n");
+	} else
+		printf("%lu\n", freq);
+	return 0;
+}
+
+/* --hwlimits / -l */
+
+static int get_hardware_limits(unsigned int cpu) {
+	unsigned long min, max;
+	if (cpufreq_get_hardware_limits(cpu, &min, &max))
+		return -EINVAL;
+	printf("%lu %lu\n", min, max);
+	return 0;
+}
+
+/* --driver / -d */
+
+static int get_driver(unsigned int cpu) {
+	char *driver = cpufreq_get_driver(cpu);
+	if (!driver)
+		return -EINVAL;
+	printf("%s\n", driver);
+	cpufreq_put_driver(driver);
+	return 0;
+}
+
+/* --policy / -p */
+
+static int get_policy(unsigned int cpu) {
+	struct cpufreq_policy *policy = cpufreq_get_policy(cpu);
+	if (!policy)
+		return -EINVAL;
+	printf("%lu %lu %s\n", policy->min, policy->max, policy->governor);
+	cpufreq_put_policy(policy);
+	return 0;
+}
+
+/* --governors / -g */
+
+static int get_available_governors(unsigned int cpu) {
+	struct cpufreq_available_governors *governors = cpufreq_get_available_governors(cpu);
+	if (!governors)
+		return -EINVAL;
+
+	while (governors->next) {
+		printf("%s ", governors->governor);
+		governors = governors->next;
+	}
+	printf("%s\n", governors->governor);
+	cpufreq_put_available_governors(governors);
+	return 0;
+}
+
+
+/* --affected-cpus  / -a */
+
+static int get_affected_cpus(unsigned int cpu) {
+	struct cpufreq_affected_cpus *cpus = cpufreq_get_affected_cpus(cpu);
+	if (!cpus)
+		return -EINVAL;
+
+	while (cpus->next) {
+		printf("%d ", cpus->cpu);
+		cpus = cpus->next;
+	}
+	printf("%d\n", cpus->cpu);
+	cpufreq_put_affected_cpus(cpus);
+	return 0;
+}
+
+/* --related-cpus  / -r */
+
+static int get_related_cpus(unsigned int cpu) {
+	struct cpufreq_affected_cpus *cpus = cpufreq_get_related_cpus(cpu);
+	if (!cpus)
+		return -EINVAL;
+
+	while (cpus->next) {
+		printf("%d ", cpus->cpu);
+		cpus = cpus->next;
+	}
+	printf("%d\n", cpus->cpu);
+	cpufreq_put_related_cpus(cpus);
+	return 0;
+}
+
+/* --stats / -s */
+
+static int get_freq_stats(unsigned int cpu, unsigned int human) {
+	unsigned long total_trans = cpufreq_get_transitions(cpu);
+	unsigned long long total_time;
+	struct cpufreq_stats *stats = cpufreq_get_stats(cpu, &total_time);
+	while (stats) {
+		if (human) {
+			print_speed(stats->frequency);
+			printf(":%.2f%%", (100.0 * stats->time_in_state) / total_time);
+		}
+		else
+			printf("%lu:%llu", stats->frequency, stats->time_in_state);
+		stats = stats->next;
+		if (stats)
+			printf(", ");
+	}
+	cpufreq_put_stats(stats);
+	if (total_trans)
+		printf("  (%lu)\n", total_trans);
+	return 0;
+}
+
+/* --latency / -y */
+
+static int get_latency(unsigned int cpu, unsigned int human) {
+	unsigned long latency = cpufreq_get_transition_latency(cpu);
+	if (!latency)
+		return -EINVAL;
+
+	if (human) {
+		print_duration(latency);
+		printf("\n");
+	} else
+		printf("%lu\n", latency);
+	return 0;
+}
+
+static void print_header(void) {
+	printf(PACKAGE " " VERSION ": cpufreq-info (C) Dominik Brodowski 2004-2009\n");
+	printf(gettext ("Report errors and bugs to %s, please.\n"), PACKAGE_BUGREPORT);
+}
+
+static void print_help(void) {
+	printf(gettext ("Usage: cpufreq-info [options]\n"));
+	printf(gettext ("Options:\n"));
+	printf(gettext ("  -c CPU, --cpu CPU    CPU number which information shall be determined about\n"));
+	printf(gettext ("  -e, --debug          Prints out debug information\n"));
+	printf(gettext ("  -f, --freq           Get frequency the CPU currently runs at, according\n"
+	       "                       to the cpufreq core *\n"));
+	printf(gettext ("  -w, --hwfreq         Get frequency the CPU currently runs at, by reading\n"
+	       "                       it from hardware (only available to root) *\n"));
+	printf(gettext ("  -l, --hwlimits       Determine the minimum and maximum CPU frequency allowed *\n"));
+	printf(gettext ("  -d, --driver         Determines the used cpufreq kernel driver *\n"));
+	printf(gettext ("  -p, --policy         Gets the currently used cpufreq policy *\n"));
+	printf(gettext ("  -g, --governors      Determines available cpufreq governors *\n"));
+	printf(gettext ("  -r, --related-cpus   Determines which CPUs run at the same hardware frequency *\n"));
+	printf(gettext ("  -a, --affected-cpus  Determines which CPUs need to have their frequency\n"
+			"                       coordinated by software *\n"));
+	printf(gettext ("  -s, --stats          Shows cpufreq statistics if available\n"));
+	printf(gettext ("  -y, --latency        Determines the maximum latency on CPU frequency changes *\n"));
+	printf(gettext ("  -o, --proc           Prints out information like provided by the /proc/cpufreq\n"
+	       "                       interface in 2.4. and early 2.6. kernels\n"));
+	printf(gettext ("  -m, --human          human-readable output for the -f, -w, -s and -y parameters\n"));
+	printf(gettext ("  -h, --help           Prints out this screen\n"));
+
+	printf("\n");
+	printf(gettext ("If no argument or only the -c, --cpu parameter is given, debug output about\n"
+	       "cpufreq is printed which is useful e.g. for reporting bugs.\n"));
+	printf(gettext ("For the arguments marked with *, omitting the -c or --cpu argument is\n"
+	"equivalent to setting it to zero\n"));
+}
+
+static struct option info_opts[] = {
+	{ .name="cpu",		.has_arg=required_argument,	.flag=NULL,	.val='c'},
+	{ .name="debug",	.has_arg=no_argument,		.flag=NULL,	.val='e'},
+	{ .name="freq",		.has_arg=no_argument,		.flag=NULL,	.val='f'},
+	{ .name="hwfreq",	.has_arg=no_argument,		.flag=NULL,	.val='w'},
+	{ .name="hwlimits",	.has_arg=no_argument,		.flag=NULL,	.val='l'},
+	{ .name="driver",	.has_arg=no_argument,		.flag=NULL,	.val='d'},
+	{ .name="policy",	.has_arg=no_argument,		.flag=NULL,	.val='p'},
+	{ .name="governors",	.has_arg=no_argument,		.flag=NULL,	.val='g'},
+	{ .name="related-cpus", .has_arg=no_argument,		.flag=NULL,	.val='r'},
+	{ .name="affected-cpus",.has_arg=no_argument,		.flag=NULL,	.val='a'},
+	{ .name="stats",	.has_arg=no_argument,		.flag=NULL,	.val='s'},
+	{ .name="latency",	.has_arg=no_argument,		.flag=NULL,	.val='y'},
+	{ .name="proc",		.has_arg=no_argument,		.flag=NULL,	.val='o'},
+	{ .name="human",	.has_arg=no_argument,		.flag=NULL,	.val='m'},
+	{ .name="help",		.has_arg=no_argument,		.flag=NULL,	.val='h'},
+};
+
+int main(int argc, char **argv) {
+	extern char *optarg;
+	extern int optind, opterr, optopt;
+	int ret = 0, cont = 1;
+	unsigned int cpu = 0;
+	unsigned int cpu_defined = 0;
+	unsigned int human = 0;
+	int output_param = 0;
+
+	setlocale(LC_ALL, "");
+	textdomain (PACKAGE);
+
+	do {
+		ret = getopt_long(argc, argv, "c:hoefwldpgrasmy", info_opts, NULL);
+		switch (ret) {
+		case '?':
+			output_param = '?';
+			cont = 0;
+			break;
+		case 'h':
+			output_param = 'h';
+			cont = 0;
+			break;
+		case -1:
+			cont = 0;
+			break;
+		case 'o':
+		case 'a':
+		case 'r':
+		case 'g':
+		case 'p':
+		case 'd':
+		case 'l':
+		case 'w':
+		case 'f':
+		case 'e':
+		case 's':
+		case 'y':
+			if (output_param) {
+				output_param = -1;
+				cont = 0;
+				break;
+			}
+			output_param = ret;
+			break;
+		case 'c':
+			if (cpu_defined) {
+				output_param = -1;
+				cont = 0;
+				break;
+			}
+			if ((sscanf(optarg, "%d ", &cpu)) != 1) {
+				output_param = '?';
+				cont = 0;
+			}
+			cpu_defined = 1;
+			break;
+		case 'm':
+			if (human) {
+				output_param = -1;
+				cont = 0;
+				break;
+			}
+			human = 1;
+			break;
+		}
+	} while(cont);
+
+	switch (output_param) {
+	case 'o':
+		if (cpu_defined) {
+			print_header();
+			printf(gettext ("The argument passed to this tool can't be combined with passing a --cpu argument\n"));
+			return -EINVAL;
+		}
+		break;
+	case 0:
+		output_param = 'e';
+	}
+
+	ret = 0;
+
+	switch (output_param) {
+	case -1:
+		print_header();
+		printf(gettext ("You can't specify more than one --cpu parameter and/or\n"
+		       "more than one output-specific argument\n"));
+		return -EINVAL;
+		break;
+	case '?':
+		print_header();
+		printf(gettext ("invalid or unknown argument\n"));
+		print_help();
+		ret = -EINVAL;
+		break;
+	case 'h':
+		print_header();
+		print_help();
+		break;
+	case 'o':
+		proc_cpufreq_output();
+		break;
+	case 'e':
+		print_header();
+		debug_output(cpu, !(cpu_defined));
+		break;
+	case 'a':
+		ret = get_affected_cpus(cpu);
+		break;
+	case 'r':
+		ret = get_related_cpus(cpu);
+		break;
+	case 'g':
+		ret = get_available_governors(cpu);
+		break;
+	case 'p':
+		ret = get_policy(cpu);
+		break;
+	case 'd':
+		ret = get_driver(cpu);
+		break;
+	case 'l':
+		ret = get_hardware_limits(cpu);
+		break;
+	case 'w':
+		ret = get_freq_hardware(cpu, human);
+		break;
+	case 'f':
+		ret = get_freq_kernel(cpu, human);
+		break;
+	case 's':
+		ret = get_freq_stats(cpu, human);
+		break;
+	case 'y':
+		ret = get_latency(cpu, human);
+		break;
+	}
+	return (ret);
+}
diff --git a/utils/cpufreq-set.c b/utils/cpufreq-set.c
new file mode 100644
index 0000000..2ece47e
--- /dev/null
+++ b/utils/cpufreq-set.c
@@ -0,0 +1,375 @@
+/*
+ *  (C) 2004-2009  Dominik Brodowski <linux@dominikbrodowski.de>
+ *
+ *  Licensed under the terms of the GNU GPL License version 2.
+ */
+
+
+#include <unistd.h>
+#include <stdio.h>
+#include <errno.h>
+#include <stdlib.h>
+#include <limits.h>
+#include <string.h>
+#include <ctype.h>
+#include <libintl.h>
+#include <locale.h>
+
+#include <getopt.h>
+
+#include "cpufreq.h"
+
+#define _(String) gettext(String)
+#define gettext_noop(String) String
+#define N_(String) gettext_noop(String)
+
+#define NORM_FREQ_LEN 32
+
+static void print_header(void)
+{
+        printf(PACKAGE " " VERSION ": cpufreq-set (C) Dominik Brodowski 2004-2009\n");
+	printf(gettext("Report errors and bugs to %s, please.\n"), PACKAGE_BUGREPORT);
+}
+
+static void print_help(void)
+{
+	printf(gettext("Usage: cpufreq-set [options]\n"));
+	printf(gettext("Options:\n"));
+	printf(gettext("  -c CPU, --cpu CPU        number of CPU where cpufreq settings shall be modified\n"));
+	printf(gettext("  -d FREQ, --min FREQ      new minimum CPU frequency the governor may select\n"));
+	printf(gettext("  -u FREQ, --max FREQ      new maximum CPU frequency the governor may select\n"));
+	printf(gettext("  -g GOV, --governor GOV   new cpufreq governor\n"));
+	printf(gettext("  -f FREQ, --freq FREQ     specific frequency to be set. Requires userspace\n"
+	       "                           governor to be available and loaded\n"));
+	printf(gettext("  -r, --related            Switches all hardware-related CPUs\n"));
+	printf(gettext("  -h, --help               Prints out this screen\n"));
+	printf("\n");
+	printf(gettext("Notes:\n"
+	       "1. Omitting the -c or --cpu argument is equivalent to setting it to zero\n"
+	       "2. The -f FREQ, --freq FREQ parameter cannot be combined with any other parameter\n"
+	       "   except the -c CPU, --cpu CPU parameter\n"
+	       "3. FREQuencies can be passed in Hz, kHz (default), MHz, GHz, or THz\n"
+	       "   by postfixing the value with the wanted unit name, without any space\n"
+	       "   (FREQuency in kHz =^ Hz * 0.001 =^ MHz * 1000 =^ GHz * 1000000).\n"));
+
+}
+
+static struct option set_opts[] = {
+	{ .name="cpu",		.has_arg=required_argument,	.flag=NULL,	.val='c'},
+	{ .name="min",		.has_arg=required_argument,	.flag=NULL,	.val='d'},
+	{ .name="max",		.has_arg=required_argument,	.flag=NULL,	.val='u'},
+	{ .name="governor",	.has_arg=required_argument,	.flag=NULL,	.val='g'},
+	{ .name="freq",		.has_arg=required_argument,	.flag=NULL,	.val='f'},
+	{ .name="help",		.has_arg=no_argument,		.flag=NULL,	.val='h'},
+	{ .name="related",	.has_arg=no_argument,		.flag=NULL,	.val='r'},
+};
+
+static void print_error(void)
+{
+	printf(gettext("Error setting new values. Common errors:\n"
+			"- Do you have proper administration rights? (super-user?)\n"
+			"- Is the governor you requested available and modprobed?\n"
+			"- Trying to set an invalid policy?\n"
+			"- Trying to set a specific frequency, but userspace governor is not available,\n"
+			"   for example because of hardware which cannot be set to a specific frequency\n"
+			"   or because the userspace governor isn't loaded?\n"));
+};
+
+struct freq_units {
+	char*		str_unit;
+	int		power_of_ten;
+};
+
+const struct freq_units def_units[] = {
+	{"hz", -3},
+	{"khz", 0}, /* default */
+	{"mhz", 3},
+	{"ghz", 6},
+	{"thz", 9},
+	{NULL, 0}
+};
+
+static void print_unknown_arg(void)
+{
+	print_header();
+	printf(gettext("invalid or unknown argument\n"));
+	print_help();
+}
+
+static unsigned long string_to_frequency(const char *str)
+{
+	char normalized[NORM_FREQ_LEN];
+	const struct freq_units *unit;
+	const char *scan;
+	char *end;
+	unsigned long freq;
+	int power = 0, match_count = 0, i, cp, pad;
+
+	while (*str == '0')
+		str++;
+
+	for (scan = str; isdigit(*scan) || *scan == '.'; scan++) {
+		if (*scan == '.' && match_count == 0)
+			match_count = 1;
+		else if (*scan == '.' && match_count == 1)
+			return 0;
+	}
+
+	if (*scan) {
+		match_count = 0;
+		for (unit = def_units; unit->str_unit; unit++) {
+			for (i = 0;
+			     scan[i] && tolower(scan[i]) == unit->str_unit[i];
+			     ++i)
+				continue;
+			if (scan[i])
+				continue;
+			match_count++;
+			power = unit->power_of_ten;
+		}
+		if (match_count != 1)
+			return 0;
+	}
+
+	/* count the number of digits to be copied */
+	for (cp = 0; isdigit(str[cp]); cp++)
+		continue;
+
+	if (str[cp] == '.') {
+		while (power > -1 && isdigit(str[cp+1]))
+			cp++, power--;
+	}
+	if (power >= -1)	/* not enough => pad */
+		pad = power + 1;
+	else			/* to much => strip */
+		pad = 0, cp += power + 1;
+	/* check bounds */
+	if (cp <= 0 || cp + pad > NORM_FREQ_LEN - 1)
+		return 0;
+
+	/* copy digits */
+	for (i = 0; i < cp; i++, str++) {
+		if (*str == '.')
+			str++;
+		normalized[i] = *str;
+	}
+	/* and pad */
+	for (; i < cp + pad; i++)
+		normalized[i] = '0';
+
+	/* round up, down ? */
+	match_count = (normalized[i-1] >= '5');
+	/* and drop the decimal part */
+	normalized[i-1] = 0; /* cp > 0 && pad >= 0 ==> i > 0 */
+
+	/* final conversion (and applying rounding) */
+	errno = 0;
+	freq = strtoul(normalized, &end, 10);
+	if (errno)
+		return 0;
+	else {
+		if (match_count && freq != ULONG_MAX)
+			freq++;
+		return freq;
+	}
+}
+
+static int do_new_policy(unsigned int cpu, struct cpufreq_policy *new_pol)
+{
+	struct cpufreq_policy *cur_pol = cpufreq_get_policy(cpu);
+	int ret;
+
+	if (!cur_pol) {
+		printf(gettext("wrong, unknown or unhandled CPU?\n"));
+		return -EINVAL;
+	}
+
+	if (!new_pol->min)
+		new_pol->min = cur_pol->min;
+
+	if (!new_pol->max)
+		new_pol->max = cur_pol->max;
+
+	if (!new_pol->governor)
+		new_pol->governor = cur_pol->governor;
+
+	ret = cpufreq_set_policy(cpu, new_pol);
+
+	cpufreq_put_policy(cur_pol);
+
+	return ret;
+}
+
+	
+static int do_one_cpu(unsigned int cpu, struct cpufreq_policy *new_pol,
+		unsigned long freq, unsigned int pc)
+{
+	switch (pc) {
+	case 0:
+		return cpufreq_set_frequency(cpu, freq);
+
+	case 1:
+		/* if only one value of a policy is to be changed, we can
+		 * use a "fast path".
+		 */
+		if (new_pol->min)
+			return cpufreq_modify_policy_min(cpu, new_pol->min);
+		else if (new_pol->max)
+			return cpufreq_modify_policy_max(cpu, new_pol->max);
+		else if (new_pol->governor)
+			return cpufreq_modify_policy_governor(cpu, new_pol->governor);
+
+	default:
+		/* slow path */
+		return do_new_policy(cpu, new_pol);
+	}
+}
+
+
+int main(int argc, char **argv)
+{
+	extern char *optarg;
+	extern int optind, opterr, optopt;
+	int ret = 0, cont = 1;
+	unsigned long freq = 0;
+	char gov[20];
+	int double_parm = 0;
+	int related = 0;
+	int policychange = 0;
+	struct cpufreq_policy new_pol = {
+		.min = 0,
+		.max = 0,
+		.governor = NULL,
+	};
+	struct cpufreq_affected_cpus single_cpu = {
+		.cpu = 0,
+		.next = NULL,
+		.first = &single_cpu,
+	};
+	struct cpufreq_affected_cpus *cpus = NULL;
+
+	setlocale(LC_ALL, "");
+	textdomain (PACKAGE);
+
+	/* parameter parsing */
+	do {
+		ret = getopt_long(argc, argv, "c:d:u:g:f:hr", set_opts, NULL);
+		switch (ret) {
+		case '?':
+			print_unknown_arg();
+			return -EINVAL;
+		case 'h':
+			print_header();
+			print_help();
+			return 0;
+		case -1:
+			cont = 0;
+			break;
+		case 'r':
+			if (related)
+				double_parm++;
+			related++;
+			break;
+		case 'c':
+			if (cpus)
+				double_parm++;
+			cpus = &single_cpu;
+			if ((sscanf(optarg, "%d ", &single_cpu.cpu)) != 1) {
+				print_unknown_arg();
+				return -EINVAL;
+                        }
+			break;
+		case 'd':
+			if (new_pol.min)
+				double_parm++;
+			policychange++;
+			new_pol.min = string_to_frequency(optarg);
+			if (new_pol.min == 0) {
+				print_unknown_arg();
+				return -EINVAL;
+			}
+			break;
+		case 'u':
+			if (new_pol.max)
+				double_parm++;
+			policychange++;
+			new_pol.max = string_to_frequency(optarg);
+			if (new_pol.max == 0) {
+				print_unknown_arg();
+				return -EINVAL;
+			}
+			break;
+		case 'f':
+			if (freq)
+				double_parm++;
+			freq = string_to_frequency(optarg);
+			if (freq == 0) {
+				print_unknown_arg();
+				return -EINVAL;
+			}
+			break;
+		case 'g':
+			if (new_pol.governor)
+				double_parm++;
+			policychange++;
+			if ((strlen(optarg) < 3) || (strlen(optarg) > 18)) {
+				print_unknown_arg();
+				return -EINVAL;
+                        }
+			if ((sscanf(optarg, "%s", gov)) != 1) {
+				print_unknown_arg();
+				return -EINVAL;
+                        }
+			new_pol.governor = gov;
+			break;
+		}
+	} while(cont);
+
+	/* parameter checking */
+	if (double_parm) {
+		print_header();
+		printf("the same parameter was passed more than once\n");
+		return -EINVAL;
+	}
+
+	if (freq && policychange) {
+		printf(gettext("the -f/--freq parameter cannot be combined with -d/--min, -u/--max or\n"
+				"-g/--governor parameters\n"));
+		return -EINVAL;
+	}
+
+	if (!freq && !policychange) {
+		printf(gettext("At least one parameter out of -f/--freq, -d/--min, -u/--max, and\n"
+				"-g/--governor must be passed\n"));
+		return -EINVAL;
+	}
+
+
+	/* which CPUs shall we modify? */
+	if (!cpus)
+		cpus = &single_cpu;
+
+	if (related)
+		cpus = cpufreq_get_related_cpus(cpus->cpu);
+
+	/* loop over CPUs */
+	while (1) {
+		ret = do_one_cpu(cpus->cpu, &new_pol, freq, policychange);
+		if (ret)
+			break;
+
+		if (!cpus->next)
+			break;
+
+		cpus = cpus->next;
+	}
+
+	/* cleanup */
+	if (cpus->first != &single_cpu)
+		cpufreq_put_related_cpus(cpus->first);
+
+	if (ret)
+		print_error();
+
+	return ret;
+}
diff --git a/utils/info.c b/utils/info.c
deleted file mode 100644
index 38d906a..0000000
--- a/utils/info.c
+++ /dev/null
@@ -1,629 +0,0 @@
-/*
- *  (C) 2004-2009  Dominik Brodowski <linux@dominikbrodowski.de>
- *
- *  Licensed under the terms of the GNU GPL License version 2.
- */
-
-
-#include <unistd.h>
-#include <stdio.h>
-#include <errno.h>
-#include <stdlib.h>
-#include <string.h>
-#include <libintl.h>
-#include <locale.h>
-
-#include <getopt.h>
-
-#include "cpufreq.h"
-
-
-#define _(String) gettext (String)
-#define gettext_noop(String) String
-#define N_(String) gettext_noop (String)
-
-#define LINE_LEN 10
-
-static unsigned int count_cpus(void)
-{
-	FILE *fp;
-	char value[LINE_LEN];
-	unsigned int ret = 0;
-	unsigned int cpunr = 0;
-
-	fp = fopen("/proc/stat", "r");
-	if(!fp) {
-		printf(gettext("Couldn't count the number of CPUs (%s: %s), assuming 1\n"), "/proc/stat", strerror(errno));
-		return 1;
-	}
-
-	while (!feof(fp)) {
-		if (!fgets(value, LINE_LEN, fp))
-			continue;
-		value[LINE_LEN - 1] = '\0';
-		if (strlen(value) < (LINE_LEN - 2))
-			continue;
-		if (strstr(value, "cpu "))
-			continue;
-		if (sscanf(value, "cpu%d ", &cpunr) != 1)
-			continue;
-		if (cpunr > ret)
-			ret = cpunr;
-	}
-	fclose(fp);
-
-	/* cpu count starts from 0, on error return 1 (UP) */
-	return (ret+1);
-}
-
-
-static void proc_cpufreq_output(void)
-{
-	unsigned int cpu, nr_cpus;
-	struct cpufreq_policy *policy;
-	unsigned int min_pctg = 0;
-	unsigned int max_pctg = 0;
-	unsigned long min, max;
-
-	printf(gettext("          minimum CPU frequency  -  maximum CPU frequency  -  governor\n"));
-
-	nr_cpus = count_cpus();
-	for (cpu=0; cpu < nr_cpus; cpu++) {
-		policy = cpufreq_get_policy(cpu);
-		if (!policy)
-			continue;
-
-		if (cpufreq_get_hardware_limits(cpu, &min, &max)) {
-			max = 0;
-		} else {
-			min_pctg = (policy->min * 100) / max;
-			max_pctg = (policy->max * 100) / max;
-		}
-		printf("CPU%3d    %9lu kHz (%3d %%)  -  %9lu kHz (%3d %%)  -  %s\n",
-		       cpu , policy->min, max ? min_pctg : 0, policy->max, max ? max_pctg : 0, policy->governor);
-
-		cpufreq_put_policy(policy);
-	}
-}
-
-static void print_speed(unsigned long speed)
-{
-	unsigned long tmp;
-
-	if (speed > 1000000) {
-		tmp = speed % 10000;
-		if (tmp >= 5000)
-			speed += 10000;
-		printf ("%u.%02u GHz", ((unsigned int) speed/1000000),
-			((unsigned int) (speed%1000000)/10000));
-	} else if (speed > 100000) {
-		tmp = speed % 1000;
-		if (tmp >= 500)
-			speed += 1000;
-		printf ("%u MHz", ((unsigned int) speed / 1000));
-	} else if (speed > 1000) {
-		tmp = speed % 100;
-		if (tmp >= 50)
-			speed += 100;
-		printf ("%u.%01u MHz", ((unsigned int) speed/1000),
-			((unsigned int) (speed%1000)/100));
-	} else
-		printf ("%lu kHz", speed);
-
-	return;
-}
-
-static void print_duration(unsigned long duration)
-{
-	unsigned long tmp;
-
-	if (duration > 1000000) {
-		tmp = duration % 10000;
-		if (tmp >= 5000)
-			duration += 10000;
-		printf ("%u.%02u ms", ((unsigned int) duration/1000000),
-			((unsigned int) (duration%1000000)/10000));
-	} else if (duration > 100000) {
-		tmp = duration % 1000;
-		if (tmp >= 500)
-			duration += 1000;
-		printf ("%u us", ((unsigned int) duration / 1000));
-	} else if (duration > 1000) {
-		tmp = duration % 100;
-		if (tmp >= 50)
-			duration += 100;
-		printf ("%u.%01u us", ((unsigned int) duration/1000),
-			((unsigned int) (duration%1000)/100));
-	} else
-		printf ("%lu ns", duration);
-
-	return;
-}
-
-static void debug_output_one(unsigned int cpu)
-{
-	char *driver;
-	struct cpufreq_affected_cpus *cpus;
-	struct cpufreq_available_frequencies *freqs;
-	unsigned long min, max, freq_kernel, freq_hardware;
-	unsigned long total_trans, latency;
-	unsigned long long total_time;
-	struct cpufreq_policy *policy;
-	struct cpufreq_available_governors * governors;
-	struct cpufreq_stats *stats;
-
-	if (cpufreq_cpu_exists(cpu)) {
-		printf(gettext ("couldn't analyze CPU %d as it doesn't seem to be present\n"), cpu);
-		return;
-	}
-
-	printf(gettext ("analyzing CPU %d:\n"), cpu);
-
-	freq_kernel = cpufreq_get_freq_kernel(cpu);
-	freq_hardware = cpufreq_get_freq_hardware(cpu);
-
-	driver = cpufreq_get_driver(cpu);
-	if (!driver) {
-		printf(gettext ("  no or unknown cpufreq driver is active on this CPU\n"));
-	} else {
-		printf(gettext ("  driver: %s\n"), driver);
-		cpufreq_put_driver(driver);
-	}
-
-	cpus = cpufreq_get_related_cpus(cpu);
-	if (cpus) {
-		printf(gettext ("  CPUs which run at the same hardware frequency: "));
-		while (cpus->next) {
-			printf("%d ", cpus->cpu);
-			cpus = cpus->next;
-		}
-		printf("%d\n", cpus->cpu);
-		cpufreq_put_related_cpus(cpus);
-	}
-
-	cpus = cpufreq_get_affected_cpus(cpu);
-	if (cpus) {
-		printf(gettext ("  CPUs which need to have their frequency coordinated by software: "));
-		while (cpus->next) {
-			printf("%d ", cpus->cpu);
-			cpus = cpus->next;
-		}
-		printf("%d\n", cpus->cpu);
-		cpufreq_put_affected_cpus(cpus);
-	}
-
-	latency = cpufreq_get_transition_latency(cpu);
-	if (latency) {
-		printf(gettext ("  maximum transition latency: "));
-		print_duration(latency);
-		printf(".\n");
-	}
-
-	if (!(cpufreq_get_hardware_limits(cpu, &min, &max))) {
-		printf(gettext ("  hardware limits: "));
-		print_speed(min);
-		printf(" - ");
-		print_speed(max);
-		printf("\n");
-	}
-
-	freqs = cpufreq_get_available_frequencies(cpu);
-	if (freqs) {
-		printf(gettext ("  available frequency steps: "));
-		while (freqs->next) {
-			print_speed(freqs->frequency);
-			printf(", ");
-			freqs = freqs->next;
-		}
-		print_speed(freqs->frequency);
-		printf("\n");
-		cpufreq_put_available_frequencies(freqs);
-	}
-
-	governors = cpufreq_get_available_governors(cpu);
-	if (governors) {
-		printf(gettext ("  available cpufreq governors: "));
-		while (governors->next) {
-			printf("%s, ", governors->governor);
-			governors = governors->next;
-		}
-		printf("%s\n", governors->governor);
-		cpufreq_put_available_governors(governors);
-	}
-
-	policy = cpufreq_get_policy(cpu);
-	if (policy) {
-		printf(gettext ("  current policy: frequency should be within "));
-		print_speed(policy->min);
-		printf(gettext (" and "));
-		print_speed(policy->max);
-
-		printf(".\n                  ");
-		printf(gettext ("The governor \"%s\" may"
-		       " decide which speed to use\n                  within this range.\n"),
-		       policy->governor);
-		cpufreq_put_policy(policy);
-	}
-
-	if (freq_kernel || freq_hardware) {
-		printf(gettext ("  current CPU frequency is "));
-		if (freq_hardware) {
-			print_speed(freq_hardware);
-			printf(gettext (" (asserted by call to hardware)"));
-		}
-		else
-			print_speed(freq_kernel);
-		printf(".\n");
-	}
-	stats = cpufreq_get_stats(cpu, &total_time);
-	if (stats) {
-		printf(gettext ("  cpufreq stats: "));
-		while (stats) {
-			print_speed(stats->frequency);
-			printf(":%.2f%%", (100.0 * stats->time_in_state) / total_time);
-			stats = stats->next;
-			if (stats)
-				printf(", ");
-		}
-		cpufreq_put_stats(stats);
-		total_trans = cpufreq_get_transitions(cpu);
-		if (total_trans)
-			printf("  (%lu)\n", total_trans);
-		else
-			printf("\n");
-	}
-}
-
-static void debug_output(unsigned int cpu, unsigned int all) {
-	if (all) {
-		unsigned int nr_cpus = count_cpus();
-		for (cpu=0; cpu < nr_cpus; cpu++) {
-			if (cpufreq_cpu_exists(cpu))
-				continue;
-			debug_output_one(cpu);
-		}
-	} else
-		debug_output_one(cpu);
-}
-
-
-/* --freq / -f */
-
-static int get_freq_kernel(unsigned int cpu, unsigned int human) {
-	unsigned long freq = cpufreq_get_freq_kernel(cpu);
-	if (!freq)
-		return -EINVAL;
-	if (human) {
-		print_speed(freq);
-		printf("\n");
-	} else
-		printf("%lu\n", freq);
-	return 0;
-}
-
-
-/* --hwfreq / -w */
-
-static int get_freq_hardware(unsigned int cpu, unsigned int human) {
-	unsigned long freq = cpufreq_get_freq_hardware(cpu);
-	if (!freq)
-		return -EINVAL;
-	if (human) {
-		print_speed(freq);
-		printf("\n");
-	} else
-		printf("%lu\n", freq);
-	return 0;
-}
-
-/* --hwlimits / -l */
-
-static int get_hardware_limits(unsigned int cpu) {
-	unsigned long min, max;
-	if (cpufreq_get_hardware_limits(cpu, &min, &max))
-		return -EINVAL;
-	printf("%lu %lu\n", min, max);
-	return 0;
-}
-
-/* --driver / -d */
-
-static int get_driver(unsigned int cpu) {
-	char *driver = cpufreq_get_driver(cpu);
-	if (!driver)
-		return -EINVAL;
-	printf("%s\n", driver);
-	cpufreq_put_driver(driver);
-	return 0;
-}
-
-/* --policy / -p */
-
-static int get_policy(unsigned int cpu) {
-	struct cpufreq_policy *policy = cpufreq_get_policy(cpu);
-	if (!policy)
-		return -EINVAL;
-	printf("%lu %lu %s\n", policy->min, policy->max, policy->governor);
-	cpufreq_put_policy(policy);
-	return 0;
-}
-
-/* --governors / -g */
-
-static int get_available_governors(unsigned int cpu) {
-	struct cpufreq_available_governors *governors = cpufreq_get_available_governors(cpu);
-	if (!governors)
-		return -EINVAL;
-
-	while (governors->next) {
-		printf("%s ", governors->governor);
-		governors = governors->next;
-	}
-	printf("%s\n", governors->governor);
-	cpufreq_put_available_governors(governors);
-	return 0;
-}
-
-
-/* --affected-cpus  / -a */
-
-static int get_affected_cpus(unsigned int cpu) {
-	struct cpufreq_affected_cpus *cpus = cpufreq_get_affected_cpus(cpu);
-	if (!cpus)
-		return -EINVAL;
-
-	while (cpus->next) {
-		printf("%d ", cpus->cpu);
-		cpus = cpus->next;
-	}
-	printf("%d\n", cpus->cpu);
-	cpufreq_put_affected_cpus(cpus);
-	return 0;
-}
-
-/* --related-cpus  / -r */
-
-static int get_related_cpus(unsigned int cpu) {
-	struct cpufreq_affected_cpus *cpus = cpufreq_get_related_cpus(cpu);
-	if (!cpus)
-		return -EINVAL;
-
-	while (cpus->next) {
-		printf("%d ", cpus->cpu);
-		cpus = cpus->next;
-	}
-	printf("%d\n", cpus->cpu);
-	cpufreq_put_related_cpus(cpus);
-	return 0;
-}
-
-/* --stats / -s */
-
-static int get_freq_stats(unsigned int cpu, unsigned int human) {
-	unsigned long total_trans = cpufreq_get_transitions(cpu);
-	unsigned long long total_time;
-	struct cpufreq_stats *stats = cpufreq_get_stats(cpu, &total_time);
-	while (stats) {
-		if (human) {
-			print_speed(stats->frequency);
-			printf(":%.2f%%", (100.0 * stats->time_in_state) / total_time);
-		}
-		else
-			printf("%lu:%llu", stats->frequency, stats->time_in_state);
-		stats = stats->next;
-		if (stats)
-			printf(", ");
-	}
-	cpufreq_put_stats(stats);
-	if (total_trans)
-		printf("  (%lu)\n", total_trans);
-	return 0;
-}
-
-/* --latency / -y */
-
-static int get_latency(unsigned int cpu, unsigned int human) {
-	unsigned long latency = cpufreq_get_transition_latency(cpu);
-	if (!latency)
-		return -EINVAL;
-
-	if (human) {
-		print_duration(latency);
-		printf("\n");
-	} else
-		printf("%lu\n", latency);
-	return 0;
-}
-
-static void print_header(void) {
-	printf(PACKAGE " " VERSION ": cpufreq-info (C) Dominik Brodowski 2004-2009\n");
-	printf(gettext ("Report errors and bugs to %s, please.\n"), PACKAGE_BUGREPORT);
-}
-
-static void print_help(void) {
-	printf(gettext ("Usage: cpufreq-info [options]\n"));
-	printf(gettext ("Options:\n"));
-	printf(gettext ("  -c CPU, --cpu CPU    CPU number which information shall be determined about\n"));
-	printf(gettext ("  -e, --debug          Prints out debug information\n"));
-	printf(gettext ("  -f, --freq           Get frequency the CPU currently runs at, according\n"
-	       "                       to the cpufreq core *\n"));
-	printf(gettext ("  -w, --hwfreq         Get frequency the CPU currently runs at, by reading\n"
-	       "                       it from hardware (only available to root) *\n"));
-	printf(gettext ("  -l, --hwlimits       Determine the minimum and maximum CPU frequency allowed *\n"));
-	printf(gettext ("  -d, --driver         Determines the used cpufreq kernel driver *\n"));
-	printf(gettext ("  -p, --policy         Gets the currently used cpufreq policy *\n"));
-	printf(gettext ("  -g, --governors      Determines available cpufreq governors *\n"));
-	printf(gettext ("  -r, --related-cpus   Determines which CPUs run at the same hardware frequency *\n"));
-	printf(gettext ("  -a, --affected-cpus  Determines which CPUs need to have their frequency\n"
-			"                       coordinated by software *\n"));
-	printf(gettext ("  -s, --stats          Shows cpufreq statistics if available\n"));
-	printf(gettext ("  -y, --latency        Determines the maximum latency on CPU frequency changes *\n"));
-	printf(gettext ("  -o, --proc           Prints out information like provided by the /proc/cpufreq\n"
-	       "                       interface in 2.4. and early 2.6. kernels\n"));
-	printf(gettext ("  -m, --human          human-readable output for the -f, -w, -s and -y parameters\n"));
-	printf(gettext ("  -h, --help           Prints out this screen\n"));
-
-	printf("\n");
-	printf(gettext ("If no argument or only the -c, --cpu parameter is given, debug output about\n"
-	       "cpufreq is printed which is useful e.g. for reporting bugs.\n"));
-	printf(gettext ("For the arguments marked with *, omitting the -c or --cpu argument is\n"
-	"equivalent to setting it to zero\n"));
-}
-
-static struct option info_opts[] = {
-	{ .name="cpu",		.has_arg=required_argument,	.flag=NULL,	.val='c'},
-	{ .name="debug",	.has_arg=no_argument,		.flag=NULL,	.val='e'},
-	{ .name="freq",		.has_arg=no_argument,		.flag=NULL,	.val='f'},
-	{ .name="hwfreq",	.has_arg=no_argument,		.flag=NULL,	.val='w'},
-	{ .name="hwlimits",	.has_arg=no_argument,		.flag=NULL,	.val='l'},
-	{ .name="driver",	.has_arg=no_argument,		.flag=NULL,	.val='d'},
-	{ .name="policy",	.has_arg=no_argument,		.flag=NULL,	.val='p'},
-	{ .name="governors",	.has_arg=no_argument,		.flag=NULL,	.val='g'},
-	{ .name="related-cpus", .has_arg=no_argument,		.flag=NULL,	.val='r'},
-	{ .name="affected-cpus",.has_arg=no_argument,		.flag=NULL,	.val='a'},
-	{ .name="stats",	.has_arg=no_argument,		.flag=NULL,	.val='s'},
-	{ .name="latency",	.has_arg=no_argument,		.flag=NULL,	.val='y'},
-	{ .name="proc",		.has_arg=no_argument,		.flag=NULL,	.val='o'},
-	{ .name="human",	.has_arg=no_argument,		.flag=NULL,	.val='m'},
-	{ .name="help",		.has_arg=no_argument,		.flag=NULL,	.val='h'},
-};
-
-int main(int argc, char **argv) {
-	extern char *optarg;
-	extern int optind, opterr, optopt;
-	int ret = 0, cont = 1;
-	unsigned int cpu = 0;
-	unsigned int cpu_defined = 0;
-	unsigned int human = 0;
-	int output_param = 0;
-
-	setlocale(LC_ALL, "");
-	textdomain (PACKAGE);
-
-	do {
-		ret = getopt_long(argc, argv, "c:hoefwldpgrasmy", info_opts, NULL);
-		switch (ret) {
-		case '?':
-			output_param = '?';
-			cont = 0;
-			break;
-		case 'h':
-			output_param = 'h';
-			cont = 0;
-			break;
-		case -1:
-			cont = 0;
-			break;
-		case 'o':
-		case 'a':
-		case 'r':
-		case 'g':
-		case 'p':
-		case 'd':
-		case 'l':
-		case 'w':
-		case 'f':
-		case 'e':
-		case 's':
-		case 'y':
-			if (output_param) {
-				output_param = -1;
-				cont = 0;
-				break;
-			}
-			output_param = ret;
-			break;
-		case 'c':
-			if (cpu_defined) {
-				output_param = -1;
-				cont = 0;
-				break;
-			}
-			if ((sscanf(optarg, "%d ", &cpu)) != 1) {
-				output_param = '?';
-				cont = 0;
-			}
-			cpu_defined = 1;
-			break;
-		case 'm':
-			if (human) {
-				output_param = -1;
-				cont = 0;
-				break;
-			}
-			human = 1;
-			break;
-		}
-	} while(cont);
-
-	switch (output_param) {
-	case 'o':
-		if (cpu_defined) {
-			print_header();
-			printf(gettext ("The argument passed to this tool can't be combined with passing a --cpu argument\n"));
-			return -EINVAL;
-		}
-		break;
-	case 0:
-		output_param = 'e';
-	}
-
-	ret = 0;
-
-	switch (output_param) {
-	case -1:
-		print_header();
-		printf(gettext ("You can't specify more than one --cpu parameter and/or\n"
-		       "more than one output-specific argument\n"));
-		return -EINVAL;
-		break;
-	case '?':
-		print_header();
-		printf(gettext ("invalid or unknown argument\n"));
-		print_help();
-		ret = -EINVAL;
-		break;
-	case 'h':
-		print_header();
-		print_help();
-		break;
-	case 'o':
-		proc_cpufreq_output();
-		break;
-	case 'e':
-		print_header();
-		debug_output(cpu, !(cpu_defined));
-		break;
-	case 'a':
-		ret = get_affected_cpus(cpu);
-		break;
-	case 'r':
-		ret = get_related_cpus(cpu);
-		break;
-	case 'g':
-		ret = get_available_governors(cpu);
-		break;
-	case 'p':
-		ret = get_policy(cpu);
-		break;
-	case 'd':
-		ret = get_driver(cpu);
-		break;
-	case 'l':
-		ret = get_hardware_limits(cpu);
-		break;
-	case 'w':
-		ret = get_freq_hardware(cpu, human);
-		break;
-	case 'f':
-		ret = get_freq_kernel(cpu, human);
-		break;
-	case 's':
-		ret = get_freq_stats(cpu, human);
-		break;
-	case 'y':
-		ret = get_latency(cpu, human);
-		break;
-	}
-	return (ret);
-}
diff --git a/utils/set.c b/utils/set.c
deleted file mode 100644
index 2ece47e..0000000
--- a/utils/set.c
+++ /dev/null
@@ -1,375 +0,0 @@
-/*
- *  (C) 2004-2009  Dominik Brodowski <linux@dominikbrodowski.de>
- *
- *  Licensed under the terms of the GNU GPL License version 2.
- */
-
-
-#include <unistd.h>
-#include <stdio.h>
-#include <errno.h>
-#include <stdlib.h>
-#include <limits.h>
-#include <string.h>
-#include <ctype.h>
-#include <libintl.h>
-#include <locale.h>
-
-#include <getopt.h>
-
-#include "cpufreq.h"
-
-#define _(String) gettext(String)
-#define gettext_noop(String) String
-#define N_(String) gettext_noop(String)
-
-#define NORM_FREQ_LEN 32
-
-static void print_header(void)
-{
-        printf(PACKAGE " " VERSION ": cpufreq-set (C) Dominik Brodowski 2004-2009\n");
-	printf(gettext("Report errors and bugs to %s, please.\n"), PACKAGE_BUGREPORT);
-}
-
-static void print_help(void)
-{
-	printf(gettext("Usage: cpufreq-set [options]\n"));
-	printf(gettext("Options:\n"));
-	printf(gettext("  -c CPU, --cpu CPU        number of CPU where cpufreq settings shall be modified\n"));
-	printf(gettext("  -d FREQ, --min FREQ      new minimum CPU frequency the governor may select\n"));
-	printf(gettext("  -u FREQ, --max FREQ      new maximum CPU frequency the governor may select\n"));
-	printf(gettext("  -g GOV, --governor GOV   new cpufreq governor\n"));
-	printf(gettext("  -f FREQ, --freq FREQ     specific frequency to be set. Requires userspace\n"
-	       "                           governor to be available and loaded\n"));
-	printf(gettext("  -r, --related            Switches all hardware-related CPUs\n"));
-	printf(gettext("  -h, --help               Prints out this screen\n"));
-	printf("\n");
-	printf(gettext("Notes:\n"
-	       "1. Omitting the -c or --cpu argument is equivalent to setting it to zero\n"
-	       "2. The -f FREQ, --freq FREQ parameter cannot be combined with any other parameter\n"
-	       "   except the -c CPU, --cpu CPU parameter\n"
-	       "3. FREQuencies can be passed in Hz, kHz (default), MHz, GHz, or THz\n"
-	       "   by postfixing the value with the wanted unit name, without any space\n"
-	       "   (FREQuency in kHz =^ Hz * 0.001 =^ MHz * 1000 =^ GHz * 1000000).\n"));
-
-}
-
-static struct option set_opts[] = {
-	{ .name="cpu",		.has_arg=required_argument,	.flag=NULL,	.val='c'},
-	{ .name="min",		.has_arg=required_argument,	.flag=NULL,	.val='d'},
-	{ .name="max",		.has_arg=required_argument,	.flag=NULL,	.val='u'},
-	{ .name="governor",	.has_arg=required_argument,	.flag=NULL,	.val='g'},
-	{ .name="freq",		.has_arg=required_argument,	.flag=NULL,	.val='f'},
-	{ .name="help",		.has_arg=no_argument,		.flag=NULL,	.val='h'},
-	{ .name="related",	.has_arg=no_argument,		.flag=NULL,	.val='r'},
-};
-
-static void print_error(void)
-{
-	printf(gettext("Error setting new values. Common errors:\n"
-			"- Do you have proper administration rights? (super-user?)\n"
-			"- Is the governor you requested available and modprobed?\n"
-			"- Trying to set an invalid policy?\n"
-			"- Trying to set a specific frequency, but userspace governor is not available,\n"
-			"   for example because of hardware which cannot be set to a specific frequency\n"
-			"   or because the userspace governor isn't loaded?\n"));
-};
-
-struct freq_units {
-	char*		str_unit;
-	int		power_of_ten;
-};
-
-const struct freq_units def_units[] = {
-	{"hz", -3},
-	{"khz", 0}, /* default */
-	{"mhz", 3},
-	{"ghz", 6},
-	{"thz", 9},
-	{NULL, 0}
-};
-
-static void print_unknown_arg(void)
-{
-	print_header();
-	printf(gettext("invalid or unknown argument\n"));
-	print_help();
-}
-
-static unsigned long string_to_frequency(const char *str)
-{
-	char normalized[NORM_FREQ_LEN];
-	const struct freq_units *unit;
-	const char *scan;
-	char *end;
-	unsigned long freq;
-	int power = 0, match_count = 0, i, cp, pad;
-
-	while (*str == '0')
-		str++;
-
-	for (scan = str; isdigit(*scan) || *scan == '.'; scan++) {
-		if (*scan == '.' && match_count == 0)
-			match_count = 1;
-		else if (*scan == '.' && match_count == 1)
-			return 0;
-	}
-
-	if (*scan) {
-		match_count = 0;
-		for (unit = def_units; unit->str_unit; unit++) {
-			for (i = 0;
-			     scan[i] && tolower(scan[i]) == unit->str_unit[i];
-			     ++i)
-				continue;
-			if (scan[i])
-				continue;
-			match_count++;
-			power = unit->power_of_ten;
-		}
-		if (match_count != 1)
-			return 0;
-	}
-
-	/* count the number of digits to be copied */
-	for (cp = 0; isdigit(str[cp]); cp++)
-		continue;
-
-	if (str[cp] == '.') {
-		while (power > -1 && isdigit(str[cp+1]))
-			cp++, power--;
-	}
-	if (power >= -1)	/* not enough => pad */
-		pad = power + 1;
-	else			/* to much => strip */
-		pad = 0, cp += power + 1;
-	/* check bounds */
-	if (cp <= 0 || cp + pad > NORM_FREQ_LEN - 1)
-		return 0;
-
-	/* copy digits */
-	for (i = 0; i < cp; i++, str++) {
-		if (*str == '.')
-			str++;
-		normalized[i] = *str;
-	}
-	/* and pad */
-	for (; i < cp + pad; i++)
-		normalized[i] = '0';
-
-	/* round up, down ? */
-	match_count = (normalized[i-1] >= '5');
-	/* and drop the decimal part */
-	normalized[i-1] = 0; /* cp > 0 && pad >= 0 ==> i > 0 */
-
-	/* final conversion (and applying rounding) */
-	errno = 0;
-	freq = strtoul(normalized, &end, 10);
-	if (errno)
-		return 0;
-	else {
-		if (match_count && freq != ULONG_MAX)
-			freq++;
-		return freq;
-	}
-}
-
-static int do_new_policy(unsigned int cpu, struct cpufreq_policy *new_pol)
-{
-	struct cpufreq_policy *cur_pol = cpufreq_get_policy(cpu);
-	int ret;
-
-	if (!cur_pol) {
-		printf(gettext("wrong, unknown or unhandled CPU?\n"));
-		return -EINVAL;
-	}
-
-	if (!new_pol->min)
-		new_pol->min = cur_pol->min;
-
-	if (!new_pol->max)
-		new_pol->max = cur_pol->max;
-
-	if (!new_pol->governor)
-		new_pol->governor = cur_pol->governor;
-
-	ret = cpufreq_set_policy(cpu, new_pol);
-
-	cpufreq_put_policy(cur_pol);
-
-	return ret;
-}
-
-	
-static int do_one_cpu(unsigned int cpu, struct cpufreq_policy *new_pol,
-		unsigned long freq, unsigned int pc)
-{
-	switch (pc) {
-	case 0:
-		return cpufreq_set_frequency(cpu, freq);
-
-	case 1:
-		/* if only one value of a policy is to be changed, we can
-		 * use a "fast path".
-		 */
-		if (new_pol->min)
-			return cpufreq_modify_policy_min(cpu, new_pol->min);
-		else if (new_pol->max)
-			return cpufreq_modify_policy_max(cpu, new_pol->max);
-		else if (new_pol->governor)
-			return cpufreq_modify_policy_governor(cpu, new_pol->governor);
-
-	default:
-		/* slow path */
-		return do_new_policy(cpu, new_pol);
-	}
-}
-
-
-int main(int argc, char **argv)
-{
-	extern char *optarg;
-	extern int optind, opterr, optopt;
-	int ret = 0, cont = 1;
-	unsigned long freq = 0;
-	char gov[20];
-	int double_parm = 0;
-	int related = 0;
-	int policychange = 0;
-	struct cpufreq_policy new_pol = {
-		.min = 0,
-		.max = 0,
-		.governor = NULL,
-	};
-	struct cpufreq_affected_cpus single_cpu = {
-		.cpu = 0,
-		.next = NULL,
-		.first = &single_cpu,
-	};
-	struct cpufreq_affected_cpus *cpus = NULL;
-
-	setlocale(LC_ALL, "");
-	textdomain (PACKAGE);
-
-	/* parameter parsing */
-	do {
-		ret = getopt_long(argc, argv, "c:d:u:g:f:hr", set_opts, NULL);
-		switch (ret) {
-		case '?':
-			print_unknown_arg();
-			return -EINVAL;
-		case 'h':
-			print_header();
-			print_help();
-			return 0;
-		case -1:
-			cont = 0;
-			break;
-		case 'r':
-			if (related)
-				double_parm++;
-			related++;
-			break;
-		case 'c':
-			if (cpus)
-				double_parm++;
-			cpus = &single_cpu;
-			if ((sscanf(optarg, "%d ", &single_cpu.cpu)) != 1) {
-				print_unknown_arg();
-				return -EINVAL;
-                        }
-			break;
-		case 'd':
-			if (new_pol.min)
-				double_parm++;
-			policychange++;
-			new_pol.min = string_to_frequency(optarg);
-			if (new_pol.min == 0) {
-				print_unknown_arg();
-				return -EINVAL;
-			}
-			break;
-		case 'u':
-			if (new_pol.max)
-				double_parm++;
-			policychange++;
-			new_pol.max = string_to_frequency(optarg);
-			if (new_pol.max == 0) {
-				print_unknown_arg();
-				return -EINVAL;
-			}
-			break;
-		case 'f':
-			if (freq)
-				double_parm++;
-			freq = string_to_frequency(optarg);
-			if (freq == 0) {
-				print_unknown_arg();
-				return -EINVAL;
-			}
-			break;
-		case 'g':
-			if (new_pol.governor)
-				double_parm++;
-			policychange++;
-			if ((strlen(optarg) < 3) || (strlen(optarg) > 18)) {
-				print_unknown_arg();
-				return -EINVAL;
-                        }
-			if ((sscanf(optarg, "%s", gov)) != 1) {
-				print_unknown_arg();
-				return -EINVAL;
-                        }
-			new_pol.governor = gov;
-			break;
-		}
-	} while(cont);
-
-	/* parameter checking */
-	if (double_parm) {
-		print_header();
-		printf("the same parameter was passed more than once\n");
-		return -EINVAL;
-	}
-
-	if (freq && policychange) {
-		printf(gettext("the -f/--freq parameter cannot be combined with -d/--min, -u/--max or\n"
-				"-g/--governor parameters\n"));
-		return -EINVAL;
-	}
-
-	if (!freq && !policychange) {
-		printf(gettext("At least one parameter out of -f/--freq, -d/--min, -u/--max, and\n"
-				"-g/--governor must be passed\n"));
-		return -EINVAL;
-	}
-
-
-	/* which CPUs shall we modify? */
-	if (!cpus)
-		cpus = &single_cpu;
-
-	if (related)
-		cpus = cpufreq_get_related_cpus(cpus->cpu);
-
-	/* loop over CPUs */
-	while (1) {
-		ret = do_one_cpu(cpus->cpu, &new_pol, freq, policychange);
-		if (ret)
-			break;
-
-		if (!cpus->next)
-			break;
-
-		cpus = cpus->next;
-	}
-
-	/* cleanup */
-	if (cpus->first != &single_cpu)
-		cpufreq_put_related_cpus(cpus->first);
-
-	if (ret)
-		print_error();
-
-	return ret;
-}
-- 
1.6.4.2


^ permalink raw reply related	[flat|nested] 13+ messages in thread

* [PATCH 2/4] cpufrequtils: Add cpuidle-info tool with some cstate library functions
  2010-09-23 15:30 Rename cpufrequtils into cpupowerutils and provide some basic cpuidle functionality Thomas Renninger
  2010-09-23 15:30 ` [PATCH 1/4] cpufrequtils: Prepare for non-cpufreq related power features by renaming files Thomas Renninger
@ 2010-09-23 15:30 ` Thomas Renninger
  2010-09-23 15:30 ` [PATCH 3/4] cpufrequtils: Rename libcpufreq to libcpupower Thomas Renninger
                   ` (2 subsequent siblings)
  4 siblings, 0 replies; 13+ messages in thread
From: Thomas Renninger @ 2010-09-23 15:30 UTC (permalink / raw)
  To: cpufreq, linux; +Cc: trenn

lib/cpuidle.c is doing it very similar to lib/cpufreq.c
Most info is retrieved from:
/sys/devices/system/cpu/cpu0/cpuidle/state*
/sys/devices/system/cpu/cpuidle/*

The output is not meant to be fixed yet, but should be at some point.
Please provide suggestions how this could get enhanced!

default cpuidle-info reports:

--------------------------------

#> ./utils/cpuidle-info --silent -c0
CPUidle driver: acpi_idle
CPUidle governor: menu
Analyzing CPU 0:
Cstates: 4
Available C-states: C1 C2 C3

--------------------------------

#> /utils/cpuidle-info -c0
CPUidle driver: acpi_idle
CPUidle governor: menu
Analyzing CPU 0:
Cstates: 4
Available C-states: C1 C2 C3
C1:
Flags/Description: ACPI FFH INTEL MWAIT 0x0
Latency: 1
Usage: 366131
Duration: 379777661
C2:
Flags/Description: ACPI FFH INTEL MWAIT 0x10
Latency: 64
Usage: 1050392
Duration: 667633395
C3:
Flags/Description: ACPI FFH INTEL MWAIT 0x20
Latency: 96
Usage: 57846995
Duration: 868424861184

--------------------------------

#> ./utils/cpuidle-info --proc -c0
active state:            C0
max_cstate:              C3
maximum allowed latency: 2000000000 usec
states:
    C1:                  type[C1] promotion[--] demotion[--] latency[001] usage[00366132] duration[00000000000379777813]
    C2:                  type[C2] promotion[--] demotion[--] latency[064] usage[01050393] duration[00000000000667633592]
    C3:                  type[C3] promotion[--] demotion[--] latency[096] usage[57848625] duration[00000000868446911164]

--------------------------------

Notes to --proc compatible output:
active state is hardcoded to be C0 -> proc also always reports zero.

Same for promotion/demotion, it's also hardcoded in the kernel for some time
and returns zero info: [--]

max_cstate provides some sane info, instead of always C8 (proc).

maximum allowed latency is hardcoded, but it may make sense that cpuidle exports
this to userspace, cpuidle at least still uses the qos interface for its
decisions.

type which should differ ACPI exported and real C-state type is hardcoded for
now.

latency, usage and duration are retrieved from cpuidle.
Strange is that latency is the same, usage is the same, but the duration is
a rather different value when retrieved through cpuidle. /proc seem to be
broken, I could even get negativ values there. So better use cpuidle-info -o
instead reading out /proc/acpi/processor/*/power.

Signed-off-by: Thomas Renninger <trenn@suse.de>
CC: linux@dominikbrodowski.net
CC: cpufreq@vger.kernel.org
---
 Makefile             |   13 +-
 lib/cpufreq.c        |   26 ++--
 lib/cpuidle.c        |   59 +++++++
 lib/cpuidle.h        |   32 ++++
 lib/sysfs.c          |  440 +++++++++++++++++++++++++++++++++++++++++---------
 lib/sysfs.h          |   42 ++++--
 utils/cpuidle-info.c |  305 ++++++++++++++++++++++++++++++++++
 7 files changed, 805 insertions(+), 112 deletions(-)
 create mode 100644 lib/cpuidle.c
 create mode 100644 lib/cpuidle.h
 create mode 100644 utils/cpuidle-info.c

diff --git a/Makefile b/Makefile
index aa4b9ff..07637ed 100644
--- a/Makefile
+++ b/Makefile
@@ -111,11 +111,11 @@ WARNINGS += -Wshadow
 CPPFLAGS += -DVERSION=\"$(VERSION)\" -DPACKAGE=\"$(PACKAGE)\" \
 		-DPACKAGE_BUGREPORT=\"$(PACKAGE_BUGREPORT)\" -D_GNU_SOURCE
 
-UTIL_SRC = 	utils/cpufreq-info.c utils/cpufreq-set.c utils/cpufreq-aperf.c utils/cpuid.h
-UTIL_BINS = 	utils/cpufreq-info utils/cpufreq-set utils/cpufreq-aperf
-LIB_HEADERS = 	lib/cpufreq.h lib/sysfs.h
-LIB_SRC = 	lib/cpufreq.c lib/sysfs.c
-LIB_OBJS = 	lib/cpufreq.o lib/sysfs.o
+UTIL_SRC = 	utils/cpufreq-info.c utils/cpufreq-set.c utils/cpufreq-aperf.c utils/cpuidle-info.c utils/cpuid.h
+UTIL_BINS = 	utils/cpufreq-info utils/cpufreq-set utils/cpufreq-aperf utils/cpuidle-info
+LIB_HEADERS = 	lib/cpufreq.h lib/cpuidle.h lib/sysfs.h
+LIB_SRC = 	lib/cpufreq.c lib/cpuidle.c lib/sysfs.c
+LIB_OBJS = 	lib/cpufreq.o lib/cpuidle.o lib/sysfs.o
 
 CFLAGS +=	-pipe
 
@@ -150,8 +150,6 @@ else
 endif
 
 
-
-
 # the actual make rules
 
 all: ccdv libcpufreq utils $(COMPILE_NLS) $(COMPILE_BENCH)
@@ -244,6 +242,7 @@ uninstall:
 	- rm -f $(DESTDIR)${bindir}/cpufreq-set
 	- rm -f $(DESTDIR)${bindir}/cpufreq-info
 	- rm -f $(DESTDIR)${bindir}/cpufreq-aperf
+	- rm -f $(DESTDIR)${bindir}/cpuidle-info
 	- rm -f $(DESTDIR)${mandir}/man1/cpufreq-set.1
 	- rm -f $(DESTDIR)${mandir}/man1/cpufreq-info.1
 	- for HLANG in $(LANGUAGES); do \
diff --git a/lib/cpufreq.c b/lib/cpufreq.c
index 603dbf8..ae7d8c5 100644
--- a/lib/cpufreq.c
+++ b/lib/cpufreq.c
@@ -30,7 +30,7 @@ unsigned long cpufreq_get_freq_hardware(unsigned int cpu)
 
 unsigned long cpufreq_get_transition_latency(unsigned int cpu)
 {
-	return sysfs_get_transition_latency(cpu);
+	return sysfs_get_freq_transition_latency(cpu);
 }
 
 int cpufreq_get_hardware_limits(unsigned int cpu,
@@ -39,11 +39,11 @@ int cpufreq_get_hardware_limits(unsigned int cpu,
 {
 	if ((!min) || (!max))
 		return -EINVAL;
-	return sysfs_get_hardware_limits(cpu, min, max);
+	return sysfs_get_freq_hardware_limits(cpu, min, max);
 }
 
 char * cpufreq_get_driver(unsigned int cpu) {
-	return sysfs_get_driver(cpu);
+	return sysfs_get_freq_driver(cpu);
 }
 
 void cpufreq_put_driver(char * ptr) {
@@ -53,7 +53,7 @@ void cpufreq_put_driver(char * ptr) {
 }
 
 struct cpufreq_policy * cpufreq_get_policy(unsigned int cpu) {
-	return sysfs_get_policy(cpu);
+	return sysfs_get_freq_policy(cpu);
 }
 
 void cpufreq_put_policy(struct cpufreq_policy *policy) {
@@ -66,7 +66,7 @@ void cpufreq_put_policy(struct cpufreq_policy *policy) {
 }
 
 struct cpufreq_available_governors * cpufreq_get_available_governors(unsigned int cpu) {
-	return sysfs_get_available_governors(cpu);
+	return sysfs_get_freq_available_governors(cpu);
 }
 
 void cpufreq_put_available_governors(struct cpufreq_available_governors *any) {
@@ -106,7 +106,7 @@ void cpufreq_put_available_frequencies(struct cpufreq_available_frequencies *any
 
 
 struct cpufreq_affected_cpus * cpufreq_get_affected_cpus(unsigned int cpu) {
-	return sysfs_get_affected_cpus(cpu);
+	return sysfs_get_freq_affected_cpus(cpu);
 }
 
 void cpufreq_put_affected_cpus(struct cpufreq_affected_cpus *any) {
@@ -125,7 +125,7 @@ void cpufreq_put_affected_cpus(struct cpufreq_affected_cpus *any) {
 
 
 struct cpufreq_affected_cpus * cpufreq_get_related_cpus(unsigned int cpu) {
-	return sysfs_get_related_cpus(cpu);
+	return sysfs_get_freq_related_cpus(cpu);
 }
 
 void cpufreq_put_related_cpus(struct cpufreq_affected_cpus *any) {
@@ -137,17 +137,17 @@ int cpufreq_set_policy(unsigned int cpu, struct cpufreq_policy *policy) {
 	if (!policy || !(policy->governor))
 		return -EINVAL;
 
-	return sysfs_set_policy(cpu, policy);
+	return sysfs_set_freq_policy(cpu, policy);
 }
 
 
 int cpufreq_modify_policy_min(unsigned int cpu, unsigned long min_freq) {
-	return sysfs_modify_policy_min(cpu, min_freq);
+	return sysfs_modify_freq_policy_min(cpu, min_freq);
 }
 
 
 int cpufreq_modify_policy_max(unsigned int cpu, unsigned long max_freq) {
-	return sysfs_modify_policy_max(cpu, max_freq);
+	return sysfs_modify_freq_policy_max(cpu, max_freq);
 }
 
 
@@ -155,7 +155,7 @@ int cpufreq_modify_policy_governor(unsigned int cpu, char *governor) {
 	if ((!governor) || (strlen(governor) > 19))
 		return -EINVAL;
 
-	return sysfs_modify_policy_governor(cpu, governor);
+	return sysfs_modify_freq_policy_governor(cpu, governor);
 }
 
 int cpufreq_set_frequency(unsigned int cpu, unsigned long target_frequency) {
@@ -165,7 +165,7 @@ int cpufreq_set_frequency(unsigned int cpu, unsigned long target_frequency) {
 struct cpufreq_stats * cpufreq_get_stats(unsigned int cpu, unsigned long long *total_time) {
 	struct cpufreq_stats *ret;
 
-	ret = sysfs_get_stats(cpu, total_time);
+	ret = sysfs_get_freq_stats(cpu, total_time);
 	return (ret);
 }
 
@@ -184,7 +184,7 @@ void cpufreq_put_stats(struct cpufreq_stats *any) {
 }
 
 unsigned long cpufreq_get_transitions(unsigned int cpu) {
-	unsigned long ret = sysfs_get_transitions(cpu);
+	unsigned long ret = sysfs_get_freq_transitions(cpu);
 
 	return (ret);
 }
diff --git a/lib/cpuidle.c b/lib/cpuidle.c
new file mode 100644
index 0000000..f37cdea
--- /dev/null
+++ b/lib/cpuidle.c
@@ -0,0 +1,59 @@
+/*
+ *  (C) 2004-2009  Dominik Brodowski <linux@dominikbrodowski.de>
+ *
+ *  Licensed under the terms of the GNU GPL License version 2.
+ */
+
+
+#include <stdio.h>
+#include <errno.h>
+#include <stdlib.h>
+#include <string.h>
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <fcntl.h>
+#include <unistd.h>
+
+#include "cpuidle.h"
+#include "sysfs.h"
+
+/* read access to files which contain one numeric value */
+
+int cpuidle_get_cstate_count(unsigned int cpu) {
+	return sysfs_get_cstate_count(cpu);
+}
+
+unsigned long cpuidle_get_cstate_latency(unsigned int cpu, unsigned int cstate)
+{
+	return sysfs_get_cstate_latency(cpu, cstate);
+}
+
+unsigned long cpuidle_get_cstate_usage(unsigned int cpu, unsigned int cstate)
+{
+	return sysfs_get_cstate_usage(cpu, cstate);
+}
+
+unsigned long long cpuidle_get_cstate_time(unsigned int cpu, unsigned int cstate)
+{
+	return sysfs_get_cstate_time(cpu, cstate);
+}
+
+char * cpuidle_get_cstate_name(unsigned int cpu, unsigned int cstate)
+{
+	return sysfs_get_cstate_name(cpu, cstate);
+}
+
+char * cpuidle_get_cstate_desc(unsigned int cpu, unsigned int cstate)
+{
+	return sysfs_get_cstate_desc(cpu, cstate);
+}
+
+char * cpuidle_get_driver(void)
+{
+	return sysfs_get_cpuidle_driver();
+}
+
+char * cpuidle_get_governor(void)
+{
+	return sysfs_get_cpuidle_governor();
+}
diff --git a/lib/cpuidle.h b/lib/cpuidle.h
new file mode 100644
index 0000000..78263fb
--- /dev/null
+++ b/lib/cpuidle.h
@@ -0,0 +1,32 @@
+/*
+ *  cpuidle.h - definitions for libcpupower
+ *
+ *  Copyright (C) 2010  Thomas Renninger <trenn@suse.de>
+ *
+ *  This program is free software; you can redistribute it and/or modify
+ *  it under the terms of the GNU General Public License as published by
+ *  the Free Software Foundation, version 2 of the License.
+ *
+ *  This program is distributed in the hope that it will be useful,
+ *  but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ *  GNU General Public License for more details.
+ *
+ *  You should have received a copy of the GNU General Public License
+ *  along with this program; if not, write to the Free Software
+ *  Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ */
+
+extern int cpuidle_get_cstate_count(unsigned int cpu);
+extern unsigned long cpuidle_get_cstate_latency(unsigned int cpu,
+						unsigned int cstate);
+extern unsigned long cpuidle_get_cstate_usage(unsigned int cpu,
+					      unsigned int cstate);
+extern unsigned long long cpuidle_get_cstate_time(unsigned int cpu,
+					   unsigned int cstate);
+extern char * cpuidle_get_cstate_name(unsigned int cpu, unsigned int cstate);
+extern char * cpuidle_get_cstate_desc(unsigned int cpu, unsigned int cstate);
+extern char * cpuidle_get_driver(void);
+extern char * cpuidle_get_governor(void);
+
+
diff --git a/lib/sysfs.c b/lib/sysfs.c
index 4e0edab..2cc368a 100644
--- a/lib/sysfs.c
+++ b/lib/sysfs.c
@@ -21,9 +21,12 @@
 #define MAX_LINE_LEN 255
 #define SYSFS_PATH_MAX 255
 
+/* CPUFREQ sysfs access **************************************************/
+
 /* helper function to read file from /sys into given buffer */
 /* fname is a relative path under "cpuX/cpufreq" dir */
-unsigned int sysfs_read_file(unsigned int cpu, const char *fname, char *buf, size_t buflen)
+unsigned int sysfs_cpufreq_read_file(unsigned int cpu, const char *fname,
+				     char *buf, size_t buflen)
 {
 	char path[SYSFS_PATH_MAX];
 	int fd;
@@ -50,7 +53,8 @@ unsigned int sysfs_read_file(unsigned int cpu, const char *fname, char *buf, siz
 
 /* helper function to write a new value to a /sys file */
 /* fname is a relative path under "cpuX/cpufreq" dir */
-unsigned int sysfs_write_file(unsigned int cpu, const char *fname, const char *value, size_t len)
+unsigned int sysfs_cpufreq_write_file(unsigned int cpu, const char *fname,
+				      const char *value, size_t len)
 {
 	char path[SYSFS_PATH_MAX];
 	int fd;
@@ -76,7 +80,7 @@ unsigned int sysfs_write_file(unsigned int cpu, const char *fname, const char *v
 
 /* read access to files which contain one numeric value */
 
-enum {
+enum cpufreq_value {
 	CPUINFO_CUR_FREQ,
 	CPUINFO_MIN_FREQ,
 	CPUINFO_MAX_FREQ,
@@ -85,10 +89,10 @@ enum {
 	SCALING_MIN_FREQ,
 	SCALING_MAX_FREQ,
 	STATS_NUM_TRANSITIONS,
-	MAX_VALUE_FILES
+	MAX_CPUFREQ_VALUE_READ_FILES
 };
 
-static const char *value_files[MAX_VALUE_FILES] = {
+static const char *cpufreq_value_files[MAX_CPUFREQ_VALUE_READ_FILES] = {
 	[CPUINFO_CUR_FREQ] = "cpuinfo_cur_freq",
 	[CPUINFO_MIN_FREQ] = "cpuinfo_min_freq",
 	[CPUINFO_MAX_FREQ] = "cpuinfo_max_freq",
@@ -100,20 +104,20 @@ static const char *value_files[MAX_VALUE_FILES] = {
 };
 
 
-static unsigned long sysfs_get_one_value(unsigned int cpu, unsigned int which)
+static unsigned long sysfs_cpufreq_get_one_value(unsigned int cpu,
+						 enum cpufreq_value which)
 {
  	unsigned long value;
 	unsigned int len;
 	char linebuf[MAX_LINE_LEN];
 	char *endp;
 
-	if ( which >= MAX_VALUE_FILES )
+	if ( which >= MAX_CPUFREQ_VALUE_READ_FILES )
 		return 0;
 
-	if ( ( len = sysfs_read_file(cpu, value_files[which], linebuf, sizeof(linebuf))) == 0 )
-	{
+	if ( ( len = sysfs_cpufreq_read_file(cpu, cpufreq_value_files[which],
+					     linebuf, sizeof(linebuf))) == 0 )
 		return 0;
-	}
 
 	value = strtoul(linebuf, &endp, 0);
 
@@ -125,31 +129,31 @@ static unsigned long sysfs_get_one_value(unsigned int cpu, unsigned int which)
 
 /* read access to files which contain one string */
 
-enum {
+enum cpufreq_string {
 	SCALING_DRIVER,
 	SCALING_GOVERNOR,
-	MAX_STRING_FILES
+	MAX_CPUFREQ_STRING_FILES
 };
 
-static const char *string_files[MAX_STRING_FILES] = {
+static const char *cpufreq_string_files[MAX_CPUFREQ_STRING_FILES] = {
 	[SCALING_DRIVER] = "scaling_driver",
 	[SCALING_GOVERNOR] = "scaling_governor",
 };
 
 
-static char * sysfs_get_one_string(unsigned int cpu, unsigned int which)
+static char * sysfs_cpufreq_get_one_string(unsigned int cpu,
+					   enum cpufreq_string which)
 {
 	char linebuf[MAX_LINE_LEN];
 	char *result;
 	unsigned int len;
 
-	if (which >= MAX_STRING_FILES)
+	if (which >= MAX_CPUFREQ_STRING_FILES)
 		return NULL;
 
-	if ( ( len = sysfs_read_file(cpu, string_files[which], linebuf, sizeof(linebuf))) == 0 )
-	{
+	if ( ( len = sysfs_cpufreq_read_file(cpu, cpufreq_string_files[which],
+					     linebuf, sizeof(linebuf))) == 0 )
 		return NULL;
-	}
 
 	if ( ( result = strdup(linebuf) ) == NULL )
 		return NULL;
@@ -162,99 +166,86 @@ static char * sysfs_get_one_string(unsigned int cpu, unsigned int which)
 
 /* write access */
 
-enum {
+enum cpufreq_write {
 	WRITE_SCALING_MIN_FREQ,
 	WRITE_SCALING_MAX_FREQ,
 	WRITE_SCALING_GOVERNOR,
 	WRITE_SCALING_SET_SPEED,
-	MAX_WRITE_FILES
+	MAX_CPUFREQ_WRITE_FILES
 };
 
-static const char *write_files[MAX_VALUE_FILES] = {
+static const char *cpufreq_write_files[MAX_CPUFREQ_WRITE_FILES] = {
 	[WRITE_SCALING_MIN_FREQ] = "scaling_min_freq",
 	[WRITE_SCALING_MAX_FREQ] = "scaling_max_freq",
 	[WRITE_SCALING_GOVERNOR] = "scaling_governor",
 	[WRITE_SCALING_SET_SPEED] = "scaling_setspeed",
 };
 
-static int sysfs_write_one_value(unsigned int cpu, unsigned int which,
-				 const char *new_value, size_t len)
+static int sysfs_cpufreq_write_one_value(unsigned int cpu,
+					 enum cpufreq_write which,
+					 const char *new_value, size_t len)
 {
-	if (which >= MAX_WRITE_FILES)
+	if (which >= MAX_CPUFREQ_WRITE_FILES)
 		return 0;
 
-	if ( sysfs_write_file(cpu, write_files[which], new_value, len) != len )
+	if ( sysfs_cpufreq_write_file(cpu, cpufreq_write_files[which],
+			      new_value, len) != len )
 		return -ENODEV;
 
 	return 0;
 };
 
-
-int sysfs_cpu_exists(unsigned int cpu)
-{
-	char file[SYSFS_PATH_MAX];
-	struct stat statbuf;
-
-	snprintf(file, SYSFS_PATH_MAX, PATH_TO_CPU "cpu%u/", cpu);
-
-	if ( stat(file, &statbuf) != 0 )
-		return -ENOSYS;
-
-	return S_ISDIR(statbuf.st_mode) ? 0 : -ENOSYS;
-}
-
-
 unsigned long sysfs_get_freq_kernel(unsigned int cpu)
 {
-	return sysfs_get_one_value(cpu, SCALING_CUR_FREQ);
+	return sysfs_cpufreq_get_one_value(cpu, SCALING_CUR_FREQ);
 }
 
 unsigned long sysfs_get_freq_hardware(unsigned int cpu)
 {
-	return sysfs_get_one_value(cpu, CPUINFO_CUR_FREQ);
+	return sysfs_cpufreq_get_one_value(cpu, CPUINFO_CUR_FREQ);
 }
 
-unsigned long sysfs_get_transition_latency(unsigned int cpu)
+unsigned long sysfs_get_freq_transition_latency(unsigned int cpu)
 {
-	return sysfs_get_one_value(cpu, CPUINFO_LATENCY);
+	return sysfs_cpufreq_get_one_value(cpu, CPUINFO_LATENCY);
 }
 
-int sysfs_get_hardware_limits(unsigned int cpu,
+int sysfs_get_freq_hardware_limits(unsigned int cpu,
 			      unsigned long *min,
 			      unsigned long *max)
 {
 	if ((!min) || (!max))
 		return -EINVAL;
 
-	*min = sysfs_get_one_value(cpu, CPUINFO_MIN_FREQ);
+	*min = sysfs_cpufreq_get_one_value(cpu, CPUINFO_MIN_FREQ);
 	if (!*min)
 		return -ENODEV;
 
-	*max = sysfs_get_one_value(cpu, CPUINFO_MAX_FREQ);
+	*max = sysfs_cpufreq_get_one_value(cpu, CPUINFO_MAX_FREQ);
 	if (!*max)
 		return -ENODEV;
 
 	return 0;
 }
 
-char * sysfs_get_driver(unsigned int cpu) {
-	return sysfs_get_one_string(cpu, SCALING_DRIVER);
+char * sysfs_get_freq_driver(unsigned int cpu) {
+	return sysfs_cpufreq_get_one_string(cpu, SCALING_DRIVER);
 }
 
-struct cpufreq_policy * sysfs_get_policy(unsigned int cpu) {
+struct cpufreq_policy * sysfs_get_freq_policy(unsigned int cpu) {
 	struct cpufreq_policy *policy;
 
 	policy = malloc(sizeof(struct cpufreq_policy));
 	if (!policy)
 		return NULL;
 
-	policy->governor = sysfs_get_one_string(cpu, SCALING_GOVERNOR);
+	policy->governor = sysfs_cpufreq_get_one_string(cpu, SCALING_GOVERNOR);
 	if (!policy->governor) {
 		free(policy);
 		return NULL;
 	}
-	policy->min = sysfs_get_one_value(cpu, SCALING_MIN_FREQ);
-	policy->max = sysfs_get_one_value(cpu, SCALING_MAX_FREQ);
+	policy->min = sysfs_cpufreq_get_one_value(cpu, SCALING_MIN_FREQ);
+	policy->max = sysfs_cpufreq_get_one_value(cpu, SCALING_MAX_FREQ);
 	if ((!policy->min) || (!policy->max)) {
 		free(policy->governor);
 		free(policy);
@@ -264,14 +255,16 @@ struct cpufreq_policy * sysfs_get_policy(unsigned int cpu) {
 	return policy;
 }
 
-struct cpufreq_available_governors * sysfs_get_available_governors(unsigned int cpu) {
+struct cpufreq_available_governors *
+sysfs_get_freq_available_governors(unsigned int cpu) {
 	struct cpufreq_available_governors *first = NULL;
 	struct cpufreq_available_governors *current = NULL;
 	char linebuf[MAX_LINE_LEN];
 	unsigned int pos, i;
 	unsigned int len;
 
-	if ( ( len = sysfs_read_file(cpu, "scaling_available_governors", linebuf, sizeof(linebuf))) == 0 )
+	if ( ( len = sysfs_cpufreq_read_file(cpu, "scaling_available_governors",
+					     linebuf, sizeof(linebuf))) == 0 )
 	{
 		return NULL;
 	}
@@ -321,7 +314,8 @@ struct cpufreq_available_governors * sysfs_get_available_governors(unsigned int
 }
 
 
-struct cpufreq_available_frequencies * sysfs_get_available_frequencies(unsigned int cpu) {
+struct cpufreq_available_frequencies *
+sysfs_get_available_frequencies(unsigned int cpu) {
 	struct cpufreq_available_frequencies *first = NULL;
 	struct cpufreq_available_frequencies *current = NULL;
 	char one_value[SYSFS_PATH_MAX];
@@ -329,7 +323,9 @@ struct cpufreq_available_frequencies * sysfs_get_available_frequencies(unsigned
 	unsigned int pos, i;
 	unsigned int len;
 
-	if ( ( len = sysfs_read_file(cpu, "scaling_available_frequencies", linebuf, sizeof(linebuf))) == 0 )
+	if ( ( len = sysfs_cpufreq_read_file(cpu,
+					     "scaling_available_frequencies",
+					     linebuf, sizeof(linebuf))) == 0 )
 	{
 		return NULL;
 	}
@@ -386,7 +382,8 @@ static struct cpufreq_affected_cpus * sysfs_get_cpu_list(unsigned int cpu,
 	unsigned int pos, i;
 	unsigned int len;
 
-	if ( ( len = sysfs_read_file(cpu, file, linebuf, sizeof(linebuf))) == 0 )
+	if ( ( len = sysfs_cpufreq_read_file(cpu, file, linebuf,
+					     sizeof(linebuf))) == 0 )
 	{
 		return NULL;
 	}
@@ -435,15 +432,15 @@ static struct cpufreq_affected_cpus * sysfs_get_cpu_list(unsigned int cpu,
 	return NULL;
 }
 
-struct cpufreq_affected_cpus * sysfs_get_affected_cpus(unsigned int cpu) {
+struct cpufreq_affected_cpus * sysfs_get_freq_affected_cpus(unsigned int cpu) {
 	return sysfs_get_cpu_list(cpu, "affected_cpus");
 }
 
-struct cpufreq_affected_cpus * sysfs_get_related_cpus(unsigned int cpu) {
+struct cpufreq_affected_cpus * sysfs_get_freq_related_cpus(unsigned int cpu) {
 	return sysfs_get_cpu_list(cpu, "related_cpus");
 }
 
-struct cpufreq_stats * sysfs_get_stats(unsigned int cpu, unsigned long long *total_time) {
+struct cpufreq_stats * sysfs_get_freq_stats(unsigned int cpu, unsigned long long *total_time) {
 	struct cpufreq_stats *first = NULL;
 	struct cpufreq_stats *current = NULL;
 	char one_value[SYSFS_PATH_MAX];
@@ -451,7 +448,8 @@ struct cpufreq_stats * sysfs_get_stats(unsigned int cpu, unsigned long long *tot
 	unsigned int pos, i;
 	unsigned int len;
 
-	if ( ( len = sysfs_read_file(cpu, "stats/time_in_state", linebuf, sizeof(linebuf))) == 0 )
+	if ( ( len = sysfs_cpufreq_read_file(cpu, "stats/time_in_state",
+					     linebuf, sizeof(linebuf))) == 0 )
 		return NULL;
 
 	*total_time = 0;
@@ -499,9 +497,9 @@ struct cpufreq_stats * sysfs_get_stats(unsigned int cpu, unsigned long long *tot
 	return NULL;
 }
 
-unsigned long sysfs_get_transitions(unsigned int cpu)
+unsigned long sysfs_get_freq_transitions(unsigned int cpu)
 {
-	return sysfs_get_one_value(cpu, STATS_NUM_TRANSITIONS);
+	return sysfs_cpufreq_get_one_value(cpu, STATS_NUM_TRANSITIONS);
 }
 
 static int verify_gov(char *new_gov, char *passed_gov)
@@ -539,7 +537,7 @@ static int verify_gov(char *new_gov, char *passed_gov)
 	return 0;
 }
 
-int sysfs_modify_policy_governor(unsigned int cpu, char *governor)
+int sysfs_modify_freq_policy_governor(unsigned int cpu, char *governor)
 {
 	char new_gov[SYSFS_PATH_MAX];
 
@@ -549,30 +547,33 @@ int sysfs_modify_policy_governor(unsigned int cpu, char *governor)
 	if (verify_gov(new_gov, governor))
 		return -EINVAL;
 
-	return sysfs_write_one_value(cpu, WRITE_SCALING_GOVERNOR, new_gov, strlen(new_gov));
+	return sysfs_cpufreq_write_one_value(cpu, WRITE_SCALING_GOVERNOR,
+					     new_gov, strlen(new_gov));
 };
 
-int sysfs_modify_policy_max(unsigned int cpu, unsigned long max_freq)
+int sysfs_modify_freq_policy_max(unsigned int cpu, unsigned long max_freq)
 {
 	char value[SYSFS_PATH_MAX];
 
 	snprintf(value, SYSFS_PATH_MAX, "%lu", max_freq);
 
-	return sysfs_write_one_value(cpu, WRITE_SCALING_MAX_FREQ, value, strlen(value));
+	return sysfs_cpufreq_write_one_value(cpu, WRITE_SCALING_MAX_FREQ,
+					     value, strlen(value));
 };
 
 
-int sysfs_modify_policy_min(unsigned int cpu, unsigned long min_freq)
+int sysfs_modify_freq_policy_min(unsigned int cpu, unsigned long min_freq)
 {
 	char value[SYSFS_PATH_MAX];
 
 	snprintf(value, SYSFS_PATH_MAX, "%lu", min_freq);
 
-	return sysfs_write_one_value(cpu, WRITE_SCALING_MIN_FREQ, value, strlen(value));
+	return sysfs_cpufreq_write_one_value(cpu, WRITE_SCALING_MIN_FREQ,
+					     value, strlen(value));
 };
 
 
-int sysfs_set_policy(unsigned int cpu, struct cpufreq_policy *policy)
+int sysfs_set_freq_policy(unsigned int cpu, struct cpufreq_policy *policy)
 {
 	char min[SYSFS_PATH_MAX];
 	char max[SYSFS_PATH_MAX];
@@ -593,30 +594,34 @@ int sysfs_set_policy(unsigned int cpu, struct cpufreq_policy *policy)
 	snprintf(min, SYSFS_PATH_MAX, "%lu", policy->min);
 	snprintf(max, SYSFS_PATH_MAX, "%lu", policy->max);
 
-	old_min = sysfs_get_one_value(cpu, SCALING_MIN_FREQ);
+	old_min = sysfs_cpufreq_get_one_value(cpu, SCALING_MIN_FREQ);
 	write_max_first = (old_min && (policy->max < old_min) ? 0 : 1);
 
 	if (write_max_first) {
-		ret = sysfs_write_one_value(cpu, WRITE_SCALING_MAX_FREQ, max, strlen(max));
+		ret = sysfs_cpufreq_write_one_value(cpu, WRITE_SCALING_MAX_FREQ,
+						    max, strlen(max));
 		if (ret)
 			return ret;
 	}
 
-	ret = sysfs_write_one_value(cpu, WRITE_SCALING_MIN_FREQ, min, strlen(min));
+	ret = sysfs_cpufreq_write_one_value(cpu, WRITE_SCALING_MIN_FREQ, min,
+					    strlen(min));
 	if (ret)
 		return ret;
 
 	if (!write_max_first) {
-		ret = sysfs_write_one_value(cpu, WRITE_SCALING_MAX_FREQ, max, strlen(max));
+		ret = sysfs_cpufreq_write_one_value(cpu, WRITE_SCALING_MAX_FREQ,
+						    max, strlen(max));
 		if (ret)
 			return ret;
 	}
 
-	return sysfs_write_one_value(cpu, WRITE_SCALING_GOVERNOR, gov, strlen(gov));
+	return sysfs_cpufreq_write_one_value(cpu, WRITE_SCALING_GOVERNOR,
+					     gov, strlen(gov));
 }
 
 int sysfs_set_frequency(unsigned int cpu, unsigned long target_frequency) {
-	struct cpufreq_policy *pol = sysfs_get_policy(cpu);
+	struct cpufreq_policy *pol = sysfs_get_freq_policy(cpu);
 	char userspace_gov[] = "userspace";
 	char freq[SYSFS_PATH_MAX];
 	int ret;
@@ -625,7 +630,7 @@ int sysfs_set_frequency(unsigned int cpu, unsigned long target_frequency) {
 		return -ENODEV;
 
 	if (strncmp(pol->governor, userspace_gov, 9) != 0) {
-		ret = sysfs_modify_policy_governor(cpu, userspace_gov);
+		ret = sysfs_modify_freq_policy_governor(cpu, userspace_gov);
 		if (ret) {
 			cpufreq_put_policy(pol);
 			return (ret);
@@ -636,5 +641,282 @@ int sysfs_set_frequency(unsigned int cpu, unsigned long target_frequency) {
 
 	snprintf(freq, SYSFS_PATH_MAX, "%lu", target_frequency);
 
-	return sysfs_write_one_value(cpu, WRITE_SCALING_SET_SPEED, freq, strlen(freq));
+	return sysfs_cpufreq_write_one_value(cpu, WRITE_SCALING_SET_SPEED,
+					     freq, strlen(freq));
+}
+
+/* CPUFREQ sysfs access **************************************************/
+
+/* CPUidle Cstate specific /sys/devices/system/cpu/cpuX/cpuidle/ access */
+
+/*
+ * helper function to read file from /sys into given buffer
+ * fname is a relative path under "cpuX/cpuidle/stateX/" dir
+ * cstates starting with 0, C0 is not counted as cstate.
+ * This means if you want C1 info, pass 0 as cstate param
+ */
+unsigned int sysfs_cstate_read_file(unsigned int cpu, unsigned int cstate,
+			     const char *fname, char *buf, size_t buflen)
+{
+	char path[SYSFS_PATH_MAX];
+	int fd;
+	size_t numread;
+
+	snprintf(path, sizeof(path), PATH_TO_CPU "cpu%u/cpuidle/state%u/%s",
+		 cpu, cstate, fname);
+
+	if ( ( fd = open(path, O_RDONLY) ) == -1 )
+		return 0;
+
+	numread = read(fd, buf, buflen - 1);
+	if ( numread < 1 )
+	{
+		close(fd);
+		return 0;
+	}
+
+	buf[numread] = '\0';
+	close(fd);
+
+	return numread;
 }
+
+/* read access to files which contain one numeric value */
+
+enum cstate_value {
+	CSTATE_USAGE,
+	CSTATE_POWER,
+	CSTATE_LATENCY,
+	CSTATE_TIME,
+	MAX_CSTATE_VALUE_FILES
+};
+
+static const char *cstate_value_files[MAX_CSTATE_VALUE_FILES] = {
+	[CSTATE_USAGE] = "usage",
+	[CSTATE_POWER] = "power",
+	[CSTATE_LATENCY] = "latency",
+	[CSTATE_TIME]  = "time",
+};
+
+static unsigned long long sysfs_cstate_get_one_value(unsigned int cpu,
+						     unsigned int cstate,
+						     enum cstate_value which)
+{
+ 	unsigned long value;
+	unsigned int len;
+	char linebuf[MAX_LINE_LEN];
+	char *endp;
+
+	if ( which >= MAX_CSTATE_VALUE_FILES )
+		return 0;
+
+	if ( ( len = sysfs_cstate_read_file(cpu, cstate,
+					    cstate_value_files[which],
+					    linebuf, sizeof(linebuf))) == 0 )
+	{
+		return 0;
+	}
+
+	value = strtoul(linebuf, &endp, 0);
+
+	if ( endp == linebuf || errno == ERANGE )
+		return 0;
+
+	return value;
+}
+
+/* read access to files which contain one string */
+
+enum cstate_string {
+	CSTATE_DESC,
+	CSTATE_NAME,
+	MAX_CSTATE_STRING_FILES
+};
+
+static const char *cstate_string_files[MAX_CSTATE_STRING_FILES] = {
+	[CSTATE_DESC] = "desc",
+	[CSTATE_NAME] = "name",
+};
+
+
+static char * sysfs_cstate_get_one_string(unsigned int cpu,
+					  unsigned int cstate,
+					  enum cstate_string which)
+{
+	char linebuf[MAX_LINE_LEN];
+	char *result;
+	unsigned int len;
+
+	if (which >= MAX_CSTATE_STRING_FILES)
+		return NULL;
+
+	if ( ( len = sysfs_cstate_read_file(cpu, cstate,
+					    cstate_string_files[which],
+					    linebuf, sizeof(linebuf))) == 0 )
+		return NULL;
+
+	if ( ( result = strdup(linebuf) ) == NULL )
+		return NULL;
+
+	if (result[strlen(result) - 1] == '\n')
+		result[strlen(result) - 1] = '\0';
+
+	return result;
+}
+
+unsigned long sysfs_get_cstate_latency(unsigned int cpu, unsigned int cstate)
+{
+	return sysfs_cstate_get_one_value(cpu, cstate, CSTATE_LATENCY);
+}
+
+unsigned long sysfs_get_cstate_usage(unsigned int cpu, unsigned int cstate)
+{
+	return sysfs_cstate_get_one_value(cpu, cstate, CSTATE_USAGE);
+}
+
+unsigned long long sysfs_get_cstate_time(unsigned int cpu, unsigned int cstate)
+{
+	return sysfs_cstate_get_one_value(cpu, cstate, CSTATE_TIME);
+}
+
+char * sysfs_get_cstate_name(unsigned int cpu, unsigned int cstate)
+{
+	return sysfs_cstate_get_one_string(cpu, cstate, CSTATE_NAME);
+}
+
+char * sysfs_get_cstate_desc(unsigned int cpu, unsigned int cstate)
+{
+	return sysfs_cstate_get_one_string(cpu, cstate, CSTATE_DESC);
+}
+
+/*
+ * Returns number of supported C-states of CPU core cpu
+ * Negativ in error case
+ * Zero if cpuidle does not export any C-states
+ */
+int sysfs_get_cstate_count(unsigned int cpu)
+{
+	char file[SYSFS_PATH_MAX];
+	struct stat statbuf;
+	int cstates = 1;
+
+	
+	snprintf(file, SYSFS_PATH_MAX, PATH_TO_CPU "cpuidle");
+	if ( stat(file, &statbuf) != 0 || !S_ISDIR(statbuf.st_mode))
+		return -ENODEV;
+
+	snprintf(file, SYSFS_PATH_MAX, PATH_TO_CPU "cpu%u/cpuidle/state0", cpu);
+	if ( stat(file, &statbuf) != 0 || !S_ISDIR(statbuf.st_mode))
+		return 0;
+
+	while(stat(file, &statbuf) == 0 && S_ISDIR(statbuf.st_mode)) {
+		snprintf(file, SYSFS_PATH_MAX, PATH_TO_CPU
+			 "cpu%u/cpuidle/state%d", cpu, cstates);
+		cstates++;
+	}
+	cstates--;
+	return cstates;
+}
+
+/* CPUidle Cstate specific /sys/devices/system/cpu/cpuX/cpuidle/ access */
+
+/* CPUidle general /sys/devices/system/cpu/cpuidle/ sysfs access ********/
+
+/*
+ * helper function to read file from /sys into given buffer
+ * fname is a relative path under "cpu/cpuidle/" dir
+ */
+unsigned int sysfs_cpuidle_read_file(const char *fname, char *buf,
+				     size_t buflen)
+{
+	char path[SYSFS_PATH_MAX];
+	int fd;
+	size_t numread;
+
+	snprintf(path, sizeof(path), PATH_TO_CPU "cpuidle/%s", fname);
+
+	if ( ( fd = open(path, O_RDONLY) ) == -1 )
+		return 0;
+
+	numread = read(fd, buf, buflen - 1);
+	if ( numread < 1 )
+	{
+		close(fd);
+		return 0;
+	}
+
+	buf[numread] = '\0';
+	close(fd);
+
+	return numread;
+}
+
+/* read access to files which contain one string */
+
+enum cpuidle_string {
+	CPUIDLE_GOVERNOR,
+	CPUIDLE_GOVERNOR_RO,
+	CPUIDLE_DRIVER,
+	MAX_CPUIDLE_STRING_FILES
+};
+
+static const char *cpuidle_string_files[MAX_CPUIDLE_STRING_FILES] = {
+	[CPUIDLE_GOVERNOR]	= "current_governor",
+	[CPUIDLE_GOVERNOR_RO]	= "current_governor_ro",
+	[CPUIDLE_DRIVER]	= "current_driver",
+};
+
+
+static char * sysfs_cpuidle_get_one_string(enum cpuidle_string which)
+{
+	char linebuf[MAX_LINE_LEN];
+	char *result;
+	unsigned int len;
+
+	if (which >= MAX_CPUIDLE_STRING_FILES)
+		return NULL;
+
+	if ( ( len = sysfs_cpuidle_read_file(cpuidle_string_files[which],
+					    linebuf, sizeof(linebuf))) == 0 )
+		return NULL;
+
+	if ( ( result = strdup(linebuf) ) == NULL )
+		return NULL;
+
+	if (result[strlen(result) - 1] == '\n')
+		result[strlen(result) - 1] = '\0';
+
+	return result;
+}
+
+char * sysfs_get_cpuidle_governor(void)
+{
+	char *tmp = sysfs_cpuidle_get_one_string(CPUIDLE_GOVERNOR_RO);
+	if (!tmp)
+		return sysfs_cpuidle_get_one_string(CPUIDLE_GOVERNOR);
+	else
+		return tmp;
+}
+
+char * sysfs_get_cpuidle_driver(void)
+{
+	return sysfs_cpuidle_get_one_string(CPUIDLE_DRIVER);
+}
+
+/* CPUidle general /sys/devices/system/cpu/cpuidle/ sysfs access ********/
+
+/* General sysfs access **************************************************/
+int sysfs_cpu_exists(unsigned int cpu)
+{
+	char file[SYSFS_PATH_MAX];
+	struct stat statbuf;
+
+	snprintf(file, SYSFS_PATH_MAX, PATH_TO_CPU "cpu%u/", cpu);
+
+	if ( stat(file, &statbuf) != 0 )
+		return -ENOSYS;
+
+	return S_ISDIR(statbuf.st_mode) ? 0 : -ENOSYS;
+}
+/* General sysfs access **************************************************/
+
diff --git a/lib/sysfs.h b/lib/sysfs.h
index b8a2b69..c0eed4e 100644
--- a/lib/sysfs.h
+++ b/lib/sysfs.h
@@ -1,19 +1,35 @@
+/* General */
 extern unsigned int sysfs_cpu_exists(unsigned int cpu);
+
+/* CPUfreq */
 extern unsigned long sysfs_get_freq_kernel(unsigned int cpu);
 extern unsigned long sysfs_get_freq_hardware(unsigned int cpu);
-extern unsigned long sysfs_get_transition_latency(unsigned int cpu);
-extern int sysfs_get_hardware_limits(unsigned int cpu, unsigned long *min, unsigned long *max);
-extern char * sysfs_get_driver(unsigned int cpu);
-extern struct cpufreq_policy * sysfs_get_policy(unsigned int cpu);
-extern struct cpufreq_available_governors * sysfs_get_available_governors(unsigned int cpu);
+extern unsigned long sysfs_get_freq_transition_latency(unsigned int cpu);
+extern int sysfs_get_freq_hardware_limits(unsigned int cpu, unsigned long *min, unsigned long *max);
+extern char * sysfs_get_freq_driver(unsigned int cpu);
+extern struct cpufreq_policy * sysfs_get_freq_policy(unsigned int cpu);
+extern struct cpufreq_available_governors * sysfs_get_freq_available_governors(unsigned int cpu);
 extern struct cpufreq_available_frequencies * sysfs_get_available_frequencies(unsigned int cpu);
-extern struct cpufreq_affected_cpus * sysfs_get_affected_cpus(unsigned int cpu);
-extern struct cpufreq_affected_cpus * sysfs_get_related_cpus(unsigned int cpu);
-extern struct cpufreq_stats * sysfs_get_stats(unsigned int cpu, unsigned long long *total_time);
-extern unsigned long sysfs_get_transitions(unsigned int cpu);
-extern int sysfs_set_policy(unsigned int cpu, struct cpufreq_policy *policy);
-extern int sysfs_modify_policy_min(unsigned int cpu, unsigned long min_freq);
-extern int sysfs_modify_policy_max(unsigned int cpu, unsigned long max_freq);
-extern int sysfs_modify_policy_governor(unsigned int cpu, char *governor);
+extern struct cpufreq_affected_cpus * sysfs_get_freq_affected_cpus(unsigned int cpu);
+extern struct cpufreq_affected_cpus * sysfs_get_freq_related_cpus(unsigned int cpu);
+extern struct cpufreq_stats * sysfs_get_freq_stats(unsigned int cpu, unsigned long long *total_time);
+extern unsigned long sysfs_get_freq_transitions(unsigned int cpu);
+extern int sysfs_set_freq_policy(unsigned int cpu, struct cpufreq_policy *policy);
+extern int sysfs_modify_freq_policy_min(unsigned int cpu, unsigned long min_freq);
+extern int sysfs_modify_freq_policy_max(unsigned int cpu, unsigned long max_freq);
+extern int sysfs_modify_freq_policy_governor(unsigned int cpu, char *governor);
 extern int sysfs_set_frequency(unsigned int cpu, unsigned long target_frequency);
 
+/* CPUidle - Cstates */
+extern unsigned long sysfs_get_cstate_latency(unsigned int cpu, unsigned int cstate);
+extern unsigned long sysfs_get_cstate_usage(unsigned int cpu, unsigned int cstate);
+extern unsigned long long sysfs_get_cstate_time(unsigned int cpu, unsigned int cstate);
+extern char * sysfs_get_cstate_name(unsigned int cpu, unsigned int cstate);
+extern char * sysfs_get_cstate_desc(unsigned int cpu, unsigned int cstate);
+extern int sysfs_get_cstate_count(unsigned int cpu);
+
+extern char * sysfs_get_cpuidle_governor(void);
+extern char * sysfs_get_cpuidle_driver(void);
+
+
+
diff --git a/utils/cpuidle-info.c b/utils/cpuidle-info.c
new file mode 100644
index 0000000..b874732
--- /dev/null
+++ b/utils/cpuidle-info.c
@@ -0,0 +1,305 @@
+/*
+ *  (C) 2004-2009  Dominik Brodowski <linux@dominikbrodowski.de>
+ *
+ *  Licensed under the terms of the GNU GPL License version 2.
+ */
+
+
+#include <unistd.h>
+#include <stdio.h>
+#include <errno.h>
+#include <stdlib.h>
+#include <string.h>
+#include <libintl.h>
+#include <locale.h>
+
+#include <getopt.h>
+
+#include "cpuidle.h"
+
+#define _(String) gettext (String)
+#define gettext_noop(String) String
+#define N_(String) gettext_noop (String)
+
+#define LINE_LEN 10
+
+static unsigned int count_cpus(void)
+{
+	FILE *fp;
+	char value[LINE_LEN];
+	unsigned int ret = 0;
+	unsigned int cpunr = 0;
+
+	fp = fopen("/proc/stat", "r");
+	if(!fp) {
+		printf(gettext("Couldn't count the number of CPUs (%s: %s), assuming 1\n"), "/proc/stat", strerror(errno));
+		return 1;
+	}
+
+	while (!feof(fp)) {
+		if (!fgets(value, LINE_LEN, fp))
+			continue;
+		value[LINE_LEN - 1] = '\0';
+		if (strlen(value) < (LINE_LEN - 2))
+			continue;
+		if (strstr(value, "cpu "))
+			continue;
+		if (sscanf(value, "cpu%d ", &cpunr) != 1)
+			continue;
+		if (cpunr > ret)
+			ret = cpunr;
+	}
+	fclose(fp);
+
+	/* cpu count starts from 0, on error return 1 (UP) */
+	return (ret+1);
+}
+
+static void cpuidle_cpu_output(unsigned int cpu, int verbose)
+{
+	int cstates, cstate;
+	char *tmp;
+
+	printf(gettext ("Analyzing CPU %d:\n"), cpu);
+
+	cstates = cpuidle_get_cstate_count(cpu);
+	if (cstates == 0) {
+		printf(gettext("CPU %u: No C-states\n"), cpu);
+		return;
+	}
+	else if (cstates <= 0) {
+		printf(gettext("CPU %u: Can't read C-state info\n"), cpu);
+		return;
+	}
+	tmp = cpuidle_get_cstate_name(cpu, cstates - 1);
+	if (!tmp) {
+		printf(gettext("Could not determine max C-state %u\n"),
+		       cstates - 1);
+		return;
+	}
+
+	printf("Cstates: %d\n", cstates);
+
+	printf(gettext("Available C-states:"));
+	for (cstate = 1; cstate < cstates; cstate++) {
+		tmp = cpuidle_get_cstate_name(cpu, cstate);
+		if (!tmp)
+			continue;
+		printf(" %s", tmp);
+		free(tmp);
+	}
+	printf("\n");
+
+	if (!verbose)
+		return;
+
+	for (cstate = 1; cstate < cstates; cstate++) {
+		tmp = cpuidle_get_cstate_name(cpu, cstate);
+		if (!tmp)
+			continue;
+		printf("%s:\n", tmp);
+		free(tmp);
+
+		tmp = cpuidle_get_cstate_desc(cpu, cstate);
+		if (!tmp)
+			continue;
+		printf("Flags/Description: %s\n", tmp);
+		free(tmp);
+
+		printf(gettext("Latency: %lu\n"),
+		       cpuidle_get_cstate_latency(cpu, cstate));
+		printf(gettext("Usage: %lu\n"),
+		       cpuidle_get_cstate_usage(cpu, cstate));
+		printf(gettext("Duration: %llu\n"),
+		       cpuidle_get_cstate_time(cpu, cstate));
+	}
+	printf("\n");
+}
+
+static void cpuidle_general_output(void)
+{
+	char *tmp;
+
+	tmp = cpuidle_get_driver();
+	if (!tmp) {
+		printf(gettext ("Could not determine cpuidle driver\n"));
+		return;
+	}
+
+	printf(gettext("CPUidle driver: %s\n"), tmp);
+	free (tmp);
+
+	tmp = cpuidle_get_governor();
+	if (!tmp) {
+		printf(gettext ("Could not determine cpuidle governor\n"));
+		return;
+	}
+
+	printf(gettext("CPUidle governor: %s\n"), tmp);
+	free (tmp);
+}
+
+static void proc_cpuidle_cpu_output(unsigned int cpu)
+{
+	long max_allowed_cstate = 2000000000;
+	int cstates, cstate;
+
+	cstates = cpuidle_get_cstate_count(cpu);
+	if (cstates == 0) {
+		/*
+		 * Go on and print same useless info as you'd see with
+		 * cat /proc/acpi/processor/../power
+		 *	printf(gettext("CPU %u: No C-states available\n"), cpu);
+		 *	return;
+		 */
+	}
+	else if (cstates <= 0) {
+		printf(gettext("CPU %u: Can't read C-state info\n"), cpu);
+		return;
+	}
+	/* printf("Cstates: %d\n", cstates); */
+
+	printf(gettext("active state:            C0\n"));
+	printf(gettext("max_cstate:              C%u\n"), cstates-1);
+	printf(gettext("maximum allowed latency: %lu usec\n"), max_allowed_cstate);
+	printf(gettext("states:\t\n"));
+	for (cstate = 1; cstate < cstates; cstate++) {
+		printf("    C%d:                  "
+		       "type[C%d] ", cstate, cstate);
+		printf(gettext("promotion[--] demotion[--] "));
+		printf(gettext("latency[%03lu] "),
+		       cpuidle_get_cstate_latency(cpu, cstate));
+		printf(gettext("usage[%08lu] "),
+		       cpuidle_get_cstate_usage(cpu, cstate));
+		printf(gettext("duration[%020Lu] \n"),
+		       cpuidle_get_cstate_time(cpu, cstate));
+	}
+}
+
+static void proc_cpuidle_output(void)
+{
+	unsigned int cpu, nr_cpus;
+
+	nr_cpus = count_cpus();
+	/* printf("CPUs: %d\n", nr_cpus); */
+	for (cpu = 0; cpu < nr_cpus; cpu++) {
+		proc_cpuidle_cpu_output(cpu);
+	}
+}
+
+/* --freq / -f */
+
+
+static void print_header(void) {
+	printf(PACKAGE " " VERSION ": cpufreq-info (C) Thomas Renninger <trenn@suse.de> 2010\n");
+	printf(gettext ("Report errors and bugs to %s, please.\n"), PACKAGE_BUGREPORT);
+}
+
+static void print_help(void) {
+	printf(gettext ("Usage: cpuidle-info [options]\n"));
+	printf(gettext ("Options:\n"));
+	printf(gettext ("  -c CPU, --cpu CPU    CPU number which information shall be determined about\n"));
+	printf(gettext ("  -s, --silent         Only show general C-state information\n"));
+	printf(gettext ("  -o, --proc           Prints out information like provided by the /proc/acpi/processor/*/power\n"
+	       "                       interface in older kernels\n"));
+	printf(gettext ("  -h, --help           Prints out this screen\n"));
+
+	printf("\n");
+}
+
+static struct option info_opts[] = {
+	{ .name="cpu",		.has_arg=required_argument,	.flag=NULL,	.val='c'},
+	{ .name="silent",	.has_arg=no_argument,		.flag=NULL,	.val='s'},
+	{ .name="proc",		.has_arg=no_argument,		.flag=NULL,	.val='o'},
+	{ .name="help",		.has_arg=no_argument,		.flag=NULL,	.val='h'},
+};
+
+static inline void cpuidle_exit(int fail)
+{
+	print_header();
+	print_help();
+	exit(EXIT_FAILURE);
+}
+
+
+int main(int argc, char **argv) {
+	extern char *optarg;
+	extern int optind, opterr, optopt;
+	int ret = 0, cont = 1, output_param = 0, verbose = 1;
+	unsigned int cpu = 0, cpu_defined = 0, nr_cpus;
+
+	setlocale(LC_ALL, "");
+	textdomain (PACKAGE);
+
+	do {
+		ret = getopt_long(argc, argv, "c:hos", info_opts, NULL);
+		if (ret == -1)
+			break;
+		switch (ret) {
+		case '?':
+			output_param = '?';
+			cont = 0;
+			break;
+		case 'h':
+			output_param = 'h';
+			cont = 0;
+			break;
+		case 's':
+			verbose = 0;
+			break;
+		case -1:
+			cont = 0;
+			break;
+		case 'o':
+			if (output_param) {
+				output_param = -1;
+				cont = 0;
+				break;
+			}
+			output_param = ret;
+			break;
+		case 'c':
+			if (cpu_defined) {
+				output_param = -1;
+				cont = 0;
+				break;
+			}
+			if ((sscanf(optarg, "%d ", &cpu)) != 1) {
+				output_param = '?';
+				cont = 0;
+			}
+			cpu_defined = 1;
+			break;
+		}
+	} while(cont);
+
+	switch (output_param) {
+	case -1:
+		printf(gettext ("You can't specify more than one --cpu parameter and/or\n"
+		       "more than one output-specific argument\n"));
+		cpuidle_exit(EXIT_FAILURE);
+	case '?':
+		printf(gettext ("invalid or unknown argument\n"));
+		cpuidle_exit(EXIT_FAILURE);
+	case 'h':
+		cpuidle_exit(EXIT_SUCCESS);
+	case 'o':
+		if (cpu_defined)
+			proc_cpuidle_cpu_output(cpu);
+		else
+			proc_cpuidle_output();
+		break;
+	case 0:
+		cpuidle_general_output();
+		if (cpu_defined)
+			cpuidle_cpu_output(cpu, verbose);
+		else {
+			printf("\n");
+			nr_cpus = count_cpus();
+			for (cpu = 0; cpu < nr_cpus; cpu++)
+				cpuidle_cpu_output(cpu, verbose);
+		}
+		break;
+	}
+	return (EXIT_SUCCESS);
+}
-- 
1.6.4.2


^ permalink raw reply related	[flat|nested] 13+ messages in thread

* [PATCH 3/4] cpufrequtils: Rename libcpufreq to libcpupower
  2010-09-23 15:30 Rename cpufrequtils into cpupowerutils and provide some basic cpuidle functionality Thomas Renninger
  2010-09-23 15:30 ` [PATCH 1/4] cpufrequtils: Prepare for non-cpufreq related power features by renaming files Thomas Renninger
  2010-09-23 15:30 ` [PATCH 2/4] cpufrequtils: Add cpuidle-info tool with some cstate library functions Thomas Renninger
@ 2010-09-23 15:30 ` Thomas Renninger
  2010-09-23 15:30 ` [PATCH 4/4] cpufrequtils: Rename the project/package into cpupowerutils Thomas Renninger
  2010-09-25 12:37 ` Rename cpufrequtils into cpupowerutils and provide some basic cpuidle functionality Dominik Brodowski
  4 siblings, 0 replies; 13+ messages in thread
From: Thomas Renninger @ 2010-09-23 15:30 UTC (permalink / raw)
  To: cpufreq, linux; +Cc: trenn

But still provide libcpufreq which links against the new libcpupower now.

Like that binaries linking with -lcpufreq will still work.
Getting this (-l cpufreq) deprecated should work at packaging layer then.

Signed-off-by: Thomas Renninger <trenn@suse.de>
CC: linux@dominikbrodowski.net
CC: cpufreq@vger.kernel.org
---
 Makefile |   30 +++++++++++++++++++++---------
 1 files changed, 21 insertions(+), 9 deletions(-)

diff --git a/Makefile b/Makefile
index 07637ed..089fe33 100644
--- a/Makefile
+++ b/Makefile
@@ -152,7 +152,7 @@ endif
 
 # the actual make rules
 
-all: ccdv libcpufreq utils $(COMPILE_NLS) $(COMPILE_BENCH)
+all: ccdv libcpupower utils $(COMPILE_NLS) $(COMPILE_BENCH)
 
 ccdv: build/ccdv
 build/ccdv: build/ccdv.c
@@ -162,17 +162,25 @@ build/ccdv: build/ccdv.c
 lib/%.o: $(LIB_SRC) $(LIB_HEADERS) build/ccdv
 	$(QUIET) $(CC) $(CPPFLAGS) $(CFLAGS) -fPIC -o $@ -c lib/$*.c
 
-libcpufreq.so.$(LIB_MAJ): $(LIB_OBJS)
-	$(QUIET) $(CC) -shared $(CPPFLAGS) $(CFLAGS) $(LDFLAGS) -o $@ \
-		-Wl,-soname,libcpufreq.so.$(LIB_MIN) $(LIB_OBJS)
+libcpupower.so.$(LIB_MAJ): $(LIB_OBJS)
+	$(CC) -shared $(CPPFLAGS) $(CFLAGS) $(LDFLAGS) -o $@ \
+		-Wl,-soname,libcpupower.so.$(LIB_MIN) $(LIB_OBJS)
+	@ln -sf $@ libcpupower.so
+	@ln -sf $@ libcpupower.so.$(LIB_MIN)
+
+# Still Provide the old lib, but apps should get fixed to
+# not link against it anymore 
+libcpufreq.so.$(LIB_MAJ): libcpupower.so.$(LIB_MAJ)
+	$(CC) -shared $(CPPFLAGS) $(CFLAGS) $(LDFLAGS) -o $@ \
+		-Wl,-soname,libcpufreq.so.$(LIB_MIN) -l cpupower -L .
 	@ln -sf $@ libcpufreq.so
 	@ln -sf $@ libcpufreq.so.$(LIB_MIN)
 
-libcpufreq: libcpufreq.so.$(LIB_MAJ)
+libcpupower: libcpupower.so.$(LIB_MAJ) libcpufreq.so.$(LIB_MAJ)
 
-$(UTIL_BINS): libcpufreq.so.$(LIB_MAJ) $(UTIL_SRC)
+$(UTIL_BINS): libcpupower.so.$(LIB_MAJ) $(UTIL_SRC)
 	$(QUIET) $(CC) $(CPPFLAGS) $(CFLAGS) -I. -I./lib/ -c $@.c -o $@.o
-	$(QUIET) $(CC) $(CFLAGS) $(LDFLAGS) -L. -o $@ $@.o -lcpufreq
+	$(QUIET) $(CC) $(CFLAGS) $(LDFLAGS) -L. -o $@ $@.o -lcpupower
 	$(QUIET) $(STRIPCMD) $@
 
 utils: $(UTIL_BINS)
@@ -196,13 +204,14 @@ update-gmo: po/$(PACKAGE).pot
 		msgfmt --statistics -o po/$$HLANG.gmo po/$$HLANG.po; \
 	done;
 
-compile-bench: libcpufreq
+compile-bench: libcpupower
 	@V=$(V) confdir=$(confdir) $(MAKE) -C bench
 
 clean:
 	-find . \( -not -type d \) -and \( -name '*~' -o -name '*.[oas]' \) -type f -print \
 	 | xargs rm -f
 	-rm -f $(UTIL_BINS)
+	-rm -f libcpupower.so*
 	-rm -f libcpufreq.so*
 	-rm -f build/ccdv
 	-rm -rf po/*.gmo po/*.pot
@@ -211,9 +220,11 @@ clean:
 
 install-lib:
 	$(INSTALL) -d $(DESTDIR)${libdir}
+	$(CP) libcpupower.so* $(DESTDIR)${libdir}/
 	$(CP) libcpufreq.so* $(DESTDIR)${libdir}/
 	$(INSTALL) -d $(DESTDIR)${includedir}
 	$(INSTALL_DATA) lib/cpufreq.h $(DESTDIR)${includedir}/cpufreq.h
+	$(INSTALL_DATA) lib/cpuidle.h $(DESTDIR)${includedir}/cpuidle.h
 
 install-tools:
 	$(INSTALL) -d $(DESTDIR)${bindir}
@@ -237,6 +248,7 @@ install-bench:
 install: all install-lib install-tools install-man $(INSTALL_NLS) $(INSTALL_BENCH)
 
 uninstall:
+	- rm -f $(DESTDIR)${libdir}/libcpupower.*
 	- rm -f $(DESTDIR)${libdir}/libcpufreq.*
 	- rm -f $(DESTDIR)${includedir}/cpufreq.h
 	- rm -f $(DESTDIR)${bindir}/cpufreq-set
@@ -249,5 +261,5 @@ uninstall:
 		rm -f $(DESTDIR)${localedir}/$$HLANG/LC_MESSAGES/cpufrequtils.mo; \
 	  done;
 
-.PHONY: all utils libcpufreq ccdv update-po update-gmo install-lib install-tools install-man install-gmo install uninstall \
+.PHONY: all utils libcpupower ccdv update-po update-gmo install-lib install-tools install-man install-gmo install uninstall \
 	clean 
-- 
1.6.4.2


^ permalink raw reply related	[flat|nested] 13+ messages in thread

* [PATCH 4/4] cpufrequtils: Rename the project/package into cpupowerutils
  2010-09-23 15:30 Rename cpufrequtils into cpupowerutils and provide some basic cpuidle functionality Thomas Renninger
                   ` (2 preceding siblings ...)
  2010-09-23 15:30 ` [PATCH 3/4] cpufrequtils: Rename libcpufreq to libcpupower Thomas Renninger
@ 2010-09-23 15:30 ` Thomas Renninger
  2010-09-25 12:37 ` Rename cpufrequtils into cpupowerutils and provide some basic cpuidle functionality Dominik Brodowski
  4 siblings, 0 replies; 13+ messages in thread
From: Thomas Renninger @ 2010-09-23 15:30 UTC (permalink / raw)
  To: cpufreq, linux; +Cc: trenn

Signed-off-by: Thomas Renninger <trenn@suse.de>
CC: linux@dominikbrodowski.net
CC: cpufreq@vger.kernel.org
---
 Makefile |   12 ++++++------
 1 files changed, 6 insertions(+), 6 deletions(-)

diff --git a/Makefile b/Makefile
index 089fe33..a268264 100644
--- a/Makefile
+++ b/Makefile
@@ -1,4 +1,4 @@
-# Makefile for cpufrequtils
+# Makefile for cpupowerutils
 #
 # Copyright (C) 2005,2006 Dominik Brodowski <linux@dominikbrodowski.net>
 #
@@ -51,7 +51,7 @@ VERSION =			008
 LIB_MAJ=			0.0.0
 LIB_MIN=			0
 
-PACKAGE =			cpufrequtils
+PACKAGE =			cpupowerutils
 PACKAGE_BUGREPORT =		cpufreq@vger.kernel.org
 LANGUAGES = 			de fr it cs pt
 
@@ -66,7 +66,7 @@ mandir ?=	/usr/man
 includedir ?=	/usr/include
 libdir ?=	/usr/lib
 localedir ?=	/usr/share/locale
-docdir ?=       /usr/share/doc/packages/cpufrequtils
+docdir ?=       /usr/share/doc/packages/cpupowerutils
 confdir ?=      /etc/
 
 # Toolchain: what tools do we use, and what options do they need:
@@ -237,8 +237,8 @@ install-man:
 install-gmo:
 	$(INSTALL) -d $(DESTDIR)${localedir}
 	for HLANG in $(LANGUAGES); do \
-		echo '$(INSTALL_DATA) -D po/$$HLANG.gmo $(DESTDIR)${localedir}/$$HLANG/LC_MESSAGES/cpufrequtils.mo'; \
-		$(INSTALL_DATA) -D po/$$HLANG.gmo $(DESTDIR)${localedir}/$$HLANG/LC_MESSAGES/cpufrequtils.mo; \
+		echo '$(INSTALL_DATA) -D po/$$HLANG.gmo $(DESTDIR)${localedir}/$$HLANG/LC_MESSAGES/cpupowerutils.mo'; \
+		$(INSTALL_DATA) -D po/$$HLANG.gmo $(DESTDIR)${localedir}/$$HLANG/LC_MESSAGES/cpupowerutils.mo; \
 	done;
 
 install-bench:
@@ -258,7 +258,7 @@ uninstall:
 	- rm -f $(DESTDIR)${mandir}/man1/cpufreq-set.1
 	- rm -f $(DESTDIR)${mandir}/man1/cpufreq-info.1
 	- for HLANG in $(LANGUAGES); do \
-		rm -f $(DESTDIR)${localedir}/$$HLANG/LC_MESSAGES/cpufrequtils.mo; \
+		rm -f $(DESTDIR)${localedir}/$$HLANG/LC_MESSAGES/cpupowerutils.mo; \
 	  done;
 
 .PHONY: all utils libcpupower ccdv update-po update-gmo install-lib install-tools install-man install-gmo install uninstall \
-- 
1.6.4.2


^ permalink raw reply related	[flat|nested] 13+ messages in thread

* Re: Rename cpufrequtils into cpupowerutils and provide some basic cpuidle functionality
  2010-09-23 15:30 Rename cpufrequtils into cpupowerutils and provide some basic cpuidle functionality Thomas Renninger
                   ` (3 preceding siblings ...)
  2010-09-23 15:30 ` [PATCH 4/4] cpufrequtils: Rename the project/package into cpupowerutils Thomas Renninger
@ 2010-09-25 12:37 ` Dominik Brodowski
  2010-09-28 11:06   ` Thomas Renninger
  4 siblings, 1 reply; 13+ messages in thread
From: Dominik Brodowski @ 2010-09-25 12:37 UTC (permalink / raw)
  To: Thomas Renninger; +Cc: cpufreq

Hey,

On Thu, Sep 23, 2010 at 05:30:06PM +0200, Thomas Renninger wrote:
> here my latest patchset.

Thanks.

> If this isn't totally wrong, I'd appreciate if you could
> push these already (into a separate branch for now?)

Applied into the "cpupowerutils" branch, and pushed that to

git://git.kernel.org/pub/scm/utils/kernel/cpufreq/cpufrequtils.git 

I split up one patch into two parts, and added two patches on top. Let me
know what you think about this.

> I do not want to pollute other lists for now.
> If you accept this and I did some further testing, packaging,
> cleanup, etc., I'd like to announce this work on some more lists
> (lesswatts, linux-pm, acpi, ...).

Sounds good.

Best,
	Dominik

^ permalink raw reply	[flat|nested] 13+ messages in thread

* Re: Rename cpufrequtils into cpupowerutils and provide some basic cpuidle functionality
  2010-09-25 12:37 ` Rename cpufrequtils into cpupowerutils and provide some basic cpuidle functionality Dominik Brodowski
@ 2010-09-28 11:06   ` Thomas Renninger
  2010-09-28 11:13     ` [PATCH 1/3] cpupowerutuils: Jump to version 010 Thomas Renninger
                       ` (2 more replies)
  0 siblings, 3 replies; 13+ messages in thread
From: Thomas Renninger @ 2010-09-28 11:06 UTC (permalink / raw)
  To: Dominik Brodowski; +Cc: cpufreq

On Saturday 25 September 2010 14:37:10 Dominik Brodowski wrote:
> Hey,
> 
> On Thu, Sep 23, 2010 at 05:30:06PM +0200, Thomas Renninger wrote:
> > here my latest patchset.
> 
> Thanks.
Thank you!

> > If this isn't totally wrong, I'd appreciate if you could
> > push these already (into a separate branch for now?)
> 
> Applied into the "cpupowerutils" branch, and pushed that to
> 
> git://git.kernel.org/pub/scm/utils/kernel/cpufreq/cpufrequtils.git 
> 
> I split up one patch into two parts, and added two patches on top. Let me
> know what you think about this.
Absolutely fine.

I packaged cpupowerutils, this time with a proper split of library
and devel packages.
I then got these packages:
cpupowerutils
cpupowerutils-bench
libcpupower0
libcpupower-devel
and the obsolete one (should get removed as soon as
no app is linking against -lcpufreq anymore):
libcpufreq0

Whoever wants to have a look or try out these packages,
they can be found here, built against all kind of SUSE distros
(Factory, 11.3, 11.2, 11.1, SLE_11, SLE11_SP1 - x86_64 and i386):
http://software.opensuse.org/search?q=cpupower

I found some minor bugs/enhancements, will post them in a minute.

Comments, suggestions, etc. are very welcome.

Thanks,

        Thomas

^ permalink raw reply	[flat|nested] 13+ messages in thread

* [PATCH 1/3] cpupowerutuils: Jump to version 010
  2010-09-28 11:06   ` Thomas Renninger
@ 2010-09-28 11:13     ` Thomas Renninger
  2010-10-02 10:34       ` Dominik Brodowski
  2010-09-28 11:13     ` [PATCH 2/3] cpupowerutils: Use sbindir for binaries that need root privileges Thomas Renninger
  2010-09-28 11:13     ` [PATCH 3/3] cpupowerutils: cpufreq-bench must link against libcpupower Thomas Renninger
  2 siblings, 1 reply; 13+ messages in thread
From: Thomas Renninger @ 2010-09-28 11:13 UTC (permalink / raw)
  To: linux; +Cc: Thomas Renninger, cpufreq

Jump from version 008 to 010.
Theoretically there could still be an cpufrequtils update to 009, but even
if not, having a gap to show there were quite some changes is a good idea.

Signed-off-by: Thomas Renninger <trenn@suse.de>
CC: linux@dominikbrodowski.net
CC: cpufreq@vger.kernel.org
---
 Makefile |    2 +-
 1 files changed, 1 insertions(+), 1 deletions(-)

diff --git a/Makefile b/Makefile
index 5bcd0e0..a53b440 100644
--- a/Makefile
+++ b/Makefile
@@ -47,7 +47,7 @@ DESTDIR ?=
 # Package-related definitions. Distributions can modify the version
 # and _should_ modify the PACKAGE_BUGREPORT definition
 
-VERSION =			008
+VERSION =			010
 LIB_MAJ=			0.0.0
 LIB_MIN=			0
 
-- 
1.6.4.2


^ permalink raw reply related	[flat|nested] 13+ messages in thread

* [PATCH 2/3] cpupowerutils: Use sbindir for binaries that need root privileges
  2010-09-28 11:06   ` Thomas Renninger
  2010-09-28 11:13     ` [PATCH 1/3] cpupowerutuils: Jump to version 010 Thomas Renninger
@ 2010-09-28 11:13     ` Thomas Renninger
  2010-10-02 10:35       ` Dominik Brodowski
  2010-09-28 11:13     ` [PATCH 3/3] cpupowerutils: cpufreq-bench must link against libcpupower Thomas Renninger
  2 siblings, 1 reply; 13+ messages in thread
From: Thomas Renninger @ 2010-09-28 11:13 UTC (permalink / raw)
  To: linux; +Cc: Thomas Renninger, cpufreq

cpufreq-aperf:
   - Must be run as root or it exits with a related error message.
   - It should not be used by any scripts

cpufreq-set:
I am not sure whether above is true for cpufreq-set as well.
I expect it always must be called as root and thus should be in sbindir.


Signed-off-by: Thomas Renninger <trenn@suse.de>
CC: linux@dominikbrodowski.net
CC: cpufreq@vger.kernel.org
---
 Makefile |   10 +++++++---
 1 files changed, 7 insertions(+), 3 deletions(-)

diff --git a/Makefile b/Makefile
index a53b440..865c9f8 100644
--- a/Makefile
+++ b/Makefile
@@ -228,7 +228,11 @@ install-lib:
 
 install-tools:
 	$(INSTALL) -d $(DESTDIR)${bindir}
-	$(INSTALL_PROGRAM) $(UTIL_BINS) $(DESTDIR)${bindir}
+	$(INSTALL_PROGRAM) utils/cpufreq-info utils/cpuidle-info \
+                  $(DESTDIR)${bindir}
+	$(INSTALL) -d $(DESTDIR)${sbindir}
+	$(INSTALL_PROGRAM) utils/cpufreq-set utils/cpufreq-aperf \
+                  $(DESTDIR)${sbindir}
 
 install-man:
 	$(INSTALL_DATA) -D man/cpufreq-set.1 $(DESTDIR)${mandir}/man1/cpufreq-set.1
@@ -251,9 +255,9 @@ uninstall:
 	- rm -f $(DESTDIR)${libdir}/libcpupower.*
 	- rm -f $(DESTDIR)${libdir}/libcpufreq.*
 	- rm -f $(DESTDIR)${includedir}/cpufreq.h
-	- rm -f $(DESTDIR)${bindir}/cpufreq-set
+	- rm -f $(DESTDIR)${sbindir}/cpufreq-set
 	- rm -f $(DESTDIR)${bindir}/cpufreq-info
-	- rm -f $(DESTDIR)${bindir}/cpufreq-aperf
+	- rm -f $(DESTDIR)${sbindir}/cpufreq-aperf
 	- rm -f $(DESTDIR)${bindir}/cpuidle-info
 	- rm -f $(DESTDIR)${mandir}/man1/cpufreq-set.1
 	- rm -f $(DESTDIR)${mandir}/man1/cpufreq-info.1
-- 
1.6.4.2


^ permalink raw reply related	[flat|nested] 13+ messages in thread

* [PATCH 3/3] cpupowerutils: cpufreq-bench must link against libcpupower
  2010-09-28 11:06   ` Thomas Renninger
  2010-09-28 11:13     ` [PATCH 1/3] cpupowerutuils: Jump to version 010 Thomas Renninger
  2010-09-28 11:13     ` [PATCH 2/3] cpupowerutils: Use sbindir for binaries that need root privileges Thomas Renninger
@ 2010-09-28 11:13     ` Thomas Renninger
  2010-10-02 10:36       ` Dominik Brodowski
  2 siblings, 1 reply; 13+ messages in thread
From: Thomas Renninger @ 2010-09-28 11:13 UTC (permalink / raw)
  To: linux; +Cc: Thomas Renninger, cpufreq

Signed-off-by: Thomas Renninger <trenn@suse.de>
CC: linux@dominikbrodowski.net
CC: cpufreq@vger.kernel.org
---
 bench/Makefile |    2 +-
 1 files changed, 1 insertions(+), 1 deletions(-)

diff --git a/bench/Makefile b/bench/Makefile
index 3d8fa21..9f3b195 100644
--- a/bench/Makefile
+++ b/bench/Makefile
@@ -1,4 +1,4 @@
-LIBS = -L../ -lm -lcpufreq
+LIBS = -L../ -lm -lcpupower
 
 OBJS = main.o parse.o system.o benchmark.o
 CFLAGS += -D_GNU_SOURCE -I../lib -DDEFAULT_CONFIG_FILE=\"$(confdir)/cpufreq-bench.conf\"
-- 
1.6.4.2


^ permalink raw reply related	[flat|nested] 13+ messages in thread

* Re: [PATCH 1/3] cpupowerutuils: Jump to version 010
  2010-09-28 11:13     ` [PATCH 1/3] cpupowerutuils: Jump to version 010 Thomas Renninger
@ 2010-10-02 10:34       ` Dominik Brodowski
  0 siblings, 0 replies; 13+ messages in thread
From: Dominik Brodowski @ 2010-10-02 10:34 UTC (permalink / raw)
  To: Thomas Renninger; +Cc: cpufreq

On Tue, Sep 28, 2010 at 01:13:26PM +0200, Thomas Renninger wrote:
> Jump from version 008 to 010.
> Theoretically there could still be an cpufrequtils update to 009, but even
> if not, having a gap to show there were quite some changes is a good idea.

NAK. VERSION is only updated to a new major version on a release. I changed
VERSION to 9p1 (for 9-pre1) instead.

Best,
	Dominik

^ permalink raw reply	[flat|nested] 13+ messages in thread

* Re: [PATCH 2/3] cpupowerutils: Use sbindir for binaries that need root privileges
  2010-09-28 11:13     ` [PATCH 2/3] cpupowerutils: Use sbindir for binaries that need root privileges Thomas Renninger
@ 2010-10-02 10:35       ` Dominik Brodowski
  0 siblings, 0 replies; 13+ messages in thread
From: Dominik Brodowski @ 2010-10-02 10:35 UTC (permalink / raw)
  To: Thomas Renninger; +Cc: cpufreq

On Tue, Sep 28, 2010 at 01:13:27PM +0200, Thomas Renninger wrote:
> cpufreq-aperf:
>    - Must be run as root or it exits with a related error message.
>    - It should not be used by any scripts
> 
> cpufreq-set:
> I am not sure whether above is true for cpufreq-set as well.
> I expect it always must be called as root and thus should be in sbindir.

Applied, thanks.

	Dominik

^ permalink raw reply	[flat|nested] 13+ messages in thread

* Re: [PATCH 3/3] cpupowerutils: cpufreq-bench must link against libcpupower
  2010-09-28 11:13     ` [PATCH 3/3] cpupowerutils: cpufreq-bench must link against libcpupower Thomas Renninger
@ 2010-10-02 10:36       ` Dominik Brodowski
  0 siblings, 0 replies; 13+ messages in thread
From: Dominik Brodowski @ 2010-10-02 10:36 UTC (permalink / raw)
  To: Thomas Renninger; +Cc: cpufreq

Applied, thanks.

On Tue, Sep 28, 2010 at 01:13:28PM +0200, Thomas Renninger wrote:
> Signed-off-by: Thomas Renninger <trenn@suse.de>
> CC: linux@dominikbrodowski.net
> CC: cpufreq@vger.kernel.org
> ---
>  bench/Makefile |    2 +-
>  1 files changed, 1 insertions(+), 1 deletions(-)
> 
> diff --git a/bench/Makefile b/bench/Makefile
> index 3d8fa21..9f3b195 100644
> --- a/bench/Makefile
> +++ b/bench/Makefile
> @@ -1,4 +1,4 @@
> -LIBS = -L../ -lm -lcpufreq
> +LIBS = -L../ -lm -lcpupower
>  
>  OBJS = main.o parse.o system.o benchmark.o
>  CFLAGS += -D_GNU_SOURCE -I../lib -DDEFAULT_CONFIG_FILE=\"$(confdir)/cpufreq-bench.conf\"
> -- 
> 1.6.4.2
> 
> --
> To unsubscribe from this list: send the line "unsubscribe cpufreq" in
> the body of a message to majordomo@vger.kernel.org
> More majordomo info at  http://vger.kernel.org/majordomo-info.html

^ permalink raw reply	[flat|nested] 13+ messages in thread

end of thread, other threads:[~2010-10-02 10:36 UTC | newest]

Thread overview: 13+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2010-09-23 15:30 Rename cpufrequtils into cpupowerutils and provide some basic cpuidle functionality Thomas Renninger
2010-09-23 15:30 ` [PATCH 1/4] cpufrequtils: Prepare for non-cpufreq related power features by renaming files Thomas Renninger
2010-09-23 15:30 ` [PATCH 2/4] cpufrequtils: Add cpuidle-info tool with some cstate library functions Thomas Renninger
2010-09-23 15:30 ` [PATCH 3/4] cpufrequtils: Rename libcpufreq to libcpupower Thomas Renninger
2010-09-23 15:30 ` [PATCH 4/4] cpufrequtils: Rename the project/package into cpupowerutils Thomas Renninger
2010-09-25 12:37 ` Rename cpufrequtils into cpupowerutils and provide some basic cpuidle functionality Dominik Brodowski
2010-09-28 11:06   ` Thomas Renninger
2010-09-28 11:13     ` [PATCH 1/3] cpupowerutuils: Jump to version 010 Thomas Renninger
2010-10-02 10:34       ` Dominik Brodowski
2010-09-28 11:13     ` [PATCH 2/3] cpupowerutils: Use sbindir for binaries that need root privileges Thomas Renninger
2010-10-02 10:35       ` Dominik Brodowski
2010-09-28 11:13     ` [PATCH 3/3] cpupowerutils: cpufreq-bench must link against libcpupower Thomas Renninger
2010-10-02 10:36       ` Dominik Brodowski

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox