pass: cpuhp: Replace 'governor' with 'cpuhp' expression 43/169043/2
authorChanwoo Choi <cw00.choi@samsung.com>
Fri, 2 Feb 2018 04:26:37 +0000 (13:26 +0900)
committerChanwoo Choi <cw00.choi@samsung.com>
Fri, 2 Feb 2018 05:09:53 +0000 (14:09 +0900)
PASS uses 'CPUHP' indicating 'CPU Hotplug Manager' module.
'governor' is too abstract and old expression. Replace 'governor'
with 'cpuhp' expression in order to improve the readability.

Change-Id: Ib7c6509e200cd7603739bace6bcf913bea22475b
Signed-off-by: Chanwoo Choi <cw00.choi@samsung.com>
CMakeLists.txt
src/pass/pass-cpuhp-radiation.c [new file with mode: 0644]
src/pass/pass-cpuhp-step.c [new file with mode: 0644]
src/pass/pass-cpuhp.c [new file with mode: 0644]
src/pass/pass-gov-radiation.c [deleted file]
src/pass/pass-gov-step.c [deleted file]
src/pass/pass-gov.c [deleted file]
src/pass/pass.c
src/pass/pass.h

index 6910b9e881d8b7804a2ac104a4a5c3411e30f56e..6a40a6a1d0fb7ddfb12541ae39ef61555abe0881 100644 (file)
@@ -63,9 +63,9 @@ SET(PASS_HAL_NAME pass-hal-devel)
 
 SET(SRCS
        src/pass/pass.c
-       src/pass/pass-gov.c
-       src/pass/pass-gov-radiation.c
-       src/pass/pass-gov-step.c
+       src/pass/pass-cpuhp.c
+       src/pass/pass-cpuhp-radiation.c
+       src/pass/pass-cpuhp-step.c
        src/pass/pass-parser.c
        src/pass/pass-hal.c
        src/pass/pass-rescon.c
diff --git a/src/pass/pass-cpuhp-radiation.c b/src/pass/pass-cpuhp-radiation.c
new file mode 100644 (file)
index 0000000..649385b
--- /dev/null
@@ -0,0 +1,221 @@
+/*
+ * PASS (Power Aware Systerm Service) Radiation governor
+ *
+ * Copyright (c) 2012 - 2018 Samsung Electronics Co., Ltd.
+ *
+ * Licensed under the Apache License, Version 2.0 (the License);
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include <stdbool.h>
+#include <stdio.h>
+#include <stdlib.h>
+
+#include "pass.h"
+
+/*
+ * pass_cpuhp_radiation_governor - Check cpu state and determine the amount of resource
+ *
+ * @stats: structure for getting cpu frequency state from kerncel
+ *
+ * This function check periodically current following state of system
+ * and then determine whether pass level up or down according to pass
+ * policy with gathered data.
+ * - current cpu frequency
+ * - the number of nr_running
+ * - the number of busy_cpu
+ */
+int pass_cpuhp_radiation_governor(struct pass_resource *res)
+{
+       struct pass_level *levels = res->config_data.levels;
+       struct pass_cpuhp *cpuhp = &res->cpuhp;
+       struct pass_cpu_stats *cpu_stats = cpuhp->pass_cpu_stats;
+       int up_threshold = cpuhp->up_threshold;
+       int down_threshold = cpuhp->down_threshold;
+       int num_pass_gov = 0;
+       int level = res->rescon.curr_level;
+       int up_count = 0;
+       int down_count = 0;
+       int left_count = 0;
+       int right_count = 0;
+       bool up_condition;
+       bool down_condition;
+       bool left_condition;
+       bool right_condition;
+       int freq;
+       int nr_running;
+       int busy_cpu;
+       int i;
+       int j;
+       int64_t time;
+
+       for (i = 0; i < cpuhp->num_pass_cpu_stats; i++) {
+               time = cpu_stats[i].time;
+               freq = cpu_stats[i].freq;
+               nr_running = cpu_stats[i].nr_runnings;
+               busy_cpu = cpu_stats[i].num_busy_cpu;
+               up_condition = true;
+               down_condition = true;
+               left_condition = true;
+               right_condition = true;
+
+               if (cpuhp->last_time >= time)
+                       continue;
+               cpuhp->last_time = time;
+               num_pass_gov++;
+
+               /*
+               _I("[Level%d][%d][%lld] %d | %d | %d", level, i, time, freq,
+                                               nr_running, busy_cpu);
+               */
+
+               /* Check level up condition */
+               for (j = 0; j < levels[level].num_up_cond && up_condition; j++) {
+                       if (levels[level].up_cond[j].freq &&
+                               !(freq >= levels[level].up_cond[j].freq))
+                               up_condition = false;
+               }
+
+               if (levels[level].num_up_cond && up_condition) {
+                       up_count++;
+
+                       /*
+                       _I("[Level%d] [up_count : %2d] \
+                               freq(%d), nr_running(%d), busy_cpu(%d)",
+                               level, up_count,
+                               levels[level].up_cond[j].freq ? freq : -1,
+                       */
+               }
+
+               /* Check level down condition */
+               for (j = 0; j < levels[level].num_down_cond && down_condition; j++) {
+                       if (levels[level].down_cond[j].freq
+                               && !(freq <= levels[level].down_cond[j].freq))
+                               down_condition = false;
+               }
+
+               if (levels[level].num_down_cond && down_condition) {
+                       down_count++;
+
+                       /*
+                       _I("[Level%d] [dw_count : %2d] \
+                               freq(%d), nr_running(%d), busy_cpu(%d)",
+                               level, down_count,
+                               levels[level].down_cond[j].freq ? freq : -1,
+                       */
+               }
+
+               /* Check level right condition */
+               for (j = 0; j < levels[level].num_right_cond && right_condition; j++) {
+                       /*
+                        * If one more conditions are false among following
+                        * conditions, don't increment right_count.
+                        */
+                       if (levels[level].right_cond[j].nr_running
+                               && !(nr_running > levels[level].right_cond[j].nr_running))
+                               right_condition = false;
+
+                       if (levels[level].right_cond[j].busy_cpu
+                               && !(busy_cpu >= levels[level].right_cond[j].busy_cpu))
+                               right_condition = false;
+               }
+
+               if (levels[level].num_right_cond && right_condition) {
+                       right_count++;
+
+                       /*
+                       _I("[Level%d] [right_count : %2d] \
+                               nr_running(%d), busy_cpu(%d)",
+                               level, right_count,
+                               levels[level].right_cond[j].nr_running ? nr_running : -1,
+                               levels[level].right_cond[j].busy_cpu ? busy_cpu : -1);
+                       */
+               }
+
+               /* Check level left condition */
+               for (j = 0; j < levels[level].num_left_cond && left_condition; j++) {
+                       /*
+                        * If one more conditions are false among following
+                        * conditions, don't increment left_count.
+                        */
+                       if (levels[level].left_cond[j].nr_running
+                               && !(nr_running <= levels[level].left_cond[j].nr_running))
+                               left_condition = false;
+
+                       if (levels[level].left_cond[j].busy_cpu
+                               && !(busy_cpu < levels[level].left_cond[j].busy_cpu))
+                               left_condition = false;
+               }
+
+               if (levels[level].num_left_cond && left_condition) {
+                       left_count++;
+
+                       /*
+                       _I("[Level%d] [ left_count : %2d] \
+                               nr_running(%d), busy_cpu(%d)",
+                               level, left_count,
+                               levels[level].left_cond[j].nr_running ? nr_running : -1,
+                               levels[level].left_cond[j].busy_cpu ? busy_cpu : -1);
+                       */
+               }
+       }
+
+       if (!num_pass_gov)
+               return level;
+
+       if (up_count * 100 >= num_pass_gov * up_threshold) {
+               level += cpuhp->hotplug->num_cpus;
+
+               if (level > res->rescon.max_level)
+                       level -= cpuhp->hotplug->num_cpus;
+       } else if (down_count * 100 >= num_pass_gov * down_threshold) {
+               level -= cpuhp->hotplug->num_cpus;
+       }
+
+       if (right_count * 100 >= num_pass_gov * up_threshold) {
+               level += 1;
+
+               if (level > res->rescon.max_level)
+                       level -= 1;
+       } else if (left_count * 100 >= num_pass_gov * down_threshold) {
+               level -= 1;
+       }
+
+       /*
+       if (level == res->prev_level) {
+               for (i = num_pass_gov; i < cpuhp->num_pass_cpu_stats; i++) {
+                       time = cpu_stats[i].time;
+                       freq = cpu_stats[i].freq;
+                       nr_running = cpu_stats[i].nr_runnings;
+                       busy_cpu = cpu_stats[i].num_busy_cpu;
+
+                       _I("[Level%d][%d][%lld] %d | %d | %d",
+                                       level, i, time, freq,
+                                       nr_running, busy_cpu);
+               }
+       }
+
+       if (level != res->rescon.curr_level) {
+               _I("\n[Level%d] num_pass_gov: [%2d]", level, num_pass_gov);
+               _I("[Level%d] down_count  : %2d (%3d >= %3d)", level, down_count,
+                               down_count * 100, num_pass_gov * down_threshold);
+               _I("[Level%d] up_count    : %2d (%3d >= %3d)", level, up_count,
+                               up_count * 100, num_pass_gov * up_threshold);
+               _I("[Level%d] left_count  : %2d (%3d >= %3d)", level, left_count,
+                               left_count * 100, num_pass_gov * down_threshold);
+               _I("[Level%d] right_count : %2d (%3d >= %3d)", level, right_count,
+                               right_count * 100, num_pass_gov * up_threshold);
+       }
+       */
+
+       return level;
+}
diff --git a/src/pass/pass-cpuhp-step.c b/src/pass/pass-cpuhp-step.c
new file mode 100644 (file)
index 0000000..606d217
--- /dev/null
@@ -0,0 +1,138 @@
+/*
+ * PASS (Power Aware System Service) Step governor
+ *
+ * Copyright (c) 2012 - 2018 Samsung Electronics Co., Ltd.
+ *
+ * Licensed under the Apache License, Version 2.0 (the License);
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include <stdbool.h>
+#include <stdio.h>
+#include <stdlib.h>
+
+#include "pass.h"
+
+/*
+ * pass_cpuhp_step_governor - Check cpu state and determine the amount of resource
+ *
+ * @stats: structure for getting cpu frequency state from kerncel
+ *
+ * This function check periodically current following state of system
+ * and then determine whether pass level up or down according to pass
+ * policy with gathered data.
+ * - current cpu frequency
+ * - the number of nr_running
+ * - the number of busy_cpu
+ */
+int pass_cpuhp_step_governor(struct pass_resource *res)
+{
+       struct pass_level *levels = res->config_data.levels;
+       struct pass_cpuhp *cpuhp = &res->cpuhp;
+       struct pass_cpu_stats *cpu_stats = cpuhp->pass_cpu_stats;
+       int up_threshold = cpuhp->up_threshold;
+       int down_threshold = cpuhp->down_threshold;
+       int num_pass_gov = 0;
+       int level = res->rescon.curr_level;
+       int up_count = 0;
+       int up_max_count = 0;
+       int down_count = 0;
+       bool up_condition;
+       bool down_condition;
+       int freq;
+       int nr_running;
+       int busy_cpu;
+       int i;
+       int j;
+       int64_t time;
+
+       for (i = 0; i < cpuhp->num_pass_cpu_stats; i++) {
+               time = cpu_stats[i].time;
+               freq = cpu_stats[i].freq;
+               nr_running = cpu_stats[i].nr_runnings;
+               busy_cpu = cpu_stats[i].num_busy_cpu;
+               up_condition = false;
+               down_condition = false;
+
+               if (cpuhp->last_time >= time)
+                       continue;
+               cpuhp->last_time = time;
+               num_pass_gov++;
+
+               /* Check level up condition */
+               for (j = 0; j < levels[level].num_up_cond; j++) {
+                       /*
+                        * If one more conditions are false among following
+                        * conditions, don't increment up_count.
+                        */
+                       if (freq >= levels[level].up_cond[j].freq
+                               && nr_running >= levels[level].up_cond[j].nr_running
+                               && busy_cpu >= levels[level].up_cond[j].busy_cpu)
+                               up_condition = true;
+               }
+
+               if (levels[level].num_up_cond && up_condition) {
+                       up_count++;
+
+                       /*
+                       _I("[Level%d] [up_count : %2d] \
+                               freq(%d), nr_running(%d), busy_cpu(%d)",
+                               level, up_count,
+                               levels[level].up_cond[0].freq ? freq : -1,
+                               levels[level].up_cond[0].nr_running ? nr_running : -1,
+                               levels[level].up_cond[0].busy_cpu ? busy_cpu : -1);
+                       */
+               }
+
+               /* Check level down condition */
+               for (j = 0; j < levels[level].num_down_cond; j++) {
+                       /*
+                        * If one more conditions are false among following
+                        * conditions, don't increment down_count.
+                        */
+                       if (freq <= levels[level].down_cond[j].freq
+                               && nr_running < levels[level].down_cond[j].nr_running
+                               && busy_cpu < levels[level].down_cond[j].busy_cpu)
+                               down_condition = true;
+               }
+
+               if (levels[level].num_down_cond && down_condition) {
+                       down_count++;
+
+                       /*
+                       _I("[Level%d] [dw_count : %2d] \
+                               freq(%d), nr_running(%d), busy_cpu(%d)",
+                               level, down_count,
+                               levels[level].down_cond[0].freq ? freq : -1,
+                               levels[level].down_cond[0].nr_running ? nr_running : -1,
+                               levels[level].down_cond[0].busy_cpu ? busy_cpu : -1);
+                       */
+               }
+
+               if (level < res->rescon.max_level &&
+                       freq == levels[level].limit_max_freq)
+                       up_max_count++;
+       }
+
+       if (!num_pass_gov)
+               return level;
+
+       if (up_count && level < res->rescon.max_level &&
+                       up_count * 100 >= num_pass_gov * up_threshold) {
+               level += 1;
+       } else if (down_count && level > res->rescon.min_level &&
+                       down_count * 100 >= num_pass_gov * down_threshold) {
+               level -= 1;
+       }
+
+       return level;
+}
diff --git a/src/pass/pass-cpuhp.c b/src/pass/pass-cpuhp.c
new file mode 100644 (file)
index 0000000..3a45909
--- /dev/null
@@ -0,0 +1,531 @@
+/*
+ * PASS (Power Aware System Service) Governor
+ *
+ * Copyright (c) 2012 - 2018 Samsung Electronics Co., Ltd.
+ *
+ * Licensed under the Apache License, Version 2.0 (the License);
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include <stdbool.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <sys/time.h>
+
+#include <pass/device-notifier.h>
+#include <pass/config-parser.h>
+
+#include "pass.h"
+#include "pass-hal.h"
+#include "pass-rescon.h"
+
+extern int pass_cpuhp_step_governor(struct pass_resource *res);
+extern int pass_cpuhp_radiation_governor(struct pass_resource *res);
+static int cpuhp_governor_update(struct pass_resource *, enum pass_state);
+
+#define PASS_DEFAULT_CPU_THRESHOLD             20
+#define PASS_DEFAULT_LEVEL_UP_THRESHOLD                30
+#define PASS_DEFAULT_LEVEL_DOWN_THRESHOLD      80
+#define PASS_CPU_STATS_MAX_COUNT       20
+
+struct pass_cpuhp_governor {
+       char name[BUFF_MAX];
+       enum pass_state state;
+
+       int (*init)(struct pass_resource *res);
+       int (*exit)(struct pass_resource *res);
+       int (*update)(struct pass_resource *res, enum pass_state state);
+       int (*governor)(struct pass_resource *res);
+};
+
+static bool is_enabled(struct pass_cpuhp *cpuhp)
+{
+       if (cpuhp->state != PASS_ON)
+               return false;
+
+       return true;
+}
+
+static void cpuhp_hotplug_stop(struct pass_resource *res)
+{
+       struct pass_level *levels = res->config_data.levels;
+       int level = res->rescon.max_level;
+
+       if (!res->cpuhp.hotplug || !levels)
+               return;
+
+       res->cpuhp.hotplug->online = levels[level].limit_min_cpu;
+}
+
+static int cpuhp_hotplug_dummy_governor(struct pass_resource *res)
+{
+       int level = res->rescon.curr_level;
+
+       return res->config_data.levels[level].limit_min_cpu;
+}
+
+static struct pass_hotplug* cpuhp_get_hotplug(struct pass_resource *res,
+                                       enum pass_gov_type type)
+{
+       struct pass_hotplug *hotplug;
+
+       switch (type) {
+       case PASS_GOV_DUMMY:
+       case PASS_GOV_BASIC:
+               /* Don't use Hotplug interface */
+               return NULL;
+       case PASS_GOV_HOTPLUG_ONLY:
+       case PASS_GOV_STEP:
+       case PASS_GOV_RADIATION:
+               /* Use Hotplug interface */
+               hotplug = calloc(1, sizeof(struct pass_hotplug));
+               if (!hotplug) {
+                       _E("cannot allocate the memory of struct pass_hotplug");
+                       return NULL;
+               }
+               hotplug->governor = cpuhp_hotplug_dummy_governor;
+               return hotplug;
+       default:
+               _E("Unknown hotplug type");
+               break;
+       };
+
+       return NULL;
+}
+
+static void cpuhp_calculate_busy_cpu(struct pass_resource *res)
+{
+       struct pass_cpuhp *cpuhp = &res->cpuhp;
+       struct pass_level *levels = res->config_data.levels;
+       struct pass_resource_config_data *config_data = &res->config_data;
+       struct pass_cpu_stats *stats = cpuhp->pass_cpu_stats;
+       unsigned int level = res->rescon.curr_level;
+       unsigned int cpu_threshold = 0;
+       unsigned int busy_cpu;
+       unsigned int cur_freq;
+       unsigned int load;
+       unsigned int sum_load;
+       unsigned int sum_runnable_load;
+       unsigned int nr_runnings;
+       int limit_min_cpu;
+       int i;
+       int j;
+
+       limit_min_cpu = levels[level].limit_min_cpu;
+
+       for (i = 0; i < cpuhp->num_pass_cpu_stats; i++) {
+               cur_freq = stats[i].freq;
+               nr_runnings = stats[i].nr_runnings;
+
+               stats[i].num_busy_cpu = 0;
+               stats[i].avg_load = 0;
+               stats[i].avg_runnable_load = 0;
+               stats[i].avg_thread_load = 0;
+               stats[i].avg_thread_runnable_load = 0;
+
+               busy_cpu = 0;
+               sum_load = 0;
+               sum_runnable_load = 0;
+
+               /* Calculate the number of busy cpu */
+               for (j = 0; j < config_data->num_cpus; j++) {
+                       load = stats[i].load[j];
+                       sum_load += stats[i].load[j];
+                       sum_runnable_load += stats[i].runnable_load[j];
+                       if (!load)
+                               continue;
+
+                       cpu_threshold =
+                               (unsigned int)(cur_freq * load)
+                                               / cpuhp->freq.max_freq;
+                       if (load == 100
+                               || cpu_threshold >= cpuhp->pass_cpu_threshold)
+                               busy_cpu++;
+               }
+
+               stats[i].num_busy_cpu = busy_cpu;
+               stats[i].avg_load = sum_load / limit_min_cpu;
+               stats[i].avg_runnable_load = sum_runnable_load / limit_min_cpu;
+               if (nr_runnings) {
+                       stats[i].avg_thread_load
+                               = (sum_load * 100) / nr_runnings;
+                       stats[i].avg_thread_runnable_load
+                               = (sum_runnable_load * 100) / nr_runnings;
+               }
+       }
+}
+
+static gboolean cpuhp_governor_timer_cb(gpointer data)
+{
+       struct pass_resource *res = (struct pass_resource *)data;
+       struct pass_level *levels = res->config_data.levels;
+       struct pass_cpuhp *cpuhp = &res->cpuhp;
+       static int count = 0;
+       double curr_gov_timeout, next_gov_timeout;
+       int level, ret;
+
+       if (!res) {
+               _E("cannot call the governor timeout callback\n");
+               return FALSE;
+       }
+
+       /*
+        * Collect data related to system state
+        * - the current frequency
+        * - the number of nr_running
+        * - the resource utilization
+        */
+       ret = pass_get_cpu_stats(res);
+       if (ret < 0) {
+               if (count++ < PASS_CPU_STATS_MAX_COUNT)
+                       return TRUE;
+
+               count = 0;
+
+               _E("cannot read the 'pass_cpu_stats' sysfs entry");
+               cpuhp_governor_update(res, PASS_OFF);
+
+               return FALSE;
+       }
+
+       /* Calculate the number of busy cpu */
+       cpuhp_calculate_busy_cpu(res);
+
+       /* Store current governor timeout */
+       curr_gov_timeout = levels[res->rescon.curr_level].gov_timeout;
+
+       /* Determine the amount of proper resource */
+       if (cpuhp->governor->governor) {
+               level = cpuhp->governor->governor(res);
+
+               pass_rescon_set_level(res, level);
+       } else {
+               _E("cannot call the governor function");
+               cpuhp_governor_update(res, PASS_OFF);
+               return FALSE;
+       }
+
+       /* Get the governor timeout interval for the next */
+       next_gov_timeout = levels[res->rescon.curr_level].gov_timeout;
+
+       /*
+        * Change the governor timeout interval when the next interval is not
+        * same as the current one
+        */
+       if (curr_gov_timeout != next_gov_timeout) {
+               _I("Change the period of governor timer from %fs to %fs\n",
+                               curr_gov_timeout,
+                               next_gov_timeout);
+               g_source_remove(cpuhp->gov_timeout_id);
+               cpuhp->gov_timeout_id = g_timeout_add(
+                               (guint)(next_gov_timeout * 1000),
+                               cpuhp_governor_timer_cb,
+                               (gpointer)res);
+       }
+
+       return TRUE;
+}
+
+static void cpuhp_governor_start(struct pass_resource *res)
+{
+       struct pass_cpuhp *cpuhp = &res->cpuhp;
+
+       if (!cpuhp->governor) {
+               _E("cannot start PASS governor");
+               return;
+       }
+
+       if (is_enabled(cpuhp)) {
+               _E("PASS governor is already active state");
+               return;
+       }
+
+       /* Add callback function for each governor timeout */
+       if (res->config_data.gov_timeout > 0) {
+               cpuhp->gov_timeout_id = g_timeout_add(
+                               (guint)(res->config_data.gov_timeout * 1000),
+                               (GSourceFunc)cpuhp_governor_timer_cb,
+                               (gpointer)res);
+               if (!cpuhp->gov_timeout_id) {
+                       _E("cannot add core timer for governor");
+                       cpuhp_governor_update(res, PASS_OFF);
+                       return;
+               }
+       } else {
+               cpuhp->gov_timeout_id = 0;
+       }
+
+       /*
+        * Set default pass level when starting pass
+        * - default pass level according to res->init_level
+        */
+       res->rescon.curr_level = -1;
+       if (res->rescon.init_level > res->rescon.max_level)
+               res->rescon.init_level = res->rescon.max_level;
+
+       pass_rescon_set_level(res, res->rescon.init_level);
+
+       /* Set PASS state as PASS_ON */
+       cpuhp->state = PASS_ON;
+
+       _I("Start governor for '%s' resource", res->config_data.res_name);
+}
+
+static void cpuhp_governor_stop(struct pass_resource *res)
+{
+       struct pass_cpuhp *cpuhp = &res->cpuhp;
+       struct pass_resource_config_data *config_data = &res->config_data;
+
+       if (!cpuhp->governor) {
+               _E("cannot stop PASS governor");
+               return;
+       }
+
+       if (cpuhp->state == PASS_OFF) {
+               _E("PASS governor is already inactive state");
+               return;
+       }
+
+       cpuhp_hotplug_stop(res);
+
+       if (cpuhp->gov_timeout_id) {
+               g_source_remove(cpuhp->gov_timeout_id);
+               cpuhp->gov_timeout_id = 0;
+       }
+
+       /* Set PASS state as PASS_OFF */
+       cpuhp->state = PASS_OFF;
+
+       _I("Stop governor for '%s' resource", config_data->res_name);
+}
+
+static int cpuhp_governor_init(struct pass_resource *res)
+{
+       struct pass_cpuhp *cpuhp = &res->cpuhp;
+
+       if (res->config_data.gov_timeout < 0) {
+               _E("invalid timeout value [%d]!", res->config_data.gov_timeout);
+               cpuhp_governor_update(res, PASS_OFF);
+               return -EINVAL;
+       }
+
+       /* Set default PASS state */
+       cpuhp->state = PASS_OFF;
+
+       if (res->config_data.state == PASS_ON)
+               cpuhp_governor_update(res, PASS_ON);
+
+       return 0;
+}
+
+static int cpuhp_governor_exit(struct pass_resource *res)
+{
+       struct pass_cpuhp *cpuhp = &res->cpuhp;
+       int i;
+
+       /*
+        * Stop timer and
+        * Restore the frequency and the number of online resources
+        */
+       cpuhp_governor_update(res, PASS_OFF);
+
+       /* Free allocated memory */
+       for (i = 0; i < cpuhp->num_pass_cpu_stats; i++) {
+               free(cpuhp->pass_cpu_stats[i].load);
+               free(cpuhp->pass_cpu_stats[i].nr_running);
+               free(cpuhp->pass_cpu_stats[i].runnable_load);
+       }
+       free(cpuhp->pass_cpu_stats);
+
+       if (cpuhp->hotplug)
+               free(cpuhp->hotplug->sequence);
+
+       /* Set pass_cpuhp structure as default value */
+       cpuhp->pass_cpu_threshold = 0;
+       cpuhp->up_threshold = 0;
+       cpuhp->down_threshold = 0;
+       cpuhp->level_up_threshold = 0;
+       cpuhp->num_pass_cpu_stats = 0;
+       cpuhp->governor = NULL;
+
+       return 0;
+}
+
+static int cpuhp_governor_update(struct pass_resource *res,
+                       enum pass_state state)
+{
+       switch (state) {
+       case PASS_ON:
+               cpuhp_governor_start(res);
+               break;
+       case PASS_OFF:
+               cpuhp_governor_stop(res);
+               break;
+       default:
+               _E("Unknown governor state");
+               return -EINVAL;
+       }
+
+       return 0;
+}
+
+/*
+ * Define CPUHP governor
+ *
+ * - Step governor
+ * - Radiation governor
+ */
+static struct pass_cpuhp_governor pass_gov_dummy = {
+       .name           = "pass_dummy",
+       .init           = cpuhp_governor_init,
+       .exit           = cpuhp_governor_exit,
+       .update         = cpuhp_governor_update,
+       .governor       = NULL,
+};
+
+static struct pass_cpuhp_governor pass_gov_step = {
+       .name           = "pass_step",
+       .init           = cpuhp_governor_init,
+       .exit           = cpuhp_governor_exit,
+       .update         = cpuhp_governor_update,
+       .governor       = pass_cpuhp_step_governor,
+};
+
+static struct pass_cpuhp_governor pass_gov_radiation = {
+       .name           = "pass_radiation",
+       .init           = cpuhp_governor_init,
+       .exit           = cpuhp_governor_exit,
+       .update         = cpuhp_governor_update,
+       .governor       = pass_cpuhp_radiation_governor,
+};
+
+/*
+ * pass_get_governor - Return specific governor instance according to type
+ * @type: the type of PASS governor
+ */
+static struct pass_cpuhp_governor* cpuhp_get_governor(struct pass_resource *res,
+                                               enum pass_gov_type type)
+{
+       switch (type) {
+       case PASS_GOV_DUMMY:
+               return NULL;
+       case PASS_GOV_BASIC:
+       case PASS_GOV_HOTPLUG_ONLY:
+               /* Use the Resource controller only */
+               return &pass_gov_dummy;
+       case PASS_GOV_STEP:
+               /* Use the Resource controller and Step governor. */
+               return &pass_gov_step;
+       case PASS_GOV_RADIATION:
+               /* Use the Resource controller and Radiation governor. */
+               return &pass_gov_radiation;
+       default:
+               _E("Unknown governor type");
+               break;
+       };
+
+       return NULL;
+}
+
+/*
+ * pass_cpuhp_init - Initialize CPUHP (CPU Hotplug Manager) module
+ *
+ * @res: the instance of struct pass_resource
+ */
+int pass_cpuhp_init(struct pass_resource *res)
+{
+       struct pass_cpuhp *cpuhp;
+       int max_freq = 0;
+       int i;
+
+       if (!res)
+               return -EINVAL;
+
+       cpuhp = &res->cpuhp;
+
+       if (!cpuhp->pass_cpu_threshold)
+               cpuhp->pass_cpu_threshold = PASS_DEFAULT_CPU_THRESHOLD;
+
+       if (!cpuhp->up_threshold)
+               cpuhp->up_threshold = PASS_DEFAULT_LEVEL_UP_THRESHOLD;
+
+       if (!cpuhp->down_threshold)
+               cpuhp->down_threshold = PASS_DEFAULT_LEVEL_DOWN_THRESHOLD;
+
+       if (!cpuhp->level_up_threshold)
+               cpuhp->level_up_threshold = 0;
+
+       if (!cpuhp->num_pass_cpu_stats)
+               cpuhp->num_pass_cpu_stats = PASS_CPU_STATS_MAX_COUNT;
+
+       for (i = 0; i < res->config_data.num_levels; i++)
+               if (max_freq < res->config_data.levels[i].limit_max_freq)
+                       max_freq = res->config_data.levels[i].limit_max_freq;
+       cpuhp->freq.max_freq = max_freq;
+
+
+       /* Allocate memory according to the number of data and cpu */
+       cpuhp->pass_cpu_stats = calloc(cpuhp->num_pass_cpu_stats,
+                                       sizeof(struct pass_cpu_stats));
+
+       for (i = 0; i < cpuhp->num_pass_cpu_stats; i++) {
+               cpuhp->pass_cpu_stats[i].load =
+                       calloc(res->config_data.num_cpus, sizeof(unsigned int));
+               cpuhp->pass_cpu_stats[i].nr_running =
+                       calloc(res->config_data.num_cpus, sizeof(unsigned int));
+               cpuhp->pass_cpu_stats[i].runnable_load =
+                       calloc(res->config_data.num_cpus, sizeof(unsigned int));
+       }
+
+       /* Get the instance of CPU Hotplug's policy */
+       cpuhp->hotplug = cpuhp_get_hotplug(res, res->config_data.gov_type);
+       if (cpuhp->hotplug) {
+               cpuhp->hotplug->sequence = calloc(res->config_data.num_cpus,
+                                               sizeof(int));
+               for (i = 0; i < res->config_data.num_cpus; i++)
+                       cpuhp->hotplug->sequence[i] = i + res->config_data.cpu;
+
+               cpuhp->hotplug->num_cpus = res->config_data.num_cpus;
+       }
+
+       /* Get the instance of CPUHP governor */
+       cpuhp->governor = cpuhp_get_governor(res, res->config_data.gov_type);
+       if (!cpuhp->governor) {
+               _E("cannot get the instance of PASS governor");
+               return -1;
+       }
+
+       if (!cpuhp->governor || !cpuhp->governor->init)
+               return -EINVAL;
+
+       return cpuhp->governor->init(res);
+}
+
+/*
+ * pass_cpuhp_exit - Exit CPUHP (CPU Hotplug Manager) module
+ *
+ * @res: the instance of struct pass_resource
+ */
+int pass_cpuhp_exit(struct pass_resource *res)
+{
+       struct pass_cpuhp *cpuhp;
+
+       if (!res)
+               return -EINVAL;
+
+       cpuhp = &res->cpuhp;
+
+       if (!cpuhp->governor || !cpuhp->governor->exit)
+               return -EINVAL;
+
+       return cpuhp->governor->exit(res);
+}
diff --git a/src/pass/pass-gov-radiation.c b/src/pass/pass-gov-radiation.c
deleted file mode 100644 (file)
index f917820..0000000
+++ /dev/null
@@ -1,221 +0,0 @@
-/*
- * PASS (Power Aware Systerm Service) Radiation governor
- *
- * Copyright (c) 2012 - 2018 Samsung Electronics Co., Ltd.
- *
- * Licensed under the Apache License, Version 2.0 (the License);
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *     http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-#include <stdbool.h>
-#include <stdio.h>
-#include <stdlib.h>
-
-#include "pass.h"
-
-/*
- * pass_radiation_governor - Check cpu state and determine the amount of resource
- *
- * @stats: structure for getting cpu frequency state from kerncel
- *
- * This function check periodically current following state of system
- * and then determine whether pass level up or down according to pass
- * policy with gathered data.
- * - current cpu frequency
- * - the number of nr_running
- * - the number of busy_cpu
- */
-int pass_radiation_governor(struct pass_resource *res)
-{
-       struct pass_level *levels = res->config_data.levels;
-       struct pass_cpuhp *cpuhp = &res->cpuhp;
-       struct pass_cpu_stats *cpu_stats = cpuhp->pass_cpu_stats;
-       int up_threshold = cpuhp->up_threshold;
-       int down_threshold = cpuhp->down_threshold;
-       int num_pass_gov = 0;
-       int level = res->rescon.curr_level;
-       int up_count = 0;
-       int down_count = 0;
-       int left_count = 0;
-       int right_count = 0;
-       bool up_condition;
-       bool down_condition;
-       bool left_condition;
-       bool right_condition;
-       int freq;
-       int nr_running;
-       int busy_cpu;
-       int i;
-       int j;
-       int64_t time;
-
-       for (i = 0; i < cpuhp->num_pass_cpu_stats; i++) {
-               time = cpu_stats[i].time;
-               freq = cpu_stats[i].freq;
-               nr_running = cpu_stats[i].nr_runnings;
-               busy_cpu = cpu_stats[i].num_busy_cpu;
-               up_condition = true;
-               down_condition = true;
-               left_condition = true;
-               right_condition = true;
-
-               if (cpuhp->last_time >= time)
-                       continue;
-               cpuhp->last_time = time;
-               num_pass_gov++;
-
-               /*
-               _I("[Level%d][%d][%lld] %d | %d | %d", level, i, time, freq,
-                                               nr_running, busy_cpu);
-               */
-
-               /* Check level up condition */
-               for (j = 0; j < levels[level].num_up_cond && up_condition; j++) {
-                       if (levels[level].up_cond[j].freq &&
-                               !(freq >= levels[level].up_cond[j].freq))
-                               up_condition = false;
-               }
-
-               if (levels[level].num_up_cond && up_condition) {
-                       up_count++;
-
-                       /*
-                       _I("[Level%d] [up_count : %2d] \
-                               freq(%d), nr_running(%d), busy_cpu(%d)",
-                               level, up_count,
-                               levels[level].up_cond[j].freq ? freq : -1,
-                       */
-               }
-
-               /* Check level down condition */
-               for (j = 0; j < levels[level].num_down_cond && down_condition; j++) {
-                       if (levels[level].down_cond[j].freq
-                               && !(freq <= levels[level].down_cond[j].freq))
-                               down_condition = false;
-               }
-
-               if (levels[level].num_down_cond && down_condition) {
-                       down_count++;
-
-                       /*
-                       _I("[Level%d] [dw_count : %2d] \
-                               freq(%d), nr_running(%d), busy_cpu(%d)",
-                               level, down_count,
-                               levels[level].down_cond[j].freq ? freq : -1,
-                       */
-               }
-
-               /* Check level right condition */
-               for (j = 0; j < levels[level].num_right_cond && right_condition; j++) {
-                       /*
-                        * If one more conditions are false among following
-                        * conditions, don't increment right_count.
-                        */
-                       if (levels[level].right_cond[j].nr_running
-                               && !(nr_running > levels[level].right_cond[j].nr_running))
-                               right_condition = false;
-
-                       if (levels[level].right_cond[j].busy_cpu
-                               && !(busy_cpu >= levels[level].right_cond[j].busy_cpu))
-                               right_condition = false;
-               }
-
-               if (levels[level].num_right_cond && right_condition) {
-                       right_count++;
-
-                       /*
-                       _I("[Level%d] [right_count : %2d] \
-                               nr_running(%d), busy_cpu(%d)",
-                               level, right_count,
-                               levels[level].right_cond[j].nr_running ? nr_running : -1,
-                               levels[level].right_cond[j].busy_cpu ? busy_cpu : -1);
-                       */
-               }
-
-               /* Check level left condition */
-               for (j = 0; j < levels[level].num_left_cond && left_condition; j++) {
-                       /*
-                        * If one more conditions are false among following
-                        * conditions, don't increment left_count.
-                        */
-                       if (levels[level].left_cond[j].nr_running
-                               && !(nr_running <= levels[level].left_cond[j].nr_running))
-                               left_condition = false;
-
-                       if (levels[level].left_cond[j].busy_cpu
-                               && !(busy_cpu < levels[level].left_cond[j].busy_cpu))
-                               left_condition = false;
-               }
-
-               if (levels[level].num_left_cond && left_condition) {
-                       left_count++;
-
-                       /*
-                       _I("[Level%d] [ left_count : %2d] \
-                               nr_running(%d), busy_cpu(%d)",
-                               level, left_count,
-                               levels[level].left_cond[j].nr_running ? nr_running : -1,
-                               levels[level].left_cond[j].busy_cpu ? busy_cpu : -1);
-                       */
-               }
-       }
-
-       if (!num_pass_gov)
-               return level;
-
-       if (up_count * 100 >= num_pass_gov * up_threshold) {
-               level += cpuhp->hotplug->num_cpus;
-
-               if (level > res->rescon.max_level)
-                       level -= cpuhp->hotplug->num_cpus;
-       } else if (down_count * 100 >= num_pass_gov * down_threshold) {
-               level -= cpuhp->hotplug->num_cpus;
-       }
-
-       if (right_count * 100 >= num_pass_gov * up_threshold) {
-               level += 1;
-
-               if (level > res->rescon.max_level)
-                       level -= 1;
-       } else if (left_count * 100 >= num_pass_gov * down_threshold) {
-               level -= 1;
-       }
-
-       /*
-       if (level == res->prev_level) {
-               for (i = num_pass_gov; i < cpuhp->num_pass_cpu_stats; i++) {
-                       time = cpu_stats[i].time;
-                       freq = cpu_stats[i].freq;
-                       nr_running = cpu_stats[i].nr_runnings;
-                       busy_cpu = cpu_stats[i].num_busy_cpu;
-
-                       _I("[Level%d][%d][%lld] %d | %d | %d",
-                                       level, i, time, freq,
-                                       nr_running, busy_cpu);
-               }
-       }
-
-       if (level != res->rescon.curr_level) {
-               _I("\n[Level%d] num_pass_gov: [%2d]", level, num_pass_gov);
-               _I("[Level%d] down_count  : %2d (%3d >= %3d)", level, down_count,
-                               down_count * 100, num_pass_gov * down_threshold);
-               _I("[Level%d] up_count    : %2d (%3d >= %3d)", level, up_count,
-                               up_count * 100, num_pass_gov * up_threshold);
-               _I("[Level%d] left_count  : %2d (%3d >= %3d)", level, left_count,
-                               left_count * 100, num_pass_gov * down_threshold);
-               _I("[Level%d] right_count : %2d (%3d >= %3d)", level, right_count,
-                               right_count * 100, num_pass_gov * up_threshold);
-       }
-       */
-
-       return level;
-}
diff --git a/src/pass/pass-gov-step.c b/src/pass/pass-gov-step.c
deleted file mode 100644 (file)
index e5e0fa0..0000000
+++ /dev/null
@@ -1,138 +0,0 @@
-/*
- * PASS (Power Aware System Service) Step governor
- *
- * Copyright (c) 2012 - 2018 Samsung Electronics Co., Ltd.
- *
- * Licensed under the Apache License, Version 2.0 (the License);
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *     http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-#include <stdbool.h>
-#include <stdio.h>
-#include <stdlib.h>
-
-#include "pass.h"
-
-/*
- * pass_step_governor - Check cpu state and determine the amount of resource
- *
- * @stats: structure for getting cpu frequency state from kerncel
- *
- * This function check periodically current following state of system
- * and then determine whether pass level up or down according to pass
- * policy with gathered data.
- * - current cpu frequency
- * - the number of nr_running
- * - the number of busy_cpu
- */
-int pass_step_governor(struct pass_resource *res)
-{
-       struct pass_level *levels = res->config_data.levels;
-       struct pass_cpuhp *cpuhp = &res->cpuhp;
-       struct pass_cpu_stats *cpu_stats = cpuhp->pass_cpu_stats;
-       int up_threshold = cpuhp->up_threshold;
-       int down_threshold = cpuhp->down_threshold;
-       int num_pass_gov = 0;
-       int level = res->rescon.curr_level;
-       int up_count = 0;
-       int up_max_count = 0;
-       int down_count = 0;
-       bool up_condition;
-       bool down_condition;
-       int freq;
-       int nr_running;
-       int busy_cpu;
-       int i;
-       int j;
-       int64_t time;
-
-       for (i = 0; i < cpuhp->num_pass_cpu_stats; i++) {
-               time = cpu_stats[i].time;
-               freq = cpu_stats[i].freq;
-               nr_running = cpu_stats[i].nr_runnings;
-               busy_cpu = cpu_stats[i].num_busy_cpu;
-               up_condition = false;
-               down_condition = false;
-
-               if (cpuhp->last_time >= time)
-                       continue;
-               cpuhp->last_time = time;
-               num_pass_gov++;
-
-               /* Check level up condition */
-               for (j = 0; j < levels[level].num_up_cond; j++) {
-                       /*
-                        * If one more conditions are false among following
-                        * conditions, don't increment up_count.
-                        */
-                       if (freq >= levels[level].up_cond[j].freq
-                               && nr_running >= levels[level].up_cond[j].nr_running
-                               && busy_cpu >= levels[level].up_cond[j].busy_cpu)
-                               up_condition = true;
-               }
-
-               if (levels[level].num_up_cond && up_condition) {
-                       up_count++;
-
-                       /*
-                       _I("[Level%d] [up_count : %2d] \
-                               freq(%d), nr_running(%d), busy_cpu(%d)",
-                               level, up_count,
-                               levels[level].up_cond[0].freq ? freq : -1,
-                               levels[level].up_cond[0].nr_running ? nr_running : -1,
-                               levels[level].up_cond[0].busy_cpu ? busy_cpu : -1);
-                       */
-               }
-
-               /* Check level down condition */
-               for (j = 0; j < levels[level].num_down_cond; j++) {
-                       /*
-                        * If one more conditions are false among following
-                        * conditions, don't increment down_count.
-                        */
-                       if (freq <= levels[level].down_cond[j].freq
-                               && nr_running < levels[level].down_cond[j].nr_running
-                               && busy_cpu < levels[level].down_cond[j].busy_cpu)
-                               down_condition = true;
-               }
-
-               if (levels[level].num_down_cond && down_condition) {
-                       down_count++;
-
-                       /*
-                       _I("[Level%d] [dw_count : %2d] \
-                               freq(%d), nr_running(%d), busy_cpu(%d)",
-                               level, down_count,
-                               levels[level].down_cond[0].freq ? freq : -1,
-                               levels[level].down_cond[0].nr_running ? nr_running : -1,
-                               levels[level].down_cond[0].busy_cpu ? busy_cpu : -1);
-                       */
-               }
-
-               if (level < res->rescon.max_level &&
-                       freq == levels[level].limit_max_freq)
-                       up_max_count++;
-       }
-
-       if (!num_pass_gov)
-               return level;
-
-       if (up_count && level < res->rescon.max_level &&
-                       up_count * 100 >= num_pass_gov * up_threshold) {
-               level += 1;
-       } else if (down_count && level > res->rescon.min_level &&
-                       down_count * 100 >= num_pass_gov * down_threshold) {
-               level -= 1;
-       }
-
-       return level;
-}
diff --git a/src/pass/pass-gov.c b/src/pass/pass-gov.c
deleted file mode 100644 (file)
index d65a2fc..0000000
+++ /dev/null
@@ -1,559 +0,0 @@
-/*
- * PASS (Power Aware System Service) Governor
- *
- * Copyright (c) 2012 - 2018 Samsung Electronics Co., Ltd.
- *
- * Licensed under the Apache License, Version 2.0 (the License);
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *     http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-#include <stdbool.h>
-#include <stdio.h>
-#include <stdlib.h>
-#include <sys/time.h>
-
-#include <pass/device-notifier.h>
-#include <pass/config-parser.h>
-
-#include "pass.h"
-#include "pass-hal.h"
-#include "pass-rescon.h"
-
-extern int pass_step_governor(struct pass_resource *res);
-extern int pass_radiation_governor(struct pass_resource *res);
-static int __pass_governor_update(struct pass_resource *, enum pass_state);
-
-#define PASS_DEFAULT_CPU_THRESHOLD             20
-#define PASS_DEFAULT_LEVEL_UP_THRESHOLD                30
-#define PASS_DEFAULT_LEVEL_DOWN_THRESHOLD      80
-#define PASS_CPU_STATS_MAX_COUNT       20
-
-struct pass_governor {
-       char name[BUFF_MAX];
-       enum pass_state state;
-
-       int (*init)(struct pass_resource *res);
-       int (*exit)(struct pass_resource *res);
-       int (*update)(struct pass_resource *res, enum pass_state state);
-       int (*governor)(struct pass_resource *res);
-};
-
-/*
- * is_enabled - Check the state of PASS governor
- * @cpuhp: the instance of struct pass_cpuhp
- *
- * Return true if the state of PASS is PASS_ON
- * Return false if the state of PASS is PASS_OFF
- */
-static bool is_enabled(struct pass_cpuhp *cpuhp)
-{
-       if (cpuhp->state != PASS_ON)
-               return false;
-
-       return true;
-}
-
-/*
- * pass_hotplug_stop - Stop PASS hotplug
- * @res: the instance of struct pass_resource
- */
-static void pass_hotplug_stop(struct pass_resource *res)
-{
-       struct pass_level *levels = res->config_data.levels;
-       int level = res->rescon.max_level;
-
-       if (!res->cpuhp.hotplug || !levels)
-               return;
-
-       res->cpuhp.hotplug->online = levels[level].limit_min_cpu;
-}
-
-static int pass_hotplug_dummy_governor(struct pass_resource *res)
-{
-       int level = res->rescon.curr_level;
-
-       return res->config_data.levels[level].limit_min_cpu;
-}
-
-static struct pass_hotplug* get_hotplug(struct pass_resource *res,
-                                       enum pass_gov_type type)
-{
-       struct pass_hotplug *hotplug;
-
-       switch (type) {
-       case PASS_GOV_DUMMY:
-       case PASS_GOV_BASIC:
-               /* Don't use Hotplug interface */
-               return NULL;
-       case PASS_GOV_HOTPLUG_ONLY:
-       case PASS_GOV_STEP:
-       case PASS_GOV_RADIATION:
-               /* Use Hotplug interface */
-               hotplug = calloc(1, sizeof(struct pass_hotplug));
-               if (!hotplug) {
-                       _E("cannot allocate the memory of struct pass_hotplug");
-                       return NULL;
-               }
-               hotplug->governor = pass_hotplug_dummy_governor;
-               return hotplug;
-       default:
-               _E("Unknown hotplug type");
-               break;
-       };
-
-       return NULL;
-}
-
-/*
- * pass_calculate_busy_cpu - Count a number of busy cpu among NR_CPUS by using
- *                          runnable_avg_sum/runnable_avg_period
- * @res: the instance of struct pass_resource
- */
-static void pass_calculate_busy_cpu(struct pass_resource *res)
-{
-       struct pass_cpuhp *cpuhp = &res->cpuhp;
-       struct pass_level *levels = res->config_data.levels;
-       struct pass_resource_config_data *config_data = &res->config_data;
-       struct pass_cpu_stats *stats = cpuhp->pass_cpu_stats;
-       unsigned int level = res->rescon.curr_level;
-       unsigned int cpu_threshold = 0;
-       unsigned int busy_cpu;
-       unsigned int cur_freq;
-       unsigned int load;
-       unsigned int sum_load;
-       unsigned int sum_runnable_load;
-       unsigned int nr_runnings;
-       int limit_min_cpu;
-       int i;
-       int j;
-
-       limit_min_cpu = levels[level].limit_min_cpu;
-
-       for (i = 0; i < cpuhp->num_pass_cpu_stats; i++) {
-               cur_freq = stats[i].freq;
-               nr_runnings = stats[i].nr_runnings;
-
-               stats[i].num_busy_cpu = 0;
-               stats[i].avg_load = 0;
-               stats[i].avg_runnable_load = 0;
-               stats[i].avg_thread_load = 0;
-               stats[i].avg_thread_runnable_load = 0;
-
-               busy_cpu = 0;
-               sum_load = 0;
-               sum_runnable_load = 0;
-
-               /* Calculate the number of busy cpu */
-               for (j = 0; j < config_data->num_cpus; j++) {
-                       load = stats[i].load[j];
-                       sum_load += stats[i].load[j];
-                       sum_runnable_load += stats[i].runnable_load[j];
-                       if (!load)
-                               continue;
-
-                       cpu_threshold =
-                               (unsigned int)(cur_freq * load)
-                                               / cpuhp->freq.max_freq;
-                       if (load == 100
-                               || cpu_threshold >= cpuhp->pass_cpu_threshold)
-                               busy_cpu++;
-               }
-
-               stats[i].num_busy_cpu = busy_cpu;
-               stats[i].avg_load = sum_load / limit_min_cpu;
-               stats[i].avg_runnable_load = sum_runnable_load / limit_min_cpu;
-               if (nr_runnings) {
-                       stats[i].avg_thread_load
-                               = (sum_load * 100) / nr_runnings;
-                       stats[i].avg_thread_runnable_load
-                               = (sum_runnable_load * 100) / nr_runnings;
-               }
-       }
-}
-
-/*
- * pass_governor_timeout_cb - Callback for each timeout interval of the governor
- * @data: the instance of struct pass_resource
-*/
-static gboolean pass_governor_timeout_cb(gpointer data)
-{
-       struct pass_resource *res = (struct pass_resource *)data;
-       struct pass_level *levels = res->config_data.levels;
-       struct pass_cpuhp *cpuhp = &res->cpuhp;
-       static int count = 0;
-       double curr_gov_timeout, next_gov_timeout;
-       int level, ret;
-
-       if (!res) {
-               _E("cannot call the governor timeout callback\n");
-               return FALSE;
-       }
-
-       /*
-        * Collect data related to system state
-        * - the current frequency
-        * - the number of nr_running
-        * - the resource utilization
-        */
-       ret = pass_get_cpu_stats(res);
-       if (ret < 0) {
-               if (count++ < PASS_CPU_STATS_MAX_COUNT)
-                       return TRUE;
-
-               count = 0;
-
-               _E("cannot read the 'pass_cpu_stats' sysfs entry");
-               __pass_governor_update(res, PASS_OFF);
-
-               return FALSE;
-       }
-
-       /* Calculate the number of busy cpu */
-       pass_calculate_busy_cpu(res);
-
-       /* Store current governor timeout */
-       curr_gov_timeout = levels[res->rescon.curr_level].gov_timeout;
-
-       /* Determine the amount of proper resource */
-       if (cpuhp->governor->governor) {
-               level = cpuhp->governor->governor(res);
-
-               pass_rescon_set_level(res, level);
-       } else {
-               _E("cannot call the governor function");
-               __pass_governor_update(res, PASS_OFF);
-               return FALSE;
-       }
-
-       /* Get the governor timeout interval for the next */
-       next_gov_timeout = levels[res->rescon.curr_level].gov_timeout;
-
-       /*
-        * Change the governor timeout interval when the next interval is not
-        * same as the current one
-        */
-       if (curr_gov_timeout != next_gov_timeout) {
-               _I("Change the period of governor timer from %fs to %fs\n",
-                               curr_gov_timeout,
-                               next_gov_timeout);
-               g_source_remove(cpuhp->gov_timeout_id);
-               cpuhp->gov_timeout_id = g_timeout_add(
-                               (guint)(next_gov_timeout * 1000),
-                               pass_governor_timeout_cb,
-                               (gpointer)res);
-       }
-
-       return TRUE;
-}
-
-/*
- * __pass_governor_start - Start PASS governor through D-Bus
- * @res: the instance of struct pass_resource
- */
-static void __pass_governor_start(struct pass_resource *res)
-{
-       struct pass_cpuhp *cpuhp = &res->cpuhp;
-
-       if (!cpuhp->governor) {
-               _E("cannot start PASS governor");
-               return;
-       }
-
-       if (is_enabled(cpuhp)) {
-               _E("PASS governor is already active state");
-               return;
-       }
-
-       /* Add callback function for each governor timeout */
-       if (res->config_data.gov_timeout > 0) {
-               cpuhp->gov_timeout_id = g_timeout_add(
-                               (guint)(res->config_data.gov_timeout * 1000),
-                               (GSourceFunc)pass_governor_timeout_cb,
-                               (gpointer)res);
-               if (!cpuhp->gov_timeout_id) {
-                       _E("cannot add core timer for governor");
-                       __pass_governor_update(res, PASS_OFF);
-                       return;
-               }
-       } else {
-               cpuhp->gov_timeout_id = 0;
-       }
-
-       /*
-        * Set default pass level when starting pass
-        * - default pass level according to res->init_level
-        */
-       res->rescon.curr_level = -1;
-       if (res->rescon.init_level > res->rescon.max_level)
-               res->rescon.init_level = res->rescon.max_level;
-
-       pass_rescon_set_level(res, res->rescon.init_level);
-
-       /* Set PASS state as PASS_ON */
-       cpuhp->state = PASS_ON;
-
-       _I("Start governor for '%s' resource", res->config_data.res_name);
-}
-
-/*
- * __pass_governor_stop - Stop PASS governor through D-Bus
- * @res: the instance of struct pass_resource
- */
-static void __pass_governor_stop(struct pass_resource *res)
-{
-       struct pass_cpuhp *cpuhp = &res->cpuhp;
-       struct pass_resource_config_data *config_data = &res->config_data;
-
-       if (!cpuhp->governor) {
-               _E("cannot stop PASS governor");
-               return;
-       }
-
-       if (cpuhp->state == PASS_OFF) {
-               _E("PASS governor is already inactive state");
-               return;
-       }
-
-       pass_hotplug_stop(res);
-
-       if (cpuhp->gov_timeout_id) {
-               g_source_remove(cpuhp->gov_timeout_id);
-               cpuhp->gov_timeout_id = 0;
-       }
-
-       /* Set PASS state as PASS_OFF */
-       cpuhp->state = PASS_OFF;
-
-       _I("Stop governor for '%s' resource", config_data->res_name);
-}
-
-static int __pass_governor_init(struct pass_resource *res)
-{
-       struct pass_cpuhp *cpuhp = &res->cpuhp;
-
-       if (res->config_data.gov_timeout < 0) {
-               _E("invalid timeout value [%d]!", res->config_data.gov_timeout);
-               __pass_governor_update(res, PASS_OFF);
-               return -EINVAL;
-       }
-
-       /* Set default PASS state */
-       cpuhp->state = PASS_OFF;
-
-       if (res->config_data.state == PASS_ON)
-               __pass_governor_update(res, PASS_ON);
-
-       return 0;
-}
-
-static int __pass_governor_exit(struct pass_resource *res)
-{
-       struct pass_cpuhp *cpuhp = &res->cpuhp;
-       int i;
-
-       /*
-        * Stop timer and
-        * Restore the frequency and the number of online resources
-        */
-       __pass_governor_update(res, PASS_OFF);
-
-       /* Free allocated memory */
-       for (i = 0; i < cpuhp->num_pass_cpu_stats; i++) {
-               free(cpuhp->pass_cpu_stats[i].load);
-               free(cpuhp->pass_cpu_stats[i].nr_running);
-               free(cpuhp->pass_cpu_stats[i].runnable_load);
-       }
-       free(cpuhp->pass_cpu_stats);
-
-       if (cpuhp->hotplug)
-               free(cpuhp->hotplug->sequence);
-
-       /* Set pass_cpuhp structure as default value */
-       cpuhp->pass_cpu_threshold = 0;
-       cpuhp->up_threshold = 0;
-       cpuhp->down_threshold = 0;
-       cpuhp->level_up_threshold = 0;
-       cpuhp->num_pass_cpu_stats = 0;
-       cpuhp->governor = NULL;
-
-       return 0;
-}
-
-static int __pass_governor_update(struct pass_resource *res,
-                       enum pass_state state)
-{
-       switch (state) {
-       case PASS_ON:
-               __pass_governor_start(res);
-               break;
-       case PASS_OFF:
-               __pass_governor_stop(res);
-               break;
-       default:
-               _E("Unknown governor state");
-               return -EINVAL;
-       }
-
-       return 0;
-}
-
-/*
- * Define PASS governor
- *
- * - Step governor
- * - Radiation governor
- */
-static struct pass_governor pass_gov_dummy = {
-       .name           = "pass_dummy",
-       .init           = __pass_governor_init,
-       .exit           = __pass_governor_exit,
-       .update         = __pass_governor_update,
-       .governor       = NULL,
-};
-
-static struct pass_governor pass_gov_step = {
-       .name           = "pass_step",
-       .init           = __pass_governor_init,
-       .exit           = __pass_governor_exit,
-       .update         = __pass_governor_update,
-
-       .governor       = pass_step_governor,
-};
-
-static struct pass_governor pass_gov_radiation = {
-       .name           = "pass_radiation",
-       .init           = __pass_governor_init,
-       .exit           = __pass_governor_exit,
-       .update         = __pass_governor_update,
-
-       .governor       = pass_radiation_governor,
-};
-
-/*
- * pass_get_governor - Return specific governor instance according to type
- * @type: the type of PASS governor
- */
-static struct pass_governor* get_governor(struct pass_resource *res,
-                                               enum pass_gov_type type)
-{
-       switch (type) {
-       case PASS_GOV_DUMMY:
-               return NULL;
-       case PASS_GOV_BASIC:
-       case PASS_GOV_HOTPLUG_ONLY:
-               /* Use the Resource controller only */
-               return &pass_gov_dummy;
-       case PASS_GOV_STEP:
-               /* Use the Resource controller and Step governor. */
-               return &pass_gov_step;
-       case PASS_GOV_RADIATION:
-               /* Use the Resource controller and Radiation governor. */
-               return &pass_gov_radiation;
-       default:
-               _E("Unknown governor type");
-               break;
-       };
-
-       return NULL;
-}
-
-/*
- * pass_governor_init - Initialize PASS governor
- * @res: the instance of struct pass_resource
- */
-int pass_governor_init(struct pass_resource *res)
-{
-       struct pass_cpuhp *cpuhp;
-       int max_freq = 0;
-       int i;
-
-       if (!res)
-               return -EINVAL;
-
-       cpuhp = &res->cpuhp;
-
-       if (!cpuhp->pass_cpu_threshold)
-               cpuhp->pass_cpu_threshold = PASS_DEFAULT_CPU_THRESHOLD;
-
-       if (!cpuhp->up_threshold)
-               cpuhp->up_threshold = PASS_DEFAULT_LEVEL_UP_THRESHOLD;
-
-       if (!cpuhp->down_threshold)
-               cpuhp->down_threshold = PASS_DEFAULT_LEVEL_DOWN_THRESHOLD;
-
-       if (!cpuhp->level_up_threshold)
-               cpuhp->level_up_threshold = 0;
-
-       if (!cpuhp->num_pass_cpu_stats)
-               cpuhp->num_pass_cpu_stats = PASS_CPU_STATS_MAX_COUNT;
-
-       for (i = 0; i < res->config_data.num_levels; i++)
-               if (max_freq < res->config_data.levels[i].limit_max_freq)
-                       max_freq = res->config_data.levels[i].limit_max_freq;
-       cpuhp->freq.max_freq = max_freq;
-
-
-       /* Allocate memory according to the number of data and cpu */
-       cpuhp->pass_cpu_stats = calloc(cpuhp->num_pass_cpu_stats,
-                                       sizeof(struct pass_cpu_stats));
-
-       for (i = 0; i < cpuhp->num_pass_cpu_stats; i++) {
-               cpuhp->pass_cpu_stats[i].load =
-                       calloc(res->config_data.num_cpus, sizeof(unsigned int));
-               cpuhp->pass_cpu_stats[i].nr_running =
-                       calloc(res->config_data.num_cpus, sizeof(unsigned int));
-               cpuhp->pass_cpu_stats[i].runnable_load =
-                       calloc(res->config_data.num_cpus, sizeof(unsigned int));
-       }
-
-       /* Get the instance of CPU Hotplug's policy */
-       cpuhp->hotplug = get_hotplug(res, res->config_data.gov_type);
-       if (cpuhp->hotplug) {
-               cpuhp->hotplug->sequence = calloc(res->config_data.num_cpus,
-                                               sizeof(int));
-               for (i = 0; i < res->config_data.num_cpus; i++)
-                       cpuhp->hotplug->sequence[i] = i + res->config_data.cpu;
-
-               cpuhp->hotplug->num_cpus = res->config_data.num_cpus;
-       }
-
-       /* Get the instance of CPUHP governor */
-       cpuhp->governor = get_governor(res, res->config_data.gov_type);
-       if (!cpuhp->governor) {
-               _E("cannot get the instance of PASS governor");
-               return -1;
-       }
-
-       if (!cpuhp->governor || !cpuhp->governor->init)
-               return -EINVAL;
-
-       return cpuhp->governor->init(res);
-}
-
-/*
- * pass_governor_exit - Exit PASS governor
- * @res: the instance of struct pass_resource
- */
-int pass_governor_exit(struct pass_resource *res)
-{
-       struct pass_cpuhp *cpuhp;
-
-       if (!res)
-               return -EINVAL;
-
-       cpuhp = &res->cpuhp;
-
-       if (!cpuhp->governor || !cpuhp->governor->exit)
-               return -EINVAL;
-
-       return cpuhp->governor->exit(res);
-}
index 03c7ea6b44a8eb14376a3caf84ccbb17ee98a9f7..9ea9e6737ba8ab077731258e50690908b0c845b0 100644 (file)
@@ -41,8 +41,8 @@
 
 extern int pass_rescon_init(struct pass_resource *res);
 extern int pass_rescon_exit(struct pass_resource *res);
