diff options
author | Thomas Renninger <trenn@suse.de> | 2013-06-28 09:34:30 -0400 |
---|---|---|
committer | Rafael J. Wysocki <rafael.j.wysocki@intel.com> | 2013-07-04 19:52:19 -0400 |
commit | 0924c369bc5492cf181a066fc2d459aa18ffa5ac (patch) | |
tree | da95fc8a244654d0ea196e5e483704566f45ce3d /tools | |
parent | f605181abd95a109031a23c67a824eb8e5dcfe67 (diff) |
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>
Diffstat (limited to 'tools')
-rw-r--r-- | tools/power/cpupower/utils/helpers/sysfs.c | 116 | ||||
-rw-r--r-- | tools/power/cpupower/utils/helpers/sysfs.h | 8 |
2 files changed, 123 insertions, 1 deletions
diff --git a/tools/power/cpupower/utils/helpers/sysfs.c b/tools/power/cpupower/utils/helpers/sysfs.c index 891f6710d026..5cdc600e8152 100644 --- a/tools/power/cpupower/utils/helpers/sysfs.c +++ b/tools/power/cpupower/utils/helpers/sysfs.c | |||
@@ -89,6 +89,33 @@ int sysfs_is_cpu_online(unsigned int cpu) | |||
89 | 89 | ||
90 | /* CPUidle idlestate specific /sys/devices/system/cpu/cpuX/cpuidle/ access */ | 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 | * helper function to read file from /sys into given buffer | 120 | * helper function to read file from /sys into given buffer |
94 | * fname is a relative path under "cpuX/cpuidle/stateX/" dir | 121 | * fname is a relative path under "cpuX/cpuidle/stateX/" dir |
@@ -121,6 +148,40 @@ unsigned int sysfs_idlestate_read_file(unsigned int cpu, unsigned int idlestate, | |||
121 | return (unsigned int) numread; | 148 | return (unsigned int) numread; |
122 | } | 149 | } |
123 | 150 | ||
151 | /* | ||
152 | * helper function to write a new value to a /sys file | ||
153 | * fname is a relative path under "../cpuX/cpuidle/cstateY/" dir | ||
154 | * | ||
155 | * Returns the number of bytes written or 0 on error | ||
156 | */ | ||
157 | static | ||
158 | unsigned int sysfs_idlestate_write_file(unsigned int cpu, | ||
159 | unsigned int idlestate, | ||
160 | const char *fname, | ||
161 | const char *value, size_t len) | ||
162 | { | ||
163 | char path[SYSFS_PATH_MAX]; | ||
164 | int fd; | ||
165 | ssize_t numwrite; | ||
166 | |||
167 | snprintf(path, sizeof(path), PATH_TO_CPU "cpu%u/cpuidle/state%u/%s", | ||
168 | cpu, idlestate, fname); | ||
169 | |||
170 | fd = open(path, O_WRONLY); | ||
171 | if (fd == -1) | ||
172 | return 0; | ||
173 | |||
174 | numwrite = write(fd, value, len); | ||
175 | if (numwrite < 1) { | ||
176 | close(fd); | ||
177 | return 0; | ||
178 | } | ||
179 | |||
180 | close(fd); | ||
181 | |||
182 | return (unsigned int) numwrite; | ||
183 | } | ||
184 | |||
124 | /* read access to files which contain one numeric value */ | 185 | /* read access to files which contain one numeric value */ |
125 | 186 | ||
126 | enum idlestate_value { | 187 | enum idlestate_value { |
@@ -128,6 +189,7 @@ enum idlestate_value { | |||
128 | IDLESTATE_POWER, | 189 | IDLESTATE_POWER, |
129 | IDLESTATE_LATENCY, | 190 | IDLESTATE_LATENCY, |
130 | IDLESTATE_TIME, | 191 | IDLESTATE_TIME, |
192 | IDLESTATE_DISABLE, | ||
131 | MAX_IDLESTATE_VALUE_FILES | 193 | MAX_IDLESTATE_VALUE_FILES |
132 | }; | 194 | }; |
133 | 195 | ||
@@ -136,6 +198,7 @@ static const char *idlestate_value_files[MAX_IDLESTATE_VALUE_FILES] = { | |||
136 | [IDLESTATE_POWER] = "power", | 198 | [IDLESTATE_POWER] = "power", |
137 | [IDLESTATE_LATENCY] = "latency", | 199 | [IDLESTATE_LATENCY] = "latency", |
138 | [IDLESTATE_TIME] = "time", | 200 | [IDLESTATE_TIME] = "time", |
201 | [IDLESTATE_DISABLE] = "disable", | ||
139 | }; | 202 | }; |
140 | 203 | ||
141 | static unsigned long long sysfs_idlestate_get_one_value(unsigned int cpu, | 204 | static unsigned long long sysfs_idlestate_get_one_value(unsigned int cpu, |
@@ -205,8 +268,59 @@ static char *sysfs_idlestate_get_one_string(unsigned int cpu, | |||
205 | return result; | 268 | return result; |
206 | } | 269 | } |
207 | 270 | ||
271 | /* | ||
272 | * Returns: | ||
273 | * 1 if disabled | ||
274 | * 0 if enabled | ||
275 | * -1 if idlestate is not available | ||
276 | * -2 if disabling is not supported by the kernel | ||
277 | */ | ||
278 | int sysfs_is_idlestate_disabled(unsigned int cpu, | ||
279 | unsigned int idlestate) | ||
280 | { | ||
281 | if (sysfs_get_idlestate_count(cpu) < idlestate) | ||
282 | return -1; | ||
283 | |||
284 | if (!sysfs_idlestate_file_exists(cpu, idlestate, | ||
285 | idlestate_value_files[IDLESTATE_DISABLE])) | ||
286 | return -2; | ||
287 | return sysfs_idlestate_get_one_value(cpu, idlestate, IDLESTATE_DISABLE); | ||
288 | } | ||
289 | |||
290 | /* | ||
291 | * Pass 1 as last argument to disable or 0 to enable the state | ||
292 | * Returns: | ||
293 | * 0 on success | ||
294 | * negative values on error, for example: | ||
295 | * -1 if idlestate is not available | ||
296 | * -2 if disabling is not supported by the kernel | ||
297 | * -3 No write access to disable/enable C-states | ||
298 | */ | ||
299 | int sysfs_idlestate_disable(unsigned int cpu, | ||
300 | unsigned int idlestate, | ||
301 | unsigned int disable) | ||
302 | { | ||
303 | char value[SYSFS_PATH_MAX]; | ||
304 | int bytes_written; | ||
305 | |||
306 | if (sysfs_get_idlestate_count(cpu) < idlestate) | ||
307 | return -1; | ||
308 | |||
309 | if (!sysfs_idlestate_file_exists(cpu, idlestate, | ||
310 | idlestate_value_files[IDLESTATE_DISABLE])) | ||
311 | return -2; | ||
312 | |||
313 | snprintf(value, SYSFS_PATH_MAX, "%u", disable); | ||
314 | |||
315 | bytes_written = sysfs_idlestate_write_file(cpu, idlestate, "disable", | ||
316 | value, sizeof(disable)); | ||
317 | if (bytes_written) | ||
318 | return 0; | ||
319 | return -3; | ||
320 | } | ||
321 | |||
208 | unsigned long sysfs_get_idlestate_latency(unsigned int cpu, | 322 | unsigned long sysfs_get_idlestate_latency(unsigned int cpu, |
209 | unsigned int idlestate) | 323 | unsigned int idlestate) |
210 | { | 324 | { |
211 | return sysfs_idlestate_get_one_value(cpu, idlestate, IDLESTATE_LATENCY); | 325 | return sysfs_idlestate_get_one_value(cpu, idlestate, IDLESTATE_LATENCY); |
212 | } | 326 | } |
diff --git a/tools/power/cpupower/utils/helpers/sysfs.h b/tools/power/cpupower/utils/helpers/sysfs.h index 0401a97a4cab..d28f11fedbda 100644 --- a/tools/power/cpupower/utils/helpers/sysfs.h +++ b/tools/power/cpupower/utils/helpers/sysfs.h | |||
@@ -7,8 +7,16 @@ | |||
7 | 7 | ||
8 | extern unsigned int sysfs_read_file(const char *path, char *buf, size_t buflen); | 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 | extern int sysfs_is_cpu_online(unsigned int cpu); | 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 | extern unsigned long sysfs_get_idlestate_latency(unsigned int cpu, | 20 | extern unsigned long sysfs_get_idlestate_latency(unsigned int cpu, |
13 | unsigned int idlestate); | 21 | unsigned int idlestate); |
14 | extern unsigned long sysfs_get_idlestate_usage(unsigned int cpu, | 22 | extern unsigned long sysfs_get_idlestate_usage(unsigned int cpu, |