Skip to content

Commit

Permalink
Add cpu scaling governor policy
Browse files Browse the repository at this point in the history
Makes it possible to configure mce so that "interactive" scaling
governor is used when device is running in normal UI state and
"performance" when device is booting up or shutting down.

Configuration via /etc/mce/NN-adaptation-name.ini files that specify
Default and Interactive sections, for example:
  [CPUScalingGovernorDefault]
  path1=/sys/devices/system/cpu/cpu*/cpufreq/scaling_governor
  data1=performance
  path2=
  [CPUScalingGovernorInteractive]
  path1=/sys/devices/system/cpu/cpu*/cpufreq/scaling_governor
  data1=interactive
  path2=

The mcetool utility can be used to override the policy via:
  mcetool -S automatic|performance|interactive
This setting persists over mce restarts / device reboots.

[mce] Add cpu scaling governor policy
  • Loading branch information
spiiroin committed Jul 29, 2013
1 parent 298d3bc commit 284827c
Show file tree
Hide file tree
Showing 4 changed files with 353 additions and 1 deletion.
6 changes: 6 additions & 0 deletions builtin-gconf.c
Expand Up @@ -1300,6 +1300,12 @@ static const setting_t gconf_defaults[] =
.type = "i",
.def = "1",
},
{
// MCE_GCONF_CPU_SCALING_GOVERNOR_PATH @ modules/display.h
.key = "/system/osso/dsm/display/cpu_scaling_governor",
.type = "i",
.def = "0", // = GOVERNOR_UNSET = no override
},
{
// MCE_GCONF_TK_AUTO_BLANK_DISABLE_PATH @ tklock.h
.key = "/system/osso/dsm/locks/tklock_blank_disable",
Expand Down
292 changes: 292 additions & 0 deletions modules/display.c
Expand Up @@ -2996,6 +2996,276 @@ static gint suspend_policy = SUSPEND_POLICY_DEFAULT;
/** GConf callback ID for automatic suspend policy changes */
static guint suspend_policy_id = 0;

/** CPU scaling governor override; not enabled by default */
static gint governor_conf = GOVERNOR_UNSET;

/** GConf callback ID for cpu scaling governor changes */
static guint governor_conf_id = 0;

/** Content and where to write it */
typedef struct governor_setting_t
{
/** Path (or rather glob pattern) to file where to write */
char *path;

/** Data to write */
char *data;
} governor_setting_t;

/** GOVERNOR_DEFAULT CPU scaling governor settings */
static governor_setting_t *governor_default = 0;

/** GOVERNOR_INTERACTIVE CPU scaling governor settings */
static governor_setting_t *governor_interactive = 0;

/** Obtain arrays of settings from mce ini-files
*
* Use governor_free_settings() to release data returned from this
* function.
*
* If CPU scaling governor is not defined in mce INI-files, an
* empty (=no-op) array of settings is returned.
*
* @param tag Name of CPU scaling governor state
*
* @return array of settings
*/
static governor_setting_t *governor_get_settings(const char *tag)
{
governor_setting_t *res = 0;
size_t have = 0;
size_t used = 0;

char sec[128], key[128], *path, *data;

snprintf(sec, sizeof sec, "CPUScalingGovernor%s", tag);
for( int i = 0; i < 32; ++i ) {
snprintf(key, sizeof key, "path%d", i+1);
path = mce_conf_get_string(sec, key, 0);
if( !path || !*path )
break;

snprintf(key, sizeof key, "data%d", i+1);
data = mce_conf_get_string(sec, key, 0);
if( !data )
break;

if( used == have ) {
have += 8;
res = realloc(res, have * sizeof *res);
}

res[used].path = strdup(path);
res[used].data = strdup(data);
++used;
mce_log(LOG_CRIT, "%s[%d]: echo > %s %s", sec, used, path, data);
}

if( used == 0 ) {
mce_log(LL_WARN, "No items defined for: %s", sec);
}

have = used + 1;
res = realloc(res, have * sizeof *res);

res[used].path = 0;
res[used].data = 0;

return res;
}

/** Release settings array obtained with governor_get_settings()
*
* @param settings array of settings, or NULL
*/
static void governor_free_settings(governor_setting_t *settings)
{
if( settings ) {
for( size_t i = 0; settings[i].path; ++i ) {
free(settings[i].path);
free(settings[i].data);
}
free(settings);
}
}

/** Write string to an already existing file
*
* @param path file to write to
* @param data text to write
*
* @returns true on success, false on failure
*/
static bool governor_write_data(const char *path, const char *data)
{
bool res = false;
int todo = strlen(data);
int done = 0;
int fd = -1;

/* NB: no O_CREAT & co, the file must already exist */
if( (fd = TEMP_FAILURE_RETRY(open(path, O_WRONLY))) == -1 ) {
mce_log(LL_WARN, "%s: failed to open for writing: %m", path);
goto cleanup;
}

errno = 0, done = TEMP_FAILURE_RETRY(write(fd, data, todo));

if( done != todo ) {
mce_log(LL_WARN, "%s: wrote %d of %d bytes: %m",
path, done, todo);
goto cleanup;
}

res = true;

cleanup:

if( fd != -1 ) TEMP_FAILURE_RETRY(close(fd));

return res;
}

/** Write cpu scaling governor parameter to sysfs
*
* @param setting Content and where to write it
*/
static void governor_apply_setting(const governor_setting_t *setting)
{
glob_t gb;

memset(&gb, 0, sizeof gb);

switch( glob(setting->path, 0, 0, &gb) )
{
case 0:
// success
break;

case GLOB_NOMATCH:
mce_log(LL_WARN, "%s: no matches found", setting->path);
goto cleanup;

case GLOB_NOSPACE:
case GLOB_ABORTED:
default:
mce_log(LL_ERR, "%s: glob() failed", setting->path);
goto cleanup;
}

for( size_t i = 0; i < gb.gl_pathc; ++i ) {
if( governor_write_data(gb.gl_pathv[i], setting->data) ) {
mce_log(LL_DEBUG, "wrote \"%s\" to: %s",
setting->data, gb.gl_pathv[i]);
}
}

cleanup:
globfree(&gb);
}

/** Switch cpu scaling governor state
*
* @param state GOVERNOR_DEFAULT, GOVERNOR_DEFAULT, ...
*/
static void governor_set_state(int state)
{
const governor_setting_t *settings = 0;

switch( state )
{
case GOVERNOR_DEFAULT:
settings = governor_default;
break;
case GOVERNOR_INTERACTIVE:
settings = governor_interactive;
break;

default: break;
}

if( !settings ) {
mce_log(LL_WARN, "governor state=%d has no mapping", state);
}
else {
for( ; settings->path; ++settings ) {
governor_apply_setting(settings);
}
}
}

/** Evaluate and apply CPU scaling governor policy */
static void governor_rethink(void)
{
static int governor_have = GOVERNOR_UNSET;

system_state_t system_state = datapipe_get_gint(system_state_pipe);

/* By default we want to use "interactive"
* cpu scaling governor, except ... */
int governor_want = GOVERNOR_INTERACTIVE;

/* Use default when in ACTDEAD etc */
if( system_state != MCE_STATE_USER ) {
governor_want = GOVERNOR_DEFAULT;
}

/* Use default during bootup */
if( suspend_timer_id || !init_done ) {
governor_want = GOVERNOR_DEFAULT;
}

/* Use default during shutdown */
if( shutdown_started ) {
governor_want = GOVERNOR_DEFAULT;
}

/* Restore default on unload / mce exit */
if( suspend_unload ) {
governor_want = GOVERNOR_DEFAULT;
}

/* Config override has been set */
if( governor_conf != GOVERNOR_UNSET ) {
governor_want = governor_conf;
}

/* Apply new policy state */
if( governor_have != governor_want ) {
mce_log(LOG_NOTICE, "state: %d -> %d",
governor_have, governor_want);
governor_set_state(governor_want);
governor_have = governor_want;
}
}

/** Callback for handling changes to cpu scaling governor configuration
*
* @param client (not used)
* @param id (not used)
* @param entry GConf entry that changed
* @param data (not used)
*/
static void governor_conf_cb(GConfClient *const client, const guint id,
GConfEntry *const entry, gpointer const data)
{
(void)client; (void)id; (void)data;

gint policy = GOVERNOR_UNSET;
const GConfValue *value = 0;

if( entry && (value = gconf_entry_get_value(entry)) ) {
if( value->type == GCONF_VALUE_INT )
policy = gconf_value_get_int(value);
}
if( governor_conf != policy ) {
mce_log(LL_NOTICE, "cpu scaling governor change: %d -> %d",
governor_conf, policy);
governor_conf = policy;
governor_rethink();
}
}


/** Make suspend policy decision
*
Expand Down Expand Up @@ -3131,6 +3401,8 @@ static gboolean shutdown_dbus_cb(DBusMessage *const msg)
/* re-evaluate suspend policy */
suspend_rethink();

governor_rethink();

return TRUE;
}

