raster pushed a commit to branch master.

commit 6b532aadadb502c34e10832a338947847ddf5429
Author: Carsten Haitzler (Rasterman) <[email protected]>
Date:   Tue May 21 21:57:56 2013 +0900

    add intel pstate support in cpufreq for kernel 3.9 and newer.
---
 src/modules/cpufreq/e_mod_main.c | 157 +++++++++++++++++++++++++++++++++++++++
 src/modules/cpufreq/e_mod_main.h |   8 ++
 src/modules/cpufreq/freqset.c    |  48 +++++++++++-
 3 files changed, 212 insertions(+), 1 deletion(-)

diff --git a/src/modules/cpufreq/e_mod_main.c b/src/modules/cpufreq/e_mod_main.c
index 9f8b15f..cfb8a31 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 5cd5a6c..f462c9b 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 3bda901..a5da622 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;
+}

-- 

------------------------------------------------------------------------------
Try New Relic Now & We'll Send You this Cool Shirt
New Relic is the only SaaS-based application performance monitoring service 
that delivers powerful full stack analytics. Optimize and monitor your
browser, app, & servers with just a few lines of code. Try New Relic
and get this awesome Nerd Life shirt! http://p.sf.net/sfu/newrelic_d2d_may

Reply via email to