summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorCarsten Haitzler (Rasterman) <raster@rasterman.com>2013-05-21 21:57:56 +0900
committerCarsten Haitzler (Rasterman) <raster@rasterman.com>2013-05-21 22:07:06 +0900
commit6b532aadadb502c34e10832a338947847ddf5429 (patch)
treed7ea915bd63f54992ce9f820450c5e396f8290e3
parent0bf55848abe19088b7546f8161d1b85e3a864ba2 (diff)
downloadenlightenment-6b532aadadb502c34e10832a338947847ddf5429.tar.gz
add intel pstate support in cpufreq for kernel 3.9 and newer.
-rw-r--r--src/modules/cpufreq/e_mod_main.c157
-rw-r--r--src/modules/cpufreq/e_mod_main.h8
-rw-r--r--src/modules/cpufreq/freqset.c48
3 files changed, 212 insertions, 1 deletions
diff --git a/src/modules/cpufreq/e_mod_main.c b/src/modules/cpufreq/e_mod_main.c
index 9f8b15ff05..cfb8a31bf3 100644
--- a/src/modules/cpufreq/e_mod_main.c
+++ b/src/modules/cpufreq/e_mod_main.c
@@ -40,6 +40,7 @@ static void _button_cb_mouse_down(void *data, Evas *e, Evas_Object *obj, vo
static void _menu_cb_post(void *data, E_Menu *m);
static void _cpufreq_set_governor(const char *governor);
static void _cpufreq_set_frequency(int frequency);
+static void _cpufreq_set_pstate(int min, int max, int turbo);
static Eina_Bool _cpufreq_cb_check(void *data);
static Status *_cpufreq_status_new(void);
static void _cpufreq_status_free(Status *s);
@@ -62,6 +63,8 @@ static void _cpufreq_menu_auto_powersave(void *data, E_Menu *m, E_Menu_Item
static void _cpufreq_menu_governor(void *data, E_Menu *m, E_Menu_Item *mi);
static void _cpufreq_menu_powersave_governor(void *data, E_Menu *m, E_Menu_Item *mi);
static void _cpufreq_menu_frequency(void *data, E_Menu *m, E_Menu_Item *mi);
+static void _cpufreq_menu_pstate_min(void *data, E_Menu *m, E_Menu_Item *mi);
+static void _cpufreq_menu_pstate_max(void *data, E_Menu *m, E_Menu_Item *mi);
static void _cpufreq_poll_interval_update(void);
static E_Config_DD *conf_edd = NULL;
@@ -330,6 +333,47 @@ _button_cb_mouse_down(void *data, Evas *e __UNUSED__, Evas_Object *obj __UNUSED_
}
}
+ if (cpufreq_config->status->pstate)
+ {
+ int set;
+
+ mo = e_menu_new();
+ cpufreq_config->menu_pstate1 = mo;
+
+ set = 0;
+#define VALMIN(_n) \
+ mi = e_menu_item_new(mo); \
+ e_menu_item_label_set(mi, #_n); \
+ e_menu_item_radio_set(mi, 1); \
+ e_menu_item_radio_group_set(mi, 1); \
+ if ((!set) && (cpufreq_config->status->pstate_min <= _n)) \
+ { set = 1; e_menu_item_toggle_set(mi, 1); } \
+ e_menu_item_callback_set(mi, _cpufreq_menu_pstate_min, (void *)_n)
+ VALMIN(0);
+ VALMIN(25);
+ VALMIN(50);
+ VALMIN(75);
+ VALMIN(100);
+
+ mo = e_menu_new();
+ cpufreq_config->menu_pstate2 = mo;
+
+ set = 0;
+#define VALMAX(_n) \
+ mi = e_menu_item_new(mo); \
+ e_menu_item_label_set(mi, #_n); \
+ e_menu_item_radio_set(mi, 1); \
+ e_menu_item_radio_group_set(mi, 1); \
+ if ((!set) && (cpufreq_config->status->pstate_max <= _n)) \
+ { set = 1; e_menu_item_toggle_set(mi, 1); } \
+ e_menu_item_callback_set(mi, _cpufreq_menu_pstate_max, (void *)_n)
+ VALMAX(5);
+ VALMAX(25);
+ VALMAX(50);
+ VALMAX(75);
+ VALMAX(100);
+ }
+
mg = e_menu_new();
mi = e_menu_item_new(mg);
e_menu_item_label_set(mi, _("Time Between Updates"));
@@ -354,6 +398,18 @@ _button_cb_mouse_down(void *data, Evas *e __UNUSED__, Evas_Object *obj __UNUSED_
e_menu_item_label_set(mi, _("Powersaving behavior"));
e_menu_item_submenu_set(mi, cpufreq_config->menu_powersave);
}
+ if (cpufreq_config->menu_pstate1)
+ {
+ mi = e_menu_item_new(mg);
+ e_menu_item_label_set(mi, _("Power State Min"));
+ e_menu_item_submenu_set(mi, cpufreq_config->menu_pstate1);
+ }
+ if (cpufreq_config->menu_pstate2)
+ {
+ mi = e_menu_item_new(mg);
+ e_menu_item_label_set(mi, _("Power State Max"));
+ e_menu_item_submenu_set(mi, cpufreq_config->menu_pstate2);
+ }
e_gadcon_canvas_zone_geometry_get(inst->gcc->gadcon,
&cx, &cy, NULL, NULL);
@@ -411,6 +467,10 @@ _menu_cb_post(void *data, E_Menu *m __UNUSED__)
cpufreq_config->menu_frequency = NULL;
if (cpufreq_config->menu_powersave)
e_object_del(E_OBJECT(cpufreq_config->menu_powersave));
+ if (cpufreq_config->menu_pstate1)
+ e_object_del(E_OBJECT(cpufreq_config->menu_pstate1));
+ if (cpufreq_config->menu_pstate2)
+ e_object_del(E_OBJECT(cpufreq_config->menu_pstate2));
cpufreq_config->menu_powersave = NULL;
}
@@ -498,6 +558,35 @@ _cpufreq_set_frequency(int frequency)
}
}
+static void
+_cpufreq_set_pstate(int min, int max, int turbo)
+{
+ char buf[4096];
+ int ret;
+
+ snprintf(buf, sizeof(buf),
+ "%s %s %i %i %i", cpufreq_config->set_exe_path, "pstate", min, max, turbo);
+ fprintf(stderr, buf);
+ ret = system(buf);
+ if (ret != 0)
+ {
+ E_Dialog *dia;
+ E_Container *con;
+
+ con = e_container_current_get(e_manager_current_get());
+ if (!(dia = e_dialog_new(con, "E", "_e_mod_cpufreq_error_setfreq")))
+ return;
+ e_dialog_title_set(dia, "Enlightenment Cpufreq Module");
+ e_dialog_icon_set(dia, "enlightenment", 64);
+ e_dialog_text_set(dia, _("There was an error trying to set the<br>"
+ "cpu power state setting via the module's<br>"
+ "setfreq utility."));
+ e_dialog_button_add(dia, _("OK"), NULL, NULL, NULL);
+ e_win_centered_set(dia->win, 1);
+ e_dialog_show(dia);
+ }
+}
+
static Eina_Bool
_cpufreq_cb_check(void *data __UNUSED__)
{
@@ -859,6 +948,38 @@ _cpufreq_status_check_current(Status *s)
}
}
}
+ f = fopen("/sys/devices/system/cpu/intel_pstate/min_perf_pct", "r");
+ if (f)
+ {
+ if (fgets(buf, sizeof(buf), f) != NULL)
+ {
+ s->pstate_min = atoi(buf);
+ s->pstate = 1;
+ }
+ fclose(f);
+ }
+ f = fopen("/sys/devices/system/cpu/intel_pstate/max_perf_pct", "r");
+ if (f)
+ {
+ if (fgets(buf, sizeof(buf), f) != NULL)
+ {
+ s->pstate_max = atoi(buf);
+ s->pstate = 1;
+ }
+ fclose(f);
+ }
+ f = fopen("/sys/devices/system/cpu/intel_pstate/no_turbo", "r");
+ if (f)
+ {
+ if (fgets(buf, sizeof(buf), f) != NULL)
+ {
+ s->pstate_turbo = atoi(buf);
+ if (s->pstate_turbo) s->pstate_turbo = 0;
+ else s->pstate_turbo = 1;
+ s->pstate = 1;
+ }
+ fclose(f);
+ }
#endif
return ret;
}
@@ -1109,6 +1230,30 @@ _cpufreq_menu_frequency(void *data, E_Menu *m __UNUSED__, E_Menu_Item *mi __UNUS
}
static void
+_cpufreq_menu_pstate_min(void *data, E_Menu *m __UNUSED__, E_Menu_Item *mi __UNUSED__)
+{
+ int min = (long)data;
+ cpufreq_config->pstate_min = min + 1;
+ if (cpufreq_config->pstate_max < cpufreq_config->pstate_min)
+ cpufreq_config->pstate_max = cpufreq_config->pstate_min;
+ _cpufreq_set_pstate(cpufreq_config->pstate_min - 1,
+ cpufreq_config->pstate_max - 1, 1);
+ e_config_save_queue();
+}
+
+static void
+_cpufreq_menu_pstate_max(void *data, E_Menu *m __UNUSED__, E_Menu_Item *mi __UNUSED__)
+{
+ int max = (long)data;
+ cpufreq_config->pstate_max = max + 1;
+ if (cpufreq_config->pstate_min > cpufreq_config->pstate_max)
+ cpufreq_config->pstate_min = cpufreq_config->pstate_max;
+ _cpufreq_set_pstate(cpufreq_config->pstate_min - 1,
+ cpufreq_config->pstate_max - 1, 1);
+ e_config_save_queue();
+}
+
+static void
_cpufreq_poll_interval_update(void)
{
if (cpufreq_config->frequency_check_poller)
@@ -1143,6 +1288,8 @@ e_modapi_init(E_Module *m)
E_CONFIG_VAL(D, T, auto_powersave, INT);
E_CONFIG_VAL(D, T, powersave_governor, STR);
E_CONFIG_VAL(D, T, governor, STR);
+ E_CONFIG_VAL(D, T, pstate_min, INT);
+ E_CONFIG_VAL(D, T, pstate_max, INT);
cpufreq_config = e_config_domain_load("module.cpufreq", conf_edd);
if ((cpufreq_config) &&
@@ -1158,6 +1305,13 @@ e_modapi_init(E_Module *m)
cpufreq_config->auto_powersave = 1;
cpufreq_config->powersave_governor = NULL;
cpufreq_config->governor = NULL;
+ cpufreq_config->pstate_min = 1;
+ cpufreq_config->pstate_max = 101;
+ }
+ else
+ {
+ if (cpufreq_config->pstate_min == 0) cpufreq_config->pstate_min = 1;
+ if (cpufreq_config->pstate_max == 0) cpufreq_config->pstate_max = 101;
}
E_CONFIG_LIMIT(cpufreq_config->poll_interval, 1, 1024);
@@ -1205,6 +1359,9 @@ e_modapi_init(E_Module *m)
}
}
+ _cpufreq_set_pstate(cpufreq_config->pstate_min - 1,
+ cpufreq_config->pstate_max - 1, 1);
+
cpufreq_config->module = m;
e_gadcon_provider_register(&_gadcon_class);
diff --git a/src/modules/cpufreq/e_mod_main.h b/src/modules/cpufreq/e_mod_main.h
index 5cd5a6c131..f462c9bf3f 100644
--- a/src/modules/cpufreq/e_mod_main.h
+++ b/src/modules/cpufreq/e_mod_main.h
@@ -17,9 +17,13 @@ struct _Status
int cur_min_frequency;
int cur_max_frequency;
int can_set_frequency;
+ int pstate_min;
+ int pstate_max;
char *cur_governor;
const char *orig_governor;
unsigned char active;
+ unsigned char pstate;
+ unsigned char pstate_turbo;
};
struct _Config
@@ -31,6 +35,8 @@ struct _Config
int auto_powersave;
const char *powersave_governor;
const char *governor;
+ int pstate_min;
+ int pstate_max;
/* just config state */
E_Module *module;
Eina_List *instances;
@@ -39,6 +45,8 @@ struct _Config
E_Menu *menu_governor;
E_Menu *menu_frequency;
E_Menu *menu_powersave;
+ E_Menu *menu_pstate1;
+ E_Menu *menu_pstate2;
Status *status;
char *set_exe_path;
Ecore_Poller *frequency_check_poller;
diff --git a/src/modules/cpufreq/freqset.c b/src/modules/cpufreq/freqset.c
index 3bda901a05..a5da6229cb 100644
--- a/src/modules/cpufreq/freqset.c
+++ b/src/modules/cpufreq/freqset.c
@@ -16,14 +16,16 @@
static int sys_cpu_setall(const char *control, const char *value);
static int sys_cpufreq_set(const char *control, const char *value);
+static int sys_cpu_pstate(int min, int max, int turbo);
int
main(int argc, char *argv[])
{
- if (argc != 3)
+ if (argc < 3)
{
fprintf(stderr, "Invalid command. Syntax:\n");
fprintf(stderr, "\tfreqset <frequency|governor> <freq-level|governor-name>\n");
+ fprintf(stderr, "\tfreqset <pstate> <min> <max> <turbo>\n");
return 1;
}
@@ -99,6 +101,28 @@ main(int argc, char *argv[])
sys_cpufreq_set("conservative/ignore_nice_load", "0");
return 0;
}
+ else if (!strcmp(argv[1], "pstate"))
+ {
+ int min, max, turbo;
+
+ if (argc < 5)
+ {
+ fprintf(stderr, "Invalid number of arguments.\n");
+ return 1;
+ }
+ min = atoi(argv[2]);
+ max = atoi(argv[3]);
+ turbo = atoi(argv[4]);
+ if ((min < 0) || (min > 100) ||
+ (max < 0) || (max > 100) ||
+ (turbo < 0) || (turbo > 1))
+ {
+ fprintf(stderr, "Invalid pstate values.\n");
+ return 1;
+ }
+ sys_cpu_pstate(min, max, turbo);
+ return 0;
+ }
else
{
fprintf(stderr, "Unknown command.\n");
@@ -156,3 +180,25 @@ sys_cpufreq_set(const char *control, const char *value)
return 1;
}
+static int
+sys_cpu_pstate(int min, int max, int turbo)
+{
+ FILE *f;
+
+ f = fopen("/sys/devices/system/cpu/intel_pstate/min_perf_pct", "w");
+ if (!f) return 0;
+ fprintf(f, "%i\n", min);
+ fclose(f);
+
+ f = fopen("/sys/devices/system/cpu/intel_pstate/max_perf_pct", "w");
+ if (!f) return 0;
+ fprintf(f, "%i\n", max);
+ fclose(f);
+
+ f = fopen("/sys/devices/system/cpu/intel_pstate/no_turbo", "w");
+ if (!f) return 0;
+ fprintf(f, "%i\n", turbo ? 0 : 1);
+ fclose(f);
+
+ return 1;
+}