Expand All @@ -3143,6 +3415,7 @@ static gboolean suspend_timer_cb(gpointer user_data)
suspend_timer_id = 0;
mce_log(LL_NOTICE, "suspend delay ended");
suspend_rethink();
governor_rethink();
}
return FALSE;
}
Expand All @@ -3169,6 +3442,7 @@ static void init_done_changed_cb(const char *path,
mce_log(LL_NOTICE, "init_done -> %s",
init_done ? "true" : "false");
suspend_rethink();
governor_rethink();
}
}

Expand All @@ -3187,6 +3461,7 @@ static void suspend_quit(void)
}

suspend_rethink();
governor_rethink();
}

/** Initialize suspend policy
Expand Down Expand Up @@ -3568,6 +3843,7 @@ static void system_state_trigger(gconstpointer data)
}
/* re-evaluate suspend policy */
suspend_rethink();
governor_rethink();
#endif

return;
Expand Down Expand Up @@ -3636,6 +3912,18 @@ const gchar *g_module_check_init(GModule *module)
(void)get_display_type();

#ifdef ENABLE_WAKELOCKS
/* Get CPU scaling governor settings from INI-files */
governor_default = governor_get_settings("Default");
governor_interactive = governor_get_settings("Interactive");

/* Get cpu scaling governor configuration & track changes */
mce_gconf_get_int(MCE_GCONF_CPU_SCALING_GOVERNOR_PATH,
&governor_conf);
mce_gconf_notifier_add(MCE_GCONF_DISPLAY_PATH,
MCE_GCONF_CPU_SCALING_GOVERNOR_PATH,
governor_conf_cb,
&governor_conf_id);

