mirror of
https://github.com/torvalds/linux.git
synced 2024-11-17 09:31:50 +00:00
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>
This commit is contained in:
parent
f605181abd
commit
0924c369bc
@ -89,6 +89,33 @@ int sysfs_is_cpu_online(unsigned int cpu)
|
||||
|
||||
/* CPUidle idlestate specific /sys/devices/system/cpu/cpuX/cpuidle/ access */
|
||||
|
||||
|
||||
/* CPUidle idlestate specific /sys/devices/system/cpu/cpuX/cpuidle/ access */
|
||||
|
||||
/*
|
||||
* helper function to check whether a file under "../cpuX/cpuidle/stateX/" dir
|
||||
* exists.
|
||||
* For example the functionality to disable c-states was introduced in later
|
||||
* kernel versions, this function can be used to explicitly check for this
|
||||
* feature.
|
||||
*
|
||||
* returns 1 if the file exists, 0 otherwise.
|
||||
*/
|
||||
unsigned int sysfs_idlestate_file_exists(unsigned int cpu,
|
||||
unsigned int idlestate,
|
||||
const char *fname)
|
||||
{
|
||||
char path[SYSFS_PATH_MAX];
|
||||
struct stat statbuf;
|
||||
|
||||
|
||||
snprintf(path, sizeof(path), PATH_TO_CPU "cpu%u/cpuidle/state%u/%s",
|
||||
cpu, idlestate, fname);
|
||||
if (stat(path, &statbuf) != 0)
|
||||
return 0;
|
||||
return 1;
|
||||
}
|
||||
|
||||
/*
|
||||
* helper function to read file from /sys into given buffer
|
||||
* 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,
|
||||
return (unsigned int) numread;
|
||||
}
|
||||
|
||||
/*
|
||||
* helper function to write a new value to a /sys file
|
||||
* fname is a relative path under "../cpuX/cpuidle/cstateY/" dir
|
||||
*
|
||||
* Returns the number of bytes written or 0 on error
|
||||
*/
|
||||
static
|
||||
unsigned int sysfs_idlestate_write_file(unsigned int cpu,
|
||||
unsigned int idlestate,
|
||||
const char *fname,
|
||||
const char *value, size_t len)
|
||||
{
|
||||
char path[SYSFS_PATH_MAX];
|
||||
int fd;
|
||||
ssize_t numwrite;
|
||||
|
||||
snprintf(path, sizeof(path), PATH_TO_CPU "cpu%u/cpuidle/state%u/%s",
|
||||
cpu, idlestate, fname);
|
||||
|
||||
fd = open(path, O_WRONLY);
|
||||
if (fd == -1)
|
||||
return 0;
|
||||
|
||||
numwrite = write(fd, value, len);
|
||||
if (numwrite < 1) {
|
||||
close(fd);
|
||||
return 0;
|
||||
}
|
||||
|
||||
close(fd);
|
||||
|
||||
return (unsigned int) numwrite;
|
||||
}
|
||||
|
||||
/* read access to files which contain one numeric value */
|
||||
|
||||
enum idlestate_value {
|
||||
@ -128,6 +189,7 @@ enum idlestate_value {
|
||||
IDLESTATE_POWER,
|
||||
IDLESTATE_LATENCY,
|
||||
IDLESTATE_TIME,
|
||||
IDLESTATE_DISABLE,
|
||||
MAX_IDLESTATE_VALUE_FILES
|
||||
};
|
||||
|
||||
@ -136,6 +198,7 @@ static const char *idlestate_value_files[MAX_IDLESTATE_VALUE_FILES] = {
|
||||
[IDLESTATE_POWER] = "power",
|
||||
[IDLESTATE_LATENCY] = "latency",
|
||||
[IDLESTATE_TIME] = "time",
|
||||
[IDLESTATE_DISABLE] = "disable",
|
||||
};
|
||||
|
||||
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,
|
||||
return result;
|
||||
}
|
||||
|
||||
/*
|
||||
* Returns:
|
||||
* 1 if disabled
|
||||
* 0 if enabled
|
||||
* -1 if idlestate is not available
|
||||
* -2 if disabling is not supported by the kernel
|
||||
*/
|
||||
int sysfs_is_idlestate_disabled(unsigned int cpu,
|
||||
unsigned int idlestate)
|
||||
{
|
||||
if (sysfs_get_idlestate_count(cpu) < idlestate)
|
||||
return -1;
|
||||
|
||||
if (!sysfs_idlestate_file_exists(cpu, idlestate,
|
||||
idlestate_value_files[IDLESTATE_DISABLE]))
|
||||
return -2;
|
||||
return sysfs_idlestate_get_one_value(cpu, idlestate, IDLESTATE_DISABLE);
|
||||
}
|
||||
|
||||
/*
|
||||
* Pass 1 as last argument to disable or 0 to enable the state
|
||||
* Returns:
|
||||
* 0 on success
|
||||
* negative values on error, for example:
|
||||
* -1 if idlestate is not available
|
||||
* -2 if disabling is not supported by the kernel
|
||||
* -3 No write access to disable/enable C-states
|
||||
*/
|
||||
int sysfs_idlestate_disable(unsigned int cpu,
|
||||
unsigned int idlestate,
|
||||
unsigned int disable)
|
||||
{
|
||||
char value[SYSFS_PATH_MAX];
|
||||
int bytes_written;
|
||||
|
||||
if (sysfs_get_idlestate_count(cpu) < idlestate)
|
||||
return -1;
|
||||
|
||||
if (!sysfs_idlestate_file_exists(cpu, idlestate,
|
||||
idlestate_value_files[IDLESTATE_DISABLE]))
|
||||
return -2;
|
||||
|
||||
snprintf(value, SYSFS_PATH_MAX, "%u", disable);
|
||||
|
||||
bytes_written = sysfs_idlestate_write_file(cpu, idlestate, "disable",
|
||||
value, sizeof(disable));
|
||||
if (bytes_written)
|
||||
return 0;
|
||||
return -3;
|
||||
}
|
||||
|
||||
unsigned long sysfs_get_idlestate_latency(unsigned int cpu,
|
||||
unsigned int idlestate)
|
||||
unsigned int idlestate)
|
||||
{
|
||||
return sysfs_idlestate_get_one_value(cpu, idlestate, IDLESTATE_LATENCY);
|
||||
}
|
||||
|
@ -7,8 +7,16 @@
|
||||
|
||||
extern unsigned int sysfs_read_file(const char *path, char *buf, size_t buflen);
|
||||
|
||||
extern unsigned int sysfs_idlestate_file_exists(unsigned int cpu,
|
||||
unsigned int idlestate,
|
||||
const char *fname);
|
||||
|
||||
extern int sysfs_is_cpu_online(unsigned int cpu);
|
||||
|
||||
extern int sysfs_is_idlestate_disabled(unsigned int cpu,
|
||||
unsigned int idlestate);
|
||||
extern int sysfs_idlestate_disable(unsigned int cpu, unsigned int idlestate,
|
||||
unsigned int disable);
|
||||
extern unsigned long sysfs_get_idlestate_latency(unsigned int cpu,
|
||||
unsigned int idlestate);
|
||||
extern unsigned long sysfs_get_idlestate_usage(unsigned int cpu,
|
||||
|
Loading…
Reference in New Issue
Block a user