^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1) // SPDX-License-Identifier: GPL-2.0-only
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3) * (C) 2004-2009 Dominik Brodowski <linux@dominikbrodowski.de>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 6)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 7) #include <stdio.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 8) #include <errno.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 9) #include <stdlib.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 10) #include <string.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 11) #include <sys/types.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 12) #include <sys/stat.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 13) #include <fcntl.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 14) #include <unistd.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 15)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 16) #include "cpufreq.h"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 17) #include "cpupower_intern.h"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 18)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 19) /* CPUFREQ sysfs access **************************************************/
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 20)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 21) /* helper function to read file from /sys into given buffer */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 22) /* fname is a relative path under "cpuX/cpufreq" dir */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 23) static unsigned int sysfs_cpufreq_read_file(unsigned int cpu, const char *fname,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 24) char *buf, size_t buflen)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 25) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 26) char path[SYSFS_PATH_MAX];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 27)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 28) snprintf(path, sizeof(path), PATH_TO_CPU "cpu%u/cpufreq/%s",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 29) cpu, fname);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 30) return cpupower_read_sysfs(path, buf, buflen);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 31) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 32)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 33) /* helper function to write a new value to a /sys file */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 34) /* fname is a relative path under "cpuX/cpufreq" dir */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 35) static unsigned int sysfs_cpufreq_write_file(unsigned int cpu,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 36) const char *fname,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 37) const char *value, size_t len)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 38) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 39) char path[SYSFS_PATH_MAX];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 40) int fd;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 41) ssize_t numwrite;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 42)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 43) snprintf(path, sizeof(path), PATH_TO_CPU "cpu%u/cpufreq/%s",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 44) cpu, fname);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 45)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 46) fd = open(path, O_WRONLY);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 47) if (fd == -1)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 48) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 49)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 50) numwrite = write(fd, value, len);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 51) if (numwrite < 1) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 52) close(fd);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 53) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 54) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 55)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 56) close(fd);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 57)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 58) return (unsigned int) numwrite;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 59) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 60)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 61) /* read access to files which contain one numeric value */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 62)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 63) enum cpufreq_value {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 64) CPUINFO_CUR_FREQ,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 65) CPUINFO_MIN_FREQ,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 66) CPUINFO_MAX_FREQ,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 67) CPUINFO_LATENCY,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 68) SCALING_CUR_FREQ,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 69) SCALING_MIN_FREQ,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 70) SCALING_MAX_FREQ,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 71) STATS_NUM_TRANSITIONS,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 72) MAX_CPUFREQ_VALUE_READ_FILES
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 73) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 74)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 75) static const char *cpufreq_value_files[MAX_CPUFREQ_VALUE_READ_FILES] = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 76) [CPUINFO_CUR_FREQ] = "cpuinfo_cur_freq",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 77) [CPUINFO_MIN_FREQ] = "cpuinfo_min_freq",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 78) [CPUINFO_MAX_FREQ] = "cpuinfo_max_freq",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 79) [CPUINFO_LATENCY] = "cpuinfo_transition_latency",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 80) [SCALING_CUR_FREQ] = "scaling_cur_freq",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 81) [SCALING_MIN_FREQ] = "scaling_min_freq",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 82) [SCALING_MAX_FREQ] = "scaling_max_freq",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 83) [STATS_NUM_TRANSITIONS] = "stats/total_trans"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 84) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 85)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 86)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 87) static unsigned long sysfs_cpufreq_get_one_value(unsigned int cpu,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 88) enum cpufreq_value which)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 89) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 90) unsigned long value;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 91) unsigned int len;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 92) char linebuf[MAX_LINE_LEN];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 93) char *endp;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 94)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 95) if (which >= MAX_CPUFREQ_VALUE_READ_FILES)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 96) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 97)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 98) len = sysfs_cpufreq_read_file(cpu, cpufreq_value_files[which],
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 99) linebuf, sizeof(linebuf));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 100)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 101) if (len == 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 102) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 103)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 104) value = strtoul(linebuf, &endp, 0);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 105)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 106) if (endp == linebuf || errno == ERANGE)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 107) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 108)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 109) return value;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 110) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 111)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 112) /* read access to files which contain one string */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 113)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 114) enum cpufreq_string {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 115) SCALING_DRIVER,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 116) SCALING_GOVERNOR,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 117) MAX_CPUFREQ_STRING_FILES
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 118) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 119)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 120) static const char *cpufreq_string_files[MAX_CPUFREQ_STRING_FILES] = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 121) [SCALING_DRIVER] = "scaling_driver",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 122) [SCALING_GOVERNOR] = "scaling_governor",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 123) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 124)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 125)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 126) static char *sysfs_cpufreq_get_one_string(unsigned int cpu,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 127) enum cpufreq_string which)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 128) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 129) char linebuf[MAX_LINE_LEN];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 130) char *result;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 131) unsigned int len;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 132)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 133) if (which >= MAX_CPUFREQ_STRING_FILES)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 134) return NULL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 135)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 136) len = sysfs_cpufreq_read_file(cpu, cpufreq_string_files[which],
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 137) linebuf, sizeof(linebuf));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 138) if (len == 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 139) return NULL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 140)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 141) result = strdup(linebuf);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 142) if (result == NULL)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 143) return NULL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 144)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 145) if (result[strlen(result) - 1] == '\n')
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 146) result[strlen(result) - 1] = '\0';
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 147)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 148) return result;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 149) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 150)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 151) /* write access */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 152)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 153) enum cpufreq_write {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 154) WRITE_SCALING_MIN_FREQ,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 155) WRITE_SCALING_MAX_FREQ,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 156) WRITE_SCALING_GOVERNOR,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 157) WRITE_SCALING_SET_SPEED,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 158) MAX_CPUFREQ_WRITE_FILES
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 159) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 160)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 161) static const char *cpufreq_write_files[MAX_CPUFREQ_WRITE_FILES] = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 162) [WRITE_SCALING_MIN_FREQ] = "scaling_min_freq",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 163) [WRITE_SCALING_MAX_FREQ] = "scaling_max_freq",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 164) [WRITE_SCALING_GOVERNOR] = "scaling_governor",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 165) [WRITE_SCALING_SET_SPEED] = "scaling_setspeed",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 166) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 167)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 168) static int sysfs_cpufreq_write_one_value(unsigned int cpu,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 169) enum cpufreq_write which,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 170) const char *new_value, size_t len)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 171) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 172) if (which >= MAX_CPUFREQ_WRITE_FILES)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 173) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 174)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 175) if (sysfs_cpufreq_write_file(cpu, cpufreq_write_files[which],
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 176) new_value, len) != len)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 177) return -ENODEV;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 178)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 179) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 180) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 181)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 182) unsigned long cpufreq_get_freq_kernel(unsigned int cpu)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 183) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 184) return sysfs_cpufreq_get_one_value(cpu, SCALING_CUR_FREQ);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 185) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 186)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 187) unsigned long cpufreq_get_freq_hardware(unsigned int cpu)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 188) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 189) return sysfs_cpufreq_get_one_value(cpu, CPUINFO_CUR_FREQ);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 190) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 191)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 192) unsigned long cpufreq_get_transition_latency(unsigned int cpu)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 193) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 194) return sysfs_cpufreq_get_one_value(cpu, CPUINFO_LATENCY);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 195) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 196)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 197) int cpufreq_get_hardware_limits(unsigned int cpu,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 198) unsigned long *min,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 199) unsigned long *max)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 200) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 201) if ((!min) || (!max))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 202) return -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 203)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 204) *min = sysfs_cpufreq_get_one_value(cpu, CPUINFO_MIN_FREQ);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 205) if (!*min)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 206) return -ENODEV;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 207)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 208) *max = sysfs_cpufreq_get_one_value(cpu, CPUINFO_MAX_FREQ);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 209) if (!*max)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 210) return -ENODEV;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 211)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 212) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 213) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 214)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 215) char *cpufreq_get_driver(unsigned int cpu)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 216) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 217) return sysfs_cpufreq_get_one_string(cpu, SCALING_DRIVER);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 218) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 219)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 220) void cpufreq_put_driver(char *ptr)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 221) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 222) if (!ptr)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 223) return;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 224) free(ptr);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 225) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 226)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 227) struct cpufreq_policy *cpufreq_get_policy(unsigned int cpu)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 228) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 229) struct cpufreq_policy *policy;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 230)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 231) policy = malloc(sizeof(struct cpufreq_policy));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 232) if (!policy)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 233) return NULL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 234)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 235) policy->governor = sysfs_cpufreq_get_one_string(cpu, SCALING_GOVERNOR);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 236) if (!policy->governor) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 237) free(policy);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 238) return NULL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 239) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 240) policy->min = sysfs_cpufreq_get_one_value(cpu, SCALING_MIN_FREQ);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 241) policy->max = sysfs_cpufreq_get_one_value(cpu, SCALING_MAX_FREQ);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 242) if ((!policy->min) || (!policy->max)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 243) free(policy->governor);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 244) free(policy);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 245) return NULL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 246) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 247)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 248) return policy;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 249) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 250)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 251) void cpufreq_put_policy(struct cpufreq_policy *policy)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 252) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 253) if ((!policy) || (!policy->governor))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 254) return;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 255)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 256) free(policy->governor);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 257) policy->governor = NULL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 258) free(policy);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 259) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 260)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 261) struct cpufreq_available_governors *cpufreq_get_available_governors(unsigned
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 262) int cpu)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 263) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 264) struct cpufreq_available_governors *first = NULL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 265) struct cpufreq_available_governors *current = NULL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 266) char linebuf[MAX_LINE_LEN];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 267) unsigned int pos, i;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 268) unsigned int len;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 269)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 270) len = sysfs_cpufreq_read_file(cpu, "scaling_available_governors",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 271) linebuf, sizeof(linebuf));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 272) if (len == 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 273) return NULL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 274)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 275) pos = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 276) for (i = 0; i < len; i++) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 277) if (linebuf[i] == ' ' || linebuf[i] == '\n') {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 278) if (i - pos < 2)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 279) continue;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 280) if (current) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 281) current->next = malloc(sizeof(*current));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 282) if (!current->next)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 283) goto error_out;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 284) current = current->next;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 285) } else {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 286) first = malloc(sizeof(*first));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 287) if (!first)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 288) return NULL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 289) current = first;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 290) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 291) current->first = first;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 292) current->next = NULL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 293)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 294) current->governor = malloc(i - pos + 1);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 295) if (!current->governor)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 296) goto error_out;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 297)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 298) memcpy(current->governor, linebuf + pos, i - pos);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 299) current->governor[i - pos] = '\0';
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 300) pos = i + 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 301) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 302) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 303)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 304) return first;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 305)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 306) error_out:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 307) while (first) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 308) current = first->next;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 309) if (first->governor)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 310) free(first->governor);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 311) free(first);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 312) first = current;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 313) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 314) return NULL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 315) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 316)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 317) void cpufreq_put_available_governors(struct cpufreq_available_governors *any)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 318) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 319) struct cpufreq_available_governors *tmp, *next;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 320)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 321) if (!any)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 322) return;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 323)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 324) tmp = any->first;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 325) while (tmp) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 326) next = tmp->next;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 327) if (tmp->governor)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 328) free(tmp->governor);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 329) free(tmp);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 330) tmp = next;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 331) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 332) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 333)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 334)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 335) struct cpufreq_available_frequencies
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 336) *cpufreq_get_available_frequencies(unsigned int cpu)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 337) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 338) struct cpufreq_available_frequencies *first = NULL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 339) struct cpufreq_available_frequencies *current = NULL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 340) char one_value[SYSFS_PATH_MAX];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 341) char linebuf[MAX_LINE_LEN];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 342) unsigned int pos, i;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 343) unsigned int len;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 344)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 345) len = sysfs_cpufreq_read_file(cpu, "scaling_available_frequencies",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 346) linebuf, sizeof(linebuf));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 347) if (len == 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 348) return NULL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 349)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 350) pos = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 351) for (i = 0; i < len; i++) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 352) if (linebuf[i] == ' ' || linebuf[i] == '\n') {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 353) if (i - pos < 2)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 354) continue;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 355) if (i - pos >= SYSFS_PATH_MAX)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 356) goto error_out;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 357) if (current) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 358) current->next = malloc(sizeof(*current));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 359) if (!current->next)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 360) goto error_out;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 361) current = current->next;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 362) } else {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 363) first = malloc(sizeof(*first));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 364) if (!first)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 365) return NULL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 366) current = first;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 367) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 368) current->first = first;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 369) current->next = NULL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 370)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 371) memcpy(one_value, linebuf + pos, i - pos);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 372) one_value[i - pos] = '\0';
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 373) if (sscanf(one_value, "%lu", ¤t->frequency) != 1)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 374) goto error_out;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 375)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 376) pos = i + 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 377) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 378) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 379)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 380) return first;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 381)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 382) error_out:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 383) while (first) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 384) current = first->next;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 385) free(first);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 386) first = current;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 387) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 388) return NULL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 389) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 390)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 391) struct cpufreq_available_frequencies
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 392) *cpufreq_get_boost_frequencies(unsigned int cpu)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 393) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 394) struct cpufreq_available_frequencies *first = NULL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 395) struct cpufreq_available_frequencies *current = NULL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 396) char one_value[SYSFS_PATH_MAX];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 397) char linebuf[MAX_LINE_LEN];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 398) unsigned int pos, i;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 399) unsigned int len;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 400)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 401) len = sysfs_cpufreq_read_file(cpu, "scaling_boost_frequencies",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 402) linebuf, sizeof(linebuf));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 403) if (len == 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 404) return NULL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 405)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 406) pos = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 407) for (i = 0; i < len; i++) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 408) if (linebuf[i] == ' ' || linebuf[i] == '\n') {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 409) if (i - pos < 2)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 410) continue;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 411) if (i - pos >= SYSFS_PATH_MAX)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 412) goto error_out;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 413) if (current) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 414) current->next = malloc(sizeof(*current));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 415) if (!current->next)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 416) goto error_out;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 417) current = current->next;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 418) } else {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 419) first = malloc(sizeof(*first));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 420) if (!first)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 421) return NULL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 422) current = first;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 423) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 424) current->first = first;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 425) current->next = NULL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 426)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 427) memcpy(one_value, linebuf + pos, i - pos);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 428) one_value[i - pos] = '\0';
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 429) if (sscanf(one_value, "%lu", ¤t->frequency) != 1)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 430) goto error_out;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 431)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 432) pos = i + 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 433) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 434) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 435)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 436) return first;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 437)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 438) error_out:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 439) while (first) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 440) current = first->next;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 441) free(first);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 442) first = current;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 443) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 444) return NULL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 445) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 446)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 447) void cpufreq_put_available_frequencies(struct cpufreq_available_frequencies *any)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 448) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 449) struct cpufreq_available_frequencies *tmp, *next;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 450)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 451) if (!any)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 452) return;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 453)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 454) tmp = any->first;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 455) while (tmp) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 456) next = tmp->next;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 457) free(tmp);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 458) tmp = next;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 459) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 460) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 461)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 462) void cpufreq_put_boost_frequencies(struct cpufreq_available_frequencies *any)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 463) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 464) cpufreq_put_available_frequencies(any);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 465) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 466)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 467) static struct cpufreq_affected_cpus *sysfs_get_cpu_list(unsigned int cpu,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 468) const char *file)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 469) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 470) struct cpufreq_affected_cpus *first = NULL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 471) struct cpufreq_affected_cpus *current = NULL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 472) char one_value[SYSFS_PATH_MAX];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 473) char linebuf[MAX_LINE_LEN];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 474) unsigned int pos, i;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 475) unsigned int len;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 476)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 477) len = sysfs_cpufreq_read_file(cpu, file, linebuf, sizeof(linebuf));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 478) if (len == 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 479) return NULL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 480)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 481) pos = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 482) for (i = 0; i < len; i++) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 483) if (i == len || linebuf[i] == ' ' || linebuf[i] == '\n') {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 484) if (i - pos < 1)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 485) continue;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 486) if (i - pos >= SYSFS_PATH_MAX)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 487) goto error_out;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 488) if (current) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 489) current->next = malloc(sizeof(*current));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 490) if (!current->next)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 491) goto error_out;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 492) current = current->next;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 493) } else {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 494) first = malloc(sizeof(*first));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 495) if (!first)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 496) return NULL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 497) current = first;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 498) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 499) current->first = first;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 500) current->next = NULL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 501)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 502) memcpy(one_value, linebuf + pos, i - pos);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 503) one_value[i - pos] = '\0';
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 504)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 505) if (sscanf(one_value, "%u", ¤t->cpu) != 1)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 506) goto error_out;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 507)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 508) pos = i + 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 509) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 510) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 511)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 512) return first;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 513)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 514) error_out:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 515) while (first) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 516) current = first->next;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 517) free(first);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 518) first = current;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 519) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 520) return NULL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 521) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 522)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 523) struct cpufreq_affected_cpus *cpufreq_get_affected_cpus(unsigned int cpu)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 524) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 525) return sysfs_get_cpu_list(cpu, "affected_cpus");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 526) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 527)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 528) void cpufreq_put_affected_cpus(struct cpufreq_affected_cpus *any)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 529) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 530) struct cpufreq_affected_cpus *tmp, *next;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 531)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 532) if (!any)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 533) return;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 534)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 535) tmp = any->first;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 536) while (tmp) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 537) next = tmp->next;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 538) free(tmp);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 539) tmp = next;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 540) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 541) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 542)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 543)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 544) struct cpufreq_affected_cpus *cpufreq_get_related_cpus(unsigned int cpu)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 545) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 546) return sysfs_get_cpu_list(cpu, "related_cpus");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 547) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 548)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 549) void cpufreq_put_related_cpus(struct cpufreq_affected_cpus *any)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 550) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 551) cpufreq_put_affected_cpus(any);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 552) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 553)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 554) static int verify_gov(char *new_gov, char *passed_gov)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 555) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 556) unsigned int i, j = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 557)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 558) if (!passed_gov || (strlen(passed_gov) > 19))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 559) return -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 560)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 561) strncpy(new_gov, passed_gov, 20);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 562) for (i = 0; i < 20; i++) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 563) if (j) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 564) new_gov[i] = '\0';
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 565) continue;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 566) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 567) if ((new_gov[i] >= 'a') && (new_gov[i] <= 'z'))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 568) continue;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 569)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 570) if ((new_gov[i] >= 'A') && (new_gov[i] <= 'Z'))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 571) continue;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 572)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 573) if (new_gov[i] == '-')
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 574) continue;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 575)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 576) if (new_gov[i] == '_')
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 577) continue;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 578)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 579) if (new_gov[i] == '\0') {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 580) j = 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 581) continue;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 582) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 583) return -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 584) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 585) new_gov[19] = '\0';
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 586) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 587) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 588)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 589) int cpufreq_set_policy(unsigned int cpu, struct cpufreq_policy *policy)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 590) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 591) char min[SYSFS_PATH_MAX];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 592) char max[SYSFS_PATH_MAX];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 593) char gov[SYSFS_PATH_MAX];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 594) int ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 595) unsigned long old_min;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 596) int write_max_first;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 597)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 598) if (!policy || !(policy->governor))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 599) return -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 600)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 601) if (policy->max < policy->min)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 602) return -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 603)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 604) if (verify_gov(gov, policy->governor))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 605) return -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 606)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 607) snprintf(min, SYSFS_PATH_MAX, "%lu", policy->min);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 608) snprintf(max, SYSFS_PATH_MAX, "%lu", policy->max);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 609)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 610) old_min = sysfs_cpufreq_get_one_value(cpu, SCALING_MIN_FREQ);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 611) write_max_first = (old_min && (policy->max < old_min) ? 0 : 1);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 612)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 613) if (write_max_first) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 614) ret = sysfs_cpufreq_write_one_value(cpu, WRITE_SCALING_MAX_FREQ,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 615) max, strlen(max));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 616) if (ret)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 617) return ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 618) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 619)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 620) ret = sysfs_cpufreq_write_one_value(cpu, WRITE_SCALING_MIN_FREQ, min,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 621) strlen(min));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 622) if (ret)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 623) return ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 624)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 625) if (!write_max_first) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 626) ret = sysfs_cpufreq_write_one_value(cpu, WRITE_SCALING_MAX_FREQ,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 627) max, strlen(max));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 628) if (ret)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 629) return ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 630) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 631)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 632) return sysfs_cpufreq_write_one_value(cpu, WRITE_SCALING_GOVERNOR,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 633) gov, strlen(gov));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 634) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 635)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 636)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 637) int cpufreq_modify_policy_min(unsigned int cpu, unsigned long min_freq)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 638) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 639) char value[SYSFS_PATH_MAX];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 640)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 641) snprintf(value, SYSFS_PATH_MAX, "%lu", min_freq);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 642)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 643) return sysfs_cpufreq_write_one_value(cpu, WRITE_SCALING_MIN_FREQ,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 644) value, strlen(value));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 645) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 646)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 647)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 648) int cpufreq_modify_policy_max(unsigned int cpu, unsigned long max_freq)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 649) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 650) char value[SYSFS_PATH_MAX];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 651)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 652) snprintf(value, SYSFS_PATH_MAX, "%lu", max_freq);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 653)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 654) return sysfs_cpufreq_write_one_value(cpu, WRITE_SCALING_MAX_FREQ,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 655) value, strlen(value));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 656) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 657)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 658) int cpufreq_modify_policy_governor(unsigned int cpu, char *governor)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 659) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 660) char new_gov[SYSFS_PATH_MAX];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 661)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 662) if ((!governor) || (strlen(governor) > 19))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 663) return -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 664)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 665) if (verify_gov(new_gov, governor))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 666) return -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 667)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 668) return sysfs_cpufreq_write_one_value(cpu, WRITE_SCALING_GOVERNOR,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 669) new_gov, strlen(new_gov));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 670) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 671)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 672) int cpufreq_set_frequency(unsigned int cpu, unsigned long target_frequency)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 673) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 674) struct cpufreq_policy *pol = cpufreq_get_policy(cpu);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 675) char userspace_gov[] = "userspace";
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 676) char freq[SYSFS_PATH_MAX];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 677) int ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 678)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 679) if (!pol)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 680) return -ENODEV;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 681)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 682) if (strncmp(pol->governor, userspace_gov, 9) != 0) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 683) ret = cpufreq_modify_policy_governor(cpu, userspace_gov);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 684) if (ret) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 685) cpufreq_put_policy(pol);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 686) return ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 687) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 688) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 689)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 690) cpufreq_put_policy(pol);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 691)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 692) snprintf(freq, SYSFS_PATH_MAX, "%lu", target_frequency);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 693)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 694) return sysfs_cpufreq_write_one_value(cpu, WRITE_SCALING_SET_SPEED,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 695) freq, strlen(freq));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 696) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 697)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 698) struct cpufreq_stats *cpufreq_get_stats(unsigned int cpu,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 699) unsigned long long *total_time)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 700) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 701) struct cpufreq_stats *first = NULL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 702) struct cpufreq_stats *current = NULL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 703) char one_value[SYSFS_PATH_MAX];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 704) char linebuf[MAX_LINE_LEN];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 705) unsigned int pos, i;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 706) unsigned int len;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 707)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 708) len = sysfs_cpufreq_read_file(cpu, "stats/time_in_state",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 709) linebuf, sizeof(linebuf));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 710) if (len == 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 711) return NULL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 712)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 713) *total_time = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 714) pos = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 715) for (i = 0; i < len; i++) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 716) if (i == strlen(linebuf) || linebuf[i] == '\n') {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 717) if (i - pos < 2)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 718) continue;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 719) if ((i - pos) >= SYSFS_PATH_MAX)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 720) goto error_out;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 721) if (current) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 722) current->next = malloc(sizeof(*current));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 723) if (!current->next)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 724) goto error_out;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 725) current = current->next;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 726) } else {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 727) first = malloc(sizeof(*first));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 728) if (!first)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 729) return NULL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 730) current = first;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 731) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 732) current->first = first;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 733) current->next = NULL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 734)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 735) memcpy(one_value, linebuf + pos, i - pos);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 736) one_value[i - pos] = '\0';
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 737) if (sscanf(one_value, "%lu %llu",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 738) ¤t->frequency,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 739) ¤t->time_in_state) != 2)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 740) goto error_out;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 741)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 742) *total_time = *total_time + current->time_in_state;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 743) pos = i + 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 744) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 745) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 746)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 747) return first;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 748)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 749) error_out:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 750) while (first) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 751) current = first->next;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 752) free(first);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 753) first = current;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 754) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 755) return NULL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 756) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 757)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 758) void cpufreq_put_stats(struct cpufreq_stats *any)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 759) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 760) struct cpufreq_stats *tmp, *next;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 761)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 762) if (!any)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 763) return;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 764)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 765) tmp = any->first;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 766) while (tmp) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 767) next = tmp->next;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 768) free(tmp);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 769) tmp = next;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 770) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 771) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 772)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 773) unsigned long cpufreq_get_transitions(unsigned int cpu)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 774) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 775) return sysfs_cpufreq_get_one_value(cpu, STATS_NUM_TRANSITIONS);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 776) }