/* Get autosuspend policy configuration & track changes */
mce_gconf_get_int(MCE_GCONF_USE_AUTOSUSPEND_PATH,
&suspend_policy);
Expand Down Expand Up @@ -4005,6 +4293,10 @@ void g_module_unload(GModule *module)

/* Cleanup suspend policy evaluator */
suspend_quit();

/* Release CPU scaling governor settings from INI-files */
governor_free_settings(governor_default), governor_default = 0;
governor_free_settings(governor_interactive), governor_interactive = 0;
#endif

/* Write display on timers to CAL */
Expand Down
10 changes: 10 additions & 0 deletions modules/display.h
Expand Up @@ -137,6 +137,8 @@
#define MCE_GCONF_USE_LOW_POWER_MODE_PATH MCE_GCONF_DISPLAY_PATH "/use_low_power_mode"
/** Path to the use autosuspend GConf setting */
#define MCE_GCONF_USE_AUTOSUSPEND_PATH MCE_GCONF_DISPLAY_PATH "/autosuspend_policy"
/** Path to the use cpu scaling governor GConf setting */
#define MCE_GCONF_CPU_SCALING_GOVERNOR_PATH MCE_GCONF_DISPLAY_PATH "/cpu_scaling_governor"

/** Default display brightness on a scale from 1-5 */
#define DEFAULT_DISP_BRIGHTNESS 3 /* 60% */
Expand Down Expand Up @@ -175,4 +177,12 @@
/** Default dim brightness, in percent */
#define DEFAULT_DIM_BRIGHTNESS 3

/** CPU scaling covernor policy states */
enum
{
GOVERNOR_UNSET,
GOVERNOR_DEFAULT,
GOVERNOR_INTERACTIVE,
};

#endif /* _DISPLAY_H_ */

0 comments on commit 284827c

Please sign in to comment.