-extern int pass_governor_init(struct pass_resource *res);
-extern int pass_governor_exit(struct pass_resource *res);
+extern int pass_cpuhp_init(struct pass_resource *res);
+extern int pass_cpuhp_exit(struct pass_resource *res);
 extern int pass_pmqos_init(struct pass_resource *res);
 extern int pass_pmqos_exit(struct pass_resource *res);
 
@@ -152,9 +152,9 @@ static int pass_init_resource(struct pass_resource *res)
                return ret;
        }
 
-       ret = pass_governor_init(res);
+       ret = pass_cpuhp_init(res);
        if (ret < 0) {
-               _E("cannot initialize PASS governor");
+               _E("cannot initialize PASS CPUHP");
                goto err_cpuhp;
        }
 
@@ -167,8 +167,8 @@ static int pass_init_resource(struct pass_resource *res)
        return 0;
 
 err_pmqos:
-       if (pass_governor_exit(res) < 0)
-               _E("cannot exit PASS governor");
+       if (pass_cpuhp_exit(res) < 0)
+               _E("cannot exit PASS CPUHP");
 err_cpuhp:
        if (pass_rescon_exit(res) < 0)
                _E("cannot exit PASS Resource-Controller");
@@ -183,9 +183,9 @@ static int pass_exit_resource(struct pass_resource *res)
        /* Put configuration of each resource from pass-resource*.conf */
        pass_put_each_resource_config(res);
 
-       ret = pass_governor_exit(res);
+       ret = pass_cpuhp_exit(res);
        if (ret < 0) {
-               _E("cannot exit PASS governor");
+               _E("cannot exit PASS CPUHP");
                return -1;
        }
 
index 7619c7ef41cf5f6c5cfe31461aeb00d64d76c99d..d465e337d88502f361d6b2081a2598ec41ee5420 100644 (file)
@@ -30,7 +30,7 @@
 #define PASS_LEVEL_COND_MAX    3
 
 struct pass_resource;
-struct pass_governor;
+struct pass_cpuhp_governor;
 
 /*
  * PASS Governor type
@@ -267,7 +267,7 @@ struct pass_cpuhp {
 
        int64_t last_time;
 
-       struct pass_governor *governor;
+       struct pass_cpuhp_governor *governor;
        guint gov_timeout_id;
 
        struct pass_hotplug *hotplug;