Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

cpupower: Implement disabling of cstate interface

Latest kernel allows to disable C-states via:
/sys/devices/system/cpu/cpuX/cpuidle/stateY/disable

This patch provides lower level sysfs access functions to make use of
this interface. A later patch will implement the higher level stuff.

Signed-off-by: Thomas Renninger <trenn@suse.de>
Signed-off-by: Rafael J. Wysocki <rafael.j.wysocki@intel.com>

authored by

Thomas Renninger and committed by
Rafael J. Wysocki
0924c369 f605181a

+123 -1
+115 -1
tools/power/cpupower/utils/helpers/sysfs.c
··· 89 89 90 90 /* CPUidle idlestate specific /sys/devices/system/cpu/cpuX/cpuidle/ access */ 91 91 92 + 93 + /* CPUidle idlestate specific /sys/devices/system/cpu/cpuX/cpuidle/ access */ 94 + 95 + /* 96 + * helper function to check whether a file under "../cpuX/cpuidle/stateX/" dir 97 + * exists. 98 + * For example the functionality to disable c-states was introduced in later 99 + * kernel versions, this function can be used to explicitly check for this 100 + * feature. 101 + * 102 + * returns 1 if the file exists, 0 otherwise. 103 + */ 104 + unsigned int sysfs_idlestate_file_exists(unsigned int cpu, 105 + unsigned int idlestate, 106 + const char *fname) 107 + { 108 + char path[SYSFS_PATH_MAX]; 109 + struct stat statbuf; 110 + 111 + 112 + snprintf(path, sizeof(path), PATH_TO_CPU "cpu%u/cpuidle/state%u/%s", 113 + cpu, idlestate, fname); 114 + if (stat(path, &statbuf) != 0) 115 + return 0; 116 + return 1; 117 + } 118 + 92 119 /* 93 120 * helper function to read file from /sys into given buffer 94 121 * fname is a relative path under "cpuX/cpuidle/stateX/" dir ··· 148 121 return (unsigned int) numread; 149 122 } 150 123 124 + /* 125 + * helper function to write a new value to a /sys file 126 + * fname is a relative path under "../cpuX/cpuidle/cstateY/" dir 127 + * 128 + * Returns the number of bytes written or 0 on error 129 + */ 130 + static 131 + unsigned int sysfs_idlestate_write_file(unsigned int cpu, 132 + unsigned int idlestate, 133 + const char *fname, 134 + const char *value, size_t len) 135 + { 136 + char path[SYSFS_PATH_MAX]; 137 + int fd; 138 + ssize_t numwrite; 139 + 140 + snprintf(path, sizeof(path), PATH_TO_CPU "cpu%u/cpuidle/state%u/%s", 141 + cpu, idlestate, fname); 142 + 143 + fd = open(path, O_WRONLY); 144 + if (fd == -1) 145 + return 0; 146 + 147 + numwrite = write(fd, value, len); 148 + if (numwrite < 1) { 149 + close(fd); 150 + return 0; 151 + } 152 + 153 + close(fd); 154 + 155 + return (unsigned int) numwrite; 156 + } 157 + 151 158 /* read access to files which contain one numeric value */ 152 159 153 160 enum idlestate_value { ··· 189 128 IDLESTATE_POWER, 190 129 IDLESTATE_LATENCY, 191 130 IDLESTATE_TIME, 131 + IDLESTATE_DISABLE, 192 132 MAX_IDLESTATE_VALUE_FILES 193 133 }; 194 134 ··· 198 136 [IDLESTATE_POWER] = "power", 199 137 [IDLESTATE_LATENCY] = "latency", 200 138 [IDLESTATE_TIME] = "time", 139 + [IDLESTATE_DISABLE] = "disable", 201 140 }; 202 141 203 142 static unsigned long long sysfs_idlestate_get_one_value(unsigned int cpu, ··· 268 205 return result; 269 206 } 270 207 208 + /* 209 + * Returns: 210 + * 1 if disabled 211 + * 0 if enabled 212 + * -1 if idlestate is not available 213 + * -2 if disabling is not supported by the kernel 214 + */ 215 + int sysfs_is_idlestate_disabled(unsigned int cpu, 216 + unsigned int idlestate) 217 + { 218 + if (sysfs_get_idlestate_count(cpu) < idlestate) 219 + return -1; 220 + 221 + if (!sysfs_idlestate_file_exists(cpu, idlestate, 222 + idlestate_value_files[IDLESTATE_DISABLE])) 223 + return -2; 224 + return sysfs_idlestate_get_one_value(cpu, idlestate, IDLESTATE_DISABLE); 225 + } 226 + 227 + /* 228 + * Pass 1 as last argument to disable or 0 to enable the state 229 + * Returns: 230 + * 0 on success 231 + * negative values on error, for example: 232 + * -1 if idlestate is not available 233 + * -2 if disabling is not supported by the kernel 234 + * -3 No write access to disable/enable C-states 235 + */ 236 + int sysfs_idlestate_disable(unsigned int cpu, 237 + unsigned int idlestate, 238 + unsigned int disable) 239 + { 240 + char value[SYSFS_PATH_MAX]; 241 + int bytes_written; 242 + 243 + if (sysfs_get_idlestate_count(cpu) < idlestate) 244 + return -1; 245 + 246 + if (!sysfs_idlestate_file_exists(cpu, idlestate, 247 + idlestate_value_files[IDLESTATE_DISABLE])) 248 + return -2; 249 + 250 + snprintf(value, SYSFS_PATH_MAX, "%u", disable); 251 + 252 + bytes_written = sysfs_idlestate_write_file(cpu, idlestate, "disable", 253 + value, sizeof(disable)); 254 + if (bytes_written) 255 + return 0; 256 + return -3; 257 + } 258 + 271 259 unsigned long sysfs_get_idlestate_latency(unsigned int cpu, 272 - unsigned int idlestate) 260 + unsigned int idlestate) 273 261 { 274 262 return sysfs_idlestate_get_one_value(cpu, idlestate, IDLESTATE_LATENCY); 275 263 }
+8
tools/power/cpupower/utils/helpers/sysfs.h
··· 7 7 8 8 extern unsigned int sysfs_read_file(const char *path, char *buf, size_t buflen); 9 9 10 + extern unsigned int sysfs_idlestate_file_exists(unsigned int cpu, 11 + unsigned int idlestate, 12 + const char *fname); 13 + 10 14 extern int sysfs_is_cpu_online(unsigned int cpu); 11 15 16 + extern int sysfs_is_idlestate_disabled(unsigned int cpu, 17 + unsigned int idlestate); 18 + extern int sysfs_idlestate_disable(unsigned int cpu, unsigned int idlestate, 19 + unsigned int disable); 12 20 extern unsigned long sysfs_get_idlestate_latency(unsigned int cpu, 13 21 unsigned int idlestate); 14 22 extern unsigned long sysfs_get_idlestate_usage(unsigned int cpu,