2 * (C) 2004-2009 Dominik Brodowski <linux@dominikbrodowski.de>
4 * Licensed under the terms of the GNU GPL License version 2.
13 #include <sys/types.h>
20 #define PATH_TO_CPU "/sys/devices/system/cpu/"
21 #define MAX_LINE_LEN 255
22 #define SYSFS_PATH_MAX 255
24 /* helper function to read file from /sys into given buffer */
25 /* fname is a relative path under "cpuX/cpufreq" dir */
26 unsigned int sysfs_read_file(unsigned int cpu, const char *fname, char *buf, size_t buflen)
28 char path[SYSFS_PATH_MAX];
32 snprintf(path, sizeof(path), PATH_TO_CPU "cpu%u/cpufreq/%s",
35 if ( ( fd = open(path, O_RDONLY) ) == -1 )
38 numread = read(fd, buf, buflen - 1);
51 /* helper function to write a new value to a /sys file */
52 /* fname is a relative path under "cpuX/cpufreq" dir */
53 unsigned int sysfs_write_file(unsigned int cpu, const char *fname, const char *value, size_t len)
55 char path[SYSFS_PATH_MAX];
59 snprintf(path, sizeof(path), PATH_TO_CPU "cpu%u/cpufreq/%s",
62 if ( ( fd = open(path, O_WRONLY) ) == -1 )
65 numwrite = write(fd, value, len);
77 /* read access to files which contain one numeric value */
87 STATS_NUM_TRANSITIONS,
88 ONDEMAND_UP_THRESHOLD,
89 ONDEMAND_SAMPLING_RATE,
90 ONDEMAND_SAMPLING_RATE_MIN,
91 ONDEMAND_SAMPLING_RATE_MAX,
92 ONDEMAND_IGNORE_NICE_LOAD,
96 static const char *value_files[MAX_VALUE_FILES] = {
97 [CPUINFO_CUR_FREQ] = "cpuinfo_cur_freq",
98 [CPUINFO_MIN_FREQ] = "cpuinfo_min_freq",
99 [CPUINFO_MAX_FREQ] = "cpuinfo_max_freq",
100 [CPUINFO_LATENCY] = "cpuinfo_transition_latency",
101 [SCALING_CUR_FREQ] = "scaling_cur_freq",
102 [SCALING_MIN_FREQ] = "scaling_min_freq",
103 [SCALING_MAX_FREQ] = "scaling_max_freq",
104 [STATS_NUM_TRANSITIONS] = "stats/total_trans",
105 [ONDEMAND_UP_THRESHOLD] = "ondemand/up_threshold",
106 [ONDEMAND_SAMPLING_RATE] = "ondemand/sampling_rate",
107 [ONDEMAND_SAMPLING_RATE_MIN] = "ondemand/sampling_rate_min",
108 [ONDEMAND_SAMPLING_RATE_MAX] = "ondemand/sampling_rate_max",
109 [ONDEMAND_IGNORE_NICE_LOAD] = "ondemand/ignore_nice_load"
113 static unsigned long sysfs_get_one_value(unsigned int cpu, unsigned int which)
117 char linebuf[MAX_LINE_LEN];
120 if ( which >= MAX_VALUE_FILES )
123 if ( ( len = sysfs_read_file(cpu, value_files[which], linebuf, sizeof(linebuf))) == 0 )
128 value = strtoul(linebuf, &endp, 0);
130 if ( endp == linebuf || errno == ERANGE )
136 /* read access to files which contain one string */
144 static const char *string_files[MAX_STRING_FILES] = {
145 [SCALING_DRIVER] = "scaling_driver",
146 [SCALING_GOVERNOR] = "scaling_governor",
150 static char * sysfs_get_one_string(unsigned int cpu, unsigned int which)
152 char linebuf[MAX_LINE_LEN];
156 if (which >= MAX_STRING_FILES)
159 if ( ( len = sysfs_read_file(cpu, string_files[which], linebuf, sizeof(linebuf))) == 0 )
164 if ( ( result = strdup(linebuf) ) == NULL )
167 if (result[strlen(result) - 1] == '\n')
168 result[strlen(result) - 1] = '\0';
176 WRITE_SCALING_MIN_FREQ,
177 WRITE_SCALING_MAX_FREQ,
178 WRITE_SCALING_GOVERNOR,
179 WRITE_SCALING_SET_SPEED,
180 WRITE_ONDEMAND_UP_THRESHOLD,
181 WRITE_ONDEMAND_SAMPLING_RATE,
182 WRITE_ONDEMAND_IGNORE_NICE_LOAD,
186 static const char *write_files[MAX_VALUE_FILES] = {
187 [WRITE_SCALING_MIN_FREQ] = "scaling_min_freq",
188 [WRITE_SCALING_MAX_FREQ] = "scaling_max_freq",
189 [WRITE_SCALING_GOVERNOR] = "scaling_governor",
190 [WRITE_SCALING_SET_SPEED] = "scaling_setspeed",
191 [WRITE_ONDEMAND_UP_THRESHOLD] = "ondemand/up_threshold",
192 [WRITE_ONDEMAND_SAMPLING_RATE] = "ondemand/sampling_rate",
193 [WRITE_ONDEMAND_IGNORE_NICE_LOAD] = "ondemand/ignore_nice_load"
196 static int sysfs_write_one_value(unsigned int cpu, unsigned int which,
197 const char *new_value, size_t len)
199 if (which >= MAX_WRITE_FILES)
202 if ( sysfs_write_file(cpu, write_files[which], new_value, len) != len )
209 int sysfs_cpu_exists(unsigned int cpu)
211 char file[SYSFS_PATH_MAX];
214 snprintf(file, SYSFS_PATH_MAX, PATH_TO_CPU "cpu%u/", cpu);
216 if ( stat(file, &statbuf) != 0 )
219 return S_ISDIR(statbuf.st_mode) ? 0 : -ENOSYS;
223 unsigned long sysfs_get_freq_kernel(unsigned int cpu)
225 return sysfs_get_one_value(cpu, SCALING_CUR_FREQ);
228 unsigned long sysfs_get_freq_hardware(unsigned int cpu)
230 return sysfs_get_one_value(cpu, CPUINFO_CUR_FREQ);
233 unsigned long sysfs_get_transition_latency(unsigned int cpu)
235 return sysfs_get_one_value(cpu, CPUINFO_LATENCY);
238 int sysfs_get_hardware_limits(unsigned int cpu,
242 if ((!min) || (!max))
245 *min = sysfs_get_one_value(cpu, CPUINFO_MIN_FREQ);
249 *max = sysfs_get_one_value(cpu, CPUINFO_MAX_FREQ);
256 char * sysfs_get_driver(unsigned int cpu) {
257 return sysfs_get_one_string(cpu, SCALING_DRIVER);
260 struct cpufreq_policy * sysfs_get_policy(unsigned int cpu) {
261 struct cpufreq_policy *policy;
263 policy = malloc(sizeof(struct cpufreq_policy));
267 policy->governor = sysfs_get_one_string(cpu, SCALING_GOVERNOR);
268 if (!policy->governor) {
272 policy->min = sysfs_get_one_value(cpu, SCALING_MIN_FREQ);
273 policy->max = sysfs_get_one_value(cpu, SCALING_MAX_FREQ);
274 if ((!policy->min) || (!policy->max)) {
275 free(policy->governor);
283 struct cpufreq_available_governors * sysfs_get_available_governors(unsigned int cpu) {
284 struct cpufreq_available_governors *first = NULL;
285 struct cpufreq_available_governors *current = NULL;
286 char linebuf[MAX_LINE_LEN];
290 if ( ( len = sysfs_read_file(cpu, "scaling_available_governors", linebuf, sizeof(linebuf))) == 0 )
296 for ( i = 0; i < len; i++ )
298 if ( linebuf[i] == ' ' || linebuf[i] == '\n' )
303 current->next = malloc(sizeof *current );
304 if ( ! current->next )
306 current = current->next;
308 first = malloc( sizeof *first );
313 current->first = first;
314 current->next = NULL;
316 current->governor = malloc(i - pos + 1);
317 if ( ! current->governor )
320 memcpy( current->governor, linebuf + pos, i - pos);
321 current->governor[i - pos] = '\0';
330 current = first->next;
331 if ( first->governor )
332 free( first->governor );
340 struct cpufreq_available_frequencies * sysfs_get_available_frequencies(unsigned int cpu) {
341 struct cpufreq_available_frequencies *first = NULL;
342 struct cpufreq_available_frequencies *current = NULL;
343 char one_value[SYSFS_PATH_MAX];
344 char linebuf[MAX_LINE_LEN];
348 if ( ( len = sysfs_read_file(cpu, "scaling_available_frequencies", linebuf, sizeof(linebuf))) == 0 )
354 for ( i = 0; i < len; i++ )
356 if ( linebuf[i] == ' ' || linebuf[i] == '\n' )
360 if ( i - pos >= SYSFS_PATH_MAX )
363 current->next = malloc(sizeof *current );
364 if ( ! current->next )
366 current = current->next;
368 first = malloc(sizeof *first );
373 current->first = first;
374 current->next = NULL;
376 memcpy(one_value, linebuf + pos, i - pos);
377 one_value[i - pos] = '\0';
378 if ( sscanf(one_value, "%lu", ¤t->frequency) != 1 )
389 current = first->next;
396 static struct cpufreq_affected_cpus * sysfs_get_cpu_list(unsigned int cpu,
398 struct cpufreq_affected_cpus *first = NULL;
399 struct cpufreq_affected_cpus *current = NULL;
400 char one_value[SYSFS_PATH_MAX];
401 char linebuf[MAX_LINE_LEN];
405 if ( ( len = sysfs_read_file(cpu, file, linebuf, sizeof(linebuf))) == 0 )
411 for ( i = 0; i < len; i++ )
413 if ( i == len || linebuf[i] == ' ' || linebuf[i] == '\n' )
417 if ( i - pos >= SYSFS_PATH_MAX )
420 current->next = malloc(sizeof *current);
421 if ( ! current->next )
423 current = current->next;
425 first = malloc(sizeof *first);
430 current->first = first;
431 current->next = NULL;
433 memcpy(one_value, linebuf + pos, i - pos);
434 one_value[i - pos] = '\0';
436 if ( sscanf(one_value, "%u", ¤t->cpu) != 1 )
447 current = first->next;
454 struct cpufreq_affected_cpus * sysfs_get_affected_cpus(unsigned int cpu) {
455 return sysfs_get_cpu_list(cpu, "affected_cpus");
458 struct cpufreq_affected_cpus * sysfs_get_related_cpus(unsigned int cpu) {
459 return sysfs_get_cpu_list(cpu, "related_cpus");
462 struct cpufreq_stats * sysfs_get_stats(unsigned int cpu, unsigned long long *total_time) {
463 struct cpufreq_stats *first = NULL;
464 struct cpufreq_stats *current = NULL;
465 char one_value[SYSFS_PATH_MAX];
466 char linebuf[MAX_LINE_LEN];
470 if ( ( len = sysfs_read_file(cpu, "stats/time_in_state", linebuf, sizeof(linebuf))) == 0 )
475 for ( i = 0; i < len; i++ )
477 if ( i == strlen(linebuf) || linebuf[i] == '\n' )
481 if ( (i - pos) >= SYSFS_PATH_MAX )
484 current->next = malloc(sizeof *current );
485 if ( ! current->next )
487 current = current->next;
489 first = malloc(sizeof *first );
494 current->first = first;
495 current->next = NULL;
497 memcpy(one_value, linebuf + pos, i - pos);
498 one_value[i - pos] = '\0';
499 if ( sscanf(one_value, "%lu %llu", ¤t->frequency, ¤t->time_in_state) != 2 )
502 *total_time = *total_time + current->time_in_state;
511 current = first->next;
518 unsigned long sysfs_get_transitions(unsigned int cpu)
520 return sysfs_get_one_value(cpu, STATS_NUM_TRANSITIONS);
523 static int verify_gov(char *new_gov, char *passed_gov)
527 if (!passed_gov || (strlen(passed_gov) > 19))
530 strncpy(new_gov, passed_gov, 20);
536 if ((new_gov[i] >= 'a') && (new_gov[i] <= 'z')) {
539 if ((new_gov[i] >= 'A') && (new_gov[i] <= 'Z')) {
542 if (new_gov[i] == '-') {
545 if (new_gov[i] == '_') {
548 if (new_gov[i] == '\0') {
558 int sysfs_modify_policy_governor(unsigned int cpu, char *governor)
560 char new_gov[SYSFS_PATH_MAX];
565 if (verify_gov(new_gov, governor))
568 return sysfs_write_one_value(cpu, WRITE_SCALING_GOVERNOR, new_gov, strlen(new_gov));
571 int sysfs_modify_policy_max(unsigned int cpu, unsigned long max_freq)
573 char value[SYSFS_PATH_MAX];
575 snprintf(value, SYSFS_PATH_MAX, "%lu", max_freq);
577 return sysfs_write_one_value(cpu, WRITE_SCALING_MAX_FREQ, value, strlen(value));
581 int sysfs_modify_policy_min(unsigned int cpu, unsigned long min_freq)
583 char value[SYSFS_PATH_MAX];
585 snprintf(value, SYSFS_PATH_MAX, "%lu", min_freq);
587 return sysfs_write_one_value(cpu, WRITE_SCALING_MIN_FREQ, value, strlen(value));
591 int sysfs_set_policy(unsigned int cpu, struct cpufreq_policy *policy)
593 char min[SYSFS_PATH_MAX];
594 char max[SYSFS_PATH_MAX];
595 char gov[SYSFS_PATH_MAX];
597 unsigned long old_min;
600 if (!policy || !(policy->governor))
603 if (policy->max < policy->min)
606 if (verify_gov(gov, policy->governor))
609 snprintf(min, SYSFS_PATH_MAX, "%lu", policy->min);
610 snprintf(max, SYSFS_PATH_MAX, "%lu", policy->max);
612 old_min = sysfs_get_one_value(cpu, SCALING_MIN_FREQ);
613 write_max_first = (old_min && (policy->max < old_min) ? 0 : 1);
615 if (write_max_first) {
616 ret = sysfs_write_one_value(cpu, WRITE_SCALING_MAX_FREQ, max, strlen(max));
621 ret = sysfs_write_one_value(cpu, WRITE_SCALING_MIN_FREQ, min, strlen(min));
625 if (!write_max_first) {
626 ret = sysfs_write_one_value(cpu, WRITE_SCALING_MAX_FREQ, max, strlen(max));
631 return sysfs_write_one_value(cpu, WRITE_SCALING_GOVERNOR, gov, strlen(gov));
634 int sysfs_set_frequency(unsigned int cpu, unsigned long target_frequency) {
635 struct cpufreq_policy *pol = sysfs_get_policy(cpu);
636 char userspace_gov[] = "userspace";
637 char freq[SYSFS_PATH_MAX];
643 if (strncmp(pol->governor, userspace_gov, 9) != 0) {
644 ret = sysfs_modify_policy_governor(cpu, userspace_gov);
646 cpufreq_put_policy(pol);
651 cpufreq_put_policy(pol);
653 snprintf(freq, SYSFS_PATH_MAX, "%lu", target_frequency);
655 return sysfs_write_one_value(cpu, WRITE_SCALING_SET_SPEED, freq, strlen(freq));
658 unsigned long sysfs_get_up_threshold(unsigned int cpu)
661 // char linebuf[MAX_LINE_LEN];
663 // if ( ( len = sysfs_read_file(cpu, "ondemand/up_threshold", linebuf, sizeof(linebuf))) == 0 )
667 // if ( ( result = strdup(linebuf) ) == NULL )
670 // if (result[strlen(result) - 1] == '\n')
671 // result[strlen(result) - 1] = '\0';
673 return sysfs_get_one_value(cpu, ONDEMAND_UP_THRESHOLD);
676 unsigned long sysfs_get_sampling_rate(unsigned int cpu)
678 return sysfs_get_one_value(cpu, ONDEMAND_SAMPLING_RATE);
681 int sysfs_set_up_threshold(unsigned int cpu, unsigned long target_up_threshold)
683 char upthreshold[SYSFS_PATH_MAX];
684 unsigned long upthreshold_target;
685 upthreshold_target = target_up_threshold;
686 if(upthreshold_target < 15)
687 upthreshold_target = 15;
688 if(upthreshold_target > 100)
689 upthreshold_target = 100;
690 snprintf(upthreshold, SYSFS_PATH_MAX, "%lu", upthreshold_target);
691 return sysfs_write_one_value(cpu, WRITE_ONDEMAND_UP_THRESHOLD, upthreshold, strlen(upthreshold));
694 int sysfs_set_sampling_rate(unsigned int cpu, unsigned long target_sampling_rate)
696 char samplingrate[SYSFS_PATH_MAX];
697 unsigned long samplingrate_min, samplingrate_max, samplingrate_target;
698 samplingrate_target = target_sampling_rate;
699 samplingrate_min = sysfs_get_one_value(cpu, ONDEMAND_SAMPLING_RATE_MIN);
700 samplingrate_max = sysfs_get_one_value(cpu, ONDEMAND_SAMPLING_RATE_MAX);
701 if(samplingrate_target < samplingrate_min)
702 samplingrate_target = samplingrate_min;
703 if(samplingrate_target > samplingrate_max)
704 samplingrate_target = samplingrate_max;
705 snprintf(samplingrate, SYSFS_PATH_MAX, "%lu", samplingrate_target);
706 return sysfs_write_one_value(cpu, WRITE_ONDEMAND_SAMPLING_RATE, samplingrate, strlen(samplingrate));
709 int sysfs_get_ignore_nice_load(unsigned int cpu)
711 char file[SYSFS_PATH_MAX];
715 snprintf(file, SYSFS_PATH_MAX, PATH_TO_CPU "cpu%u/cpufreq/ondemand/ignore_nice_load", cpu);
717 if ( stat(file, &statbuf) != 0 )
719 ret = (int) sysfs_get_one_value(cpu, ONDEMAND_IGNORE_NICE_LOAD);
723 int sysfs_set_ignore_nice_load(unsigned int cpu, int target_ignore_nice_load)
726 * echo "1" > /sys/devices/system/cpu/cpu0/cpufreq/ondemand/ignore_nice_load
727 * renice 1 `cat /syspart/applications/standby/background/tasks`
728 * renice 1 `ps | grep modest | cut -c1-5`
731 char file[SYSFS_PATH_MAX];
734 snprintf(file, SYSFS_PATH_MAX, PATH_TO_CPU "cpu%u/cpufreq/ondemand/ignore_nice_load", cpu);
736 if ( stat(file, &statbuf) != 0 )
739 if(target_ignore_nice_load)
740 return sysfs_write_one_value(cpu, WRITE_ONDEMAND_IGNORE_NICE_LOAD, "1", strlen("1"));
742 return sysfs_write_one_value(cpu, WRITE_ONDEMAND_IGNORE_NICE_LOAD, "0", strlen("0"));
746 int sysfs_get_SmartReflex()
748 char buf[MAX_LINE_LEN];
755 /* TODO add /sys/power/sr_vdd2_autocomp */
757 if ( stat("/sys/power/sr_vdd1_autocomp", &statbuf) != 0 )
760 if ( ( fd = open("/sys/power/sr_vdd1_autocomp", O_RDONLY) ) == -1 )
763 numread = read(fd, buf, MAX_LINE_LEN - 1);
773 value = strtoul(buf, &endp, 0);
775 if ( endp == buf || errno == ERANGE )
781 int sysfs_set_SmartReflex(int target_ignore_nice_load)
787 if ( stat("/sys/power/sr_vdd1_autocomp", &statbuf) != 0 )
789 if ( stat("/sys/power/sr_vdd2_autocomp", &statbuf) != 0 )
792 if ( ( fd = open("/sys/power/sr_vdd1_autocomp", O_WRONLY) ) == -1 )
795 if((target_ignore_nice_load==1) || (target_ignore_nice_load==3))
796 numwrite = write(fd, "1", strlen("1"));
798 numwrite = write(fd, "0", strlen("0"));
799 if ( numwrite < 1 ) {
806 if ( ( fd = open("/sys/power/sr_vdd2_autocomp", O_WRONLY) ) == -1 )
809 if((target_ignore_nice_load==2) || (target_ignore_nice_load==3))
810 numwrite = write(fd, "1", strlen("1"));
812 numwrite = write(fd, "0", strlen("0"));
813 if ( numwrite < 1 ) {