* on callback function. So, PASS must need global pass_policy instance. This
* code must be modified after changing deviced's notifier feature.
*/
-static struct pass_policy *policy_pmqos;
+static struct pass_policy *policy_pmqos[PASS_CLUSTER_MAX];
+static int num_policy_pmqos = 0;
/*
* is_pmqos_enabled - Check state of whether to support PM_QOS for scenario
* pass_notifier_pmqos - Callback function of DEVICE_NOTIFIER_PMQOS notifier
* @data: the scenario name
*/
-static int pass_notifier_pmqos(void *data)
+
+static int pass_notifier_pmqos_func(struct pass_policy *policy, void *data)
{
- struct pass_policy *policy = policy_pmqos;
struct pass_scenario_policy *scenario = &policy->scenario;
struct pass_scenario *scn = NULL;
enum pass_state locked = PASS_UNUSED;
return 0;
}
+static int pass_notifier_pmqos(void *data)
+{
+ int i;
+
+ if (num_policy_pmqos == 0)
+ return 0;
+
+ for (i = 0; i < num_policy_pmqos; i++) {
+ if (policy_pmqos[i]->state == PASS_ON
+ && policy_pmqos[i]->governor != NULL) {
+ pass_notifier_pmqos_func(policy_pmqos[i], data);
+ }
+ }
+
+ return 0;
+}
+
/*
* pass_notifier_booting_done - Callback function of DEVICE_NOTIFIER_BOOTING_
* DONE notifier
*/
static int pass_notifier_booting_done(void *data)
{
- if (!policy_pmqos)
+ int i;
+
+ if (num_policy_pmqos == 0)
return 0;
/* Start PASS governor if 'pass_support' in pass.conf is true */
- if (policy_pmqos->state == PASS_ON && policy_pmqos->governor)
- policy_pmqos->governor->update(policy_pmqos, PASS_GOV_START);
+ for (i = 0; i < num_policy_pmqos; i++) {
+ if (policy_pmqos[i]->state == PASS_ON
+ && policy_pmqos[i]->governor != NULL) {
+ policy_pmqos[i]->governor->update(policy_pmqos[i],
+ PASS_GOV_START);
+ }
+ }
return 0;
}
* instance. This code must be modified after changing deviced's
* notifier feature.
*/
- policy_pmqos = policy;
+ policy_pmqos[num_policy_pmqos++] = policy;
return 0;
}
return policy->pass_table[level].limit_max_cpu;
}
-/*
- * Define PASS hotplug
- *
- * - Dummy hotplug
- */
-static struct pass_hotplug pass_hotplug_dummy = {
- .name = "pass_hotplug_dummy",
- .governor = pass_hotplug_dummy_governor,
-};
-
/*
* pass_get_governor - Return specific hotplug instance according to type
*
struct pass_hotplug* pass_get_hotplug(struct pass_policy *policy,
enum pass_gov_type type)
{
+ struct pass_hotplug *hotplug;
+
switch (type) {
case PASS_GOV_STEP:
case PASS_GOV_RADIATION:
- return &pass_hotplug_dummy;
+ hotplug = malloc(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;
else
online = 1;
- curr_max_freq = get_cpufreq_scaling_max_freq();
- curr_min_freq = get_cpufreq_scaling_min_freq();
+ curr_max_freq = get_cpufreq_scaling_max_freq(policy->cluster.cpu);
+ curr_min_freq = get_cpufreq_scaling_min_freq(policy->cluster.cpu);
- set_cpufreq_scaling_min_freq(curr_max_freq);
+ set_cpufreq_scaling_min_freq(policy->cluster.cpu, curr_max_freq);
pass_hotplug_set_online(policy, online);
- set_cpufreq_scaling_min_freq(curr_min_freq);
+ set_cpufreq_scaling_min_freq(policy->cluster.cpu, curr_min_freq);
+
}
/* Set maximum CPU frequency */
- set_cpufreq_scaling_max_freq(limit_max_freq);
+ set_cpufreq_scaling_max_freq(policy->cluster.cpu, limit_max_freq);
/*
- _I("Level %4s '%d->%d' : '%d'Hz/'%d'Core\n",
+ _I("[PASS %d] Level %4s '%d->%d' : '%d'Hz/'%d'Core\n",
+ policy->cluster.id,
(curr_level > new_level ? "DOWN" : "UP"),
curr_level, new_level, limit_max_freq, limit_max_cpu);
*/
return -EINVAL;
}
+ _I("Initialize PASS (Power Aware System Service)");
+
/* Set default PASS state */
policy->gov_state = PASS_GOV_STOP;
/* Initialize notifier */
pass_notifier_init(policy);
- _I("Initialize PASS (Power Aware System Service)");
-
return 0;
}
if (policy->hotplug)
free(policy->hotplug->sequence);
+ if (num_policy_pmqos > 0) {
+ for (i = 0; i < num_policy_pmqos; i++)
+ policy_pmqos[i] = NULL;
+ num_policy_pmqos = 0;
+ }
+
/* Set pass_policy structure as default value */
policy->pass_cpu_threshold = 0;
policy->up_threshold = 0;
#define BUFF_MAX 255
/* Linux standard sysfs node */
-#define CPUFREQ_SCALING_MAX_FREQ "/sys/devices/system/cpu/cpu0/cpufreq/scaling_max_freq"
-#define CPUFREQ_SCALING_MIN_FREQ "/sys/devices/system/cpu/cpu0/cpufreq/scaling_min_freq"
-#define CPUFREQ_SAMPLING_RATE "/sys/devices/system/cpu/cpufreq/ondemand/sampling_rate"
-#define CPUFREQ_UP_THRESHOLD "/sys/devices/system/cpu/cpufreq/ondemand/up_threshold"
-
-#define PROC_DT_COMPATIBLE "/proc/device-tree/compatible"
-
-/* PASS specific sysfs node */
-#define PASS_CPU_STATS "/sys/kernel/debug/cpufreq/cpu0/load_table"
+#define CPU_KERNEL_MAX "/sys/devices/system/cpu/kernel_max"
+#define PROC_DT_COMPATIBLE "/proc/device-tree/compatible"
int get_pass_cpu_stats(struct pass_policy *policy)
{
struct pass_cpu_stats *stats = policy->pass_cpu_stats;
- char path[PATH_MAX] = PASS_CPU_STATS;
char str[BUFF_MAX];
FILE *fp_stats = NULL;
int i, j;
int ret = 1;
- if (!stats) {
+ if (!policy || !policy->cluster.path_load_table || !stats) {
_E("invalid parameter of structure pass_cpu_stats");
return -EINVAL;
}
- fp_stats = fopen(path, "r");
+ fp_stats = fopen(policy->cluster.path_load_table, "r");
if (fp_stats == NULL)
return -EIO;
/*
* Get/Set maximum cpu frequency
*/
-#define GET_VALUE(name, path) \
-int get_##name(void) \
-{ \
- int value, ret; \
- \
- ret = sys_get_int(path, &value); \
- if (ret < 0) \
- return -EAGAIN; \
- \
- return value; \
-} \
-
-#define SET_VALUE(name, path) \
-int set_##name(int value) \
-{ \
- return sys_set_int(path, value); \
-} \
-
-GET_VALUE(cpufreq_scaling_max_freq, CPUFREQ_SCALING_MAX_FREQ);
-SET_VALUE(cpufreq_scaling_max_freq, CPUFREQ_SCALING_MAX_FREQ);
-
-GET_VALUE(cpufreq_scaling_min_freq, CPUFREQ_SCALING_MIN_FREQ);
-SET_VALUE(cpufreq_scaling_min_freq, CPUFREQ_SCALING_MIN_FREQ);
-
-GET_VALUE(cpufreq_sampling_rate, CPUFREQ_SAMPLING_RATE);
-SET_VALUE(cpufreq_sampling_rate, CPUFREQ_SAMPLING_RATE);
-
-GET_VALUE(cpufreq_up_threshold, CPUFREQ_UP_THRESHOLD);
-SET_VALUE(cpufreq_up_threshold, CPUFREQ_UP_THRESHOLD);
+int get_cpufreq_scaling_max_freq(int cpu)
+{
+ char path[BUFF_MAX];
+ int online;
+ int ret;
+
+ ret = sprintf(path,
+ "/sys/devices/system/cpu/cpu%d/cpufreq/scaling_max_freq", cpu);
+ if (ret < 0)
+ return -EINVAL;
+
+ ret = sys_get_int(path, &online);
+ if (ret < 0)
+ return -EAGAIN;
+
+ return online;
+}
+
+int set_cpufreq_scaling_max_freq(int cpu, int freq)
+{
+ char path[BUFF_MAX];
+ int ret;
+
+ ret = sprintf(path,
+ "/sys/devices/system/cpu/cpu%d/cpufreq/scaling_max_freq", cpu);
+ if (ret < 0) {
+ return -EINVAL;
+ }
+
+ ret = sys_set_int(path, freq);
+ if (ret < 0) {
+ return -EAGAIN;
+ }
+
+ return 0;
+}
+
+int get_cpufreq_scaling_min_freq(int cpu)
+{
+ char path[BUFF_MAX];
+ int online;
+ int ret;
+
+ ret = sprintf(path,
+ "/sys/devices/system/cpu/cpu%d/cpufreq/scaling_min_freq", cpu);
+ if (ret < 0)
+ return -EINVAL;
+
+ ret = sys_get_int(path, &online);
+ if (ret < 0)
+ return -EAGAIN;
+
+ return online;
+}
+
+int set_cpufreq_scaling_min_freq(int cpu, int freq)
+{
+ char path[BUFF_MAX];
+ int ret;
+
+ ret = sprintf(path,
+ "/sys/devices/system/cpu/cpu%d/cpufreq/scaling_min_freq", cpu);
+ if (ret < 0) {
+ return -EINVAL;
+ }
+
+ ret = sys_set_int(path, freq);
+ if (ret < 0) {
+ return -EAGAIN;
+ }
+
+ return 0;
+}
int get_cpu_online(int cpu)
{
return 0;
}
+int get_num_cpus(void)
+{
+ int num_cpus;
+ int ret;
+
+ ret = sys_get_int(CPU_KERNEL_MAX, &num_cpus);
+ if (ret < 0)
+ return -EAGAIN;
+
+ /*
+ * Return the number of cpus with plus 1 because of index of first CPU
+ * is 0 (zero). (e.g., Octa cores have the '7' value of CPU_KERNEL_MAX)
+ */
+ return (num_cpus + 1);
+}
+
/***************************************************************************
* Parse pass.conf *
***************************************************************************/
if (MATCH(result->name, "pass_compatible")) {
char compatible[BUFF_MAX];
+ int len;
ret = sys_read_buf(PROC_DT_COMPATIBLE, compatible);
if (ret < 0)
return -EEXIST;
- if (strcmp(compatible, result->value))
+ len = strlen(result->value);
+ if (strncmp(compatible, result->value, len)) {
+ _I("Mismatch compatible string : %s\n", result->value);
return -EINVAL;
-
- _I("Match compatible string : %s\n", compatible);
+ }
} else if (MATCH(result->name, "pass_support"))
policy->state = atoi(result->value);
else if (MATCH(result->name, "pass_gov_type"))
free(policy->scenario.list);
}
+static int pass_parse_cpu_cluster_data(struct parse_result *result,
+ void *user_data, int id)
+{
+ struct pass_cluster *cluster = user_data;
+ char section_name[BUFF_MAX];
+ int i, ret;
+
+ if (!result)
+ return 0;
+
+ if (MATCH(result->name, "pass_cpu_cluster_id")) {
+ cluster->cpu[id].id = atoi(result->value);
+ } else if (MATCH(result->name, "pass_cpu_cluster_first_cpu")) {
+ cluster->cpu[id].cpu = atoi(result->value);
+ } else if (MATCH(result->name, "pass_cpu_cluster_path_conf_file")) {
+ int len = strlen(result->value);
+ strncpy(cluster->cpu[id].path_conf_file, result->value, len);
+ } else if (MATCH(result->name, "pass_cpu_cluster_path_load_table")) {
+ int len = strlen(result->value);
+ strncpy(cluster->cpu[id].path_load_table, result->value, len);
+ }
+
+ return 0;
+}
+
+static int pass_cluster_config(struct parse_result *result, void *user_data)
+{
+ struct pass_cluster *cluster = user_data;
+ char section_name[BUFF_MAX];
+ int id, ret;
+
+ if (!result)
+ return 0;
+
+ if (!result->section || !result->name || !result->value)
+ return 0;
+
+ /* Parsing 'PassCluster' section */
+ if (MATCH(result->section, "PassCluster")) {
+ if (MATCH(result->name, "pass_compatible")) {
+ char compatible[BUFF_MAX];
+ int len;
+
+ ret = sys_get_str(PROC_DT_COMPATIBLE, compatible);
+ if (ret < 0)
+ return -EEXIST;
+
+ len = strlen(result->value);
+ if (strncmp(compatible, result->value, len)) {
+ _I("Mismatch compatible string : %s\n",
+ result->value);
+ return -EINVAL;
+ }
+ } else if (MATCH(result->name, "pass_num_cpu_clusters")) {
+ cluster->num_cpu_clusters = atoi(result->value);
+ } else {
+ _E("cannot parse the number of cluster\n");
+ return -ENOENT;
+ }
+ }
+
+ /* Parsing 'ClusterX' section */
+ for (id = 0; id < cluster->num_cpu_clusters; id++) {
+ ret = sprintf(section_name, "CpuCluster%d", id);
+
+ if (MATCH(result->section, section_name)) {
+ ret = pass_parse_cpu_cluster_data(result, user_data, id);
+ if (ret < 0) {
+ _E("cannot parse 'CpuCluster' section\n");
+ return ret;
+ }
+ }
+ }
+
+ return 0;
+}
+
+int get_pass_cluster(struct pass_cluster *cluster, char *pass_conf_path)
+{
+ int ret;
+
+ ret = config_parse(pass_conf_path, pass_cluster_config, cluster);
+ if (ret < 0) {
+ _E("cannot parse %s\n", pass_conf_path);
+ return -EINVAL;
+ }
+
+ return 0;
+}
+
/*
* get_time_ms - Return current time (unit: millisecond)
*/
int get_pass_table(struct pass_policy *policy, char *pass_conf_path);
void put_pass_table(struct pass_policy *policy);
-int get_cpufreq_scaling_max_freq(void);
-int set_cpufreq_scaling_max_freq(int);
+int get_cpufreq_scaling_max_freq(int cpu);
+int set_cpufreq_scaling_max_freq(int cpu, int freq);
-int get_cpufreq_scaling_min_freq(void);
-int set_cpufreq_scaling_min_freq(int);
-
-int get_cpufreq_sampling_rate(void);
-int set_cpufreq_sampling_rate(int);
-
-int get_cpufreq_up_threshold(void);
-int set_cpufreq_up_threshold(int);
+int get_cpufreq_scaling_min_freq(int cpu);
+int set_cpufreq_scaling_min_freq(int cpu, int freq);
int get_cpu_online(int);
int set_cpu_online(int, int);
+int get_num_cpus(void);
+
int64_t get_time_ms(void);
#endif /* __PASS_PLUGIN__ */
+++ /dev/null
-/*
- * deviced
- *
- * Copyright (c) 2012 - 2015 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.
- */
-
-#ifndef __PASS_TARGET__
-#define __PASS_TARGET__
-
-enum pass_target_type {
- PASS_TARGET_UNKNOWN = 0,
- PASS_TARGET_REDWOOD_EXYNOS4412_STEP,
- PASS_TARGET_REDWOOD_EXYNOS4412_RADIATION,
- PASS_TARGET_W_EXYNOS4212,
-
- PASS_TARGET_TYPE_END,
-};
-
-#endif /* __PASS_TARGET__ */
#include "pass.h"
#include "pass-core.h"
-#include "pass-target.h"
+#include "pass-plugin.h"
#include "core/devices.h"
#include "core/common.h"
/*
* Per-target pass policy
*/
-static struct pass_policy policy;
+static struct pass_policy *policy_list;
+static struct pass_cluster cluster;
/******************************************************
* PASS D-Bus interface *
******************************************************/
static DBusMessage* e_dbus_start_cb(E_DBus_Object *obj, DBusMessage* msg)
{
- if (policy.governor)
- policy.governor->update(&policy, PASS_GOV_START);
- return dbus_message_new_method_return(msg);
+ DBusMessage *ret = NULL;
+ int i;
+
+ for (i = 0; i < cluster.num_cpu_clusters; i++) {
+ if (policy_list[i].governor)
+ policy_list[i].governor->update(&policy_list[i],
+ PASS_GOV_START);
+ ret = dbus_message_new_method_return(msg);
+ if (!ret)
+ return ret;
+ }
+
+ return ret;
}
static DBusMessage* e_dbus_stop_cb(E_DBus_Object *obj, DBusMessage* msg)
{
- if (policy.governor)
- policy.governor->update(&policy, PASS_GOV_STOP);
- return dbus_message_new_method_return(msg);
+ DBusMessage *ret = NULL;
+ int i;
+
+ for (i = 0; i < cluster.num_cpu_clusters; i++) {
+ if (policy_list[i].governor)
+ policy_list[i].governor->update(&policy_list[i], PASS_GOV_STOP);
+ ret = dbus_message_new_method_return(msg);
+ if (!ret)
+ return ret;
+ }
+
+ return ret;
}
static const struct edbus_method edbus_methods[] = {
* PASS interface (Init/Exit) *
******************************************************/
-/*
- * pass_init - Initialize PASS(Power Aware System Service)
- *
- * @data: the instance of structre pass_policy
- */
-static void pass_init(void *data)
+static int pass_cluster_init(struct pass_policy *policy)
{
- enum pass_target_type target_type;
int max_freq = 0;
int max_cpu = 0;
int ret;
int i;
- /*
- * Initialize pass-table by parsing pass.conf
- */
- ret = get_pass_table(&policy, PASS_CONF_PATH);
- if (ret < 0) {
- _E("cannot parse %s\n", PASS_CONF_PATH);
- return;
+ if (!policy) {
+ _E("cannot initialize PASS\n");
+ return -1;
}
/*
- * Initialzie D-Bus interface of PASS. User can be able to
- * turn on/off PASS through D-Bus interface.
+ * Initialize pass-table by parsing pass.conf
*/
- ret = register_edbus_interface_and_method(DEVICED_PATH_PASS,
- DEVICED_INTERFACE_PASS,
- edbus_methods,
- ARRAY_SIZE(edbus_methods));
+ ret = get_pass_table(policy, policy->cluster.path_conf_file);
if (ret < 0) {
- _I("cannot initialize PASS D-Bus (%d)", ret);
- return;
+ _E("cannot parse %s\n", policy->cluster.path_conf_file);
+ return -1;
}
/* Check whether PASS is initialzied state or not */
- if (policy.governor) {
+ if (policy->governor) {
_I("PASS is already active state");
- return;
+ return -1;
}
/*
* Set default value to global pass_policy instance
* if variable isn't initialized.
*/
- if (!policy.min_level)
- policy.min_level = PASS_DEFAULT_MIN_LEVEL;
- policy.default_min_level = policy.min_level;
+ if (!policy->min_level)
+ policy->min_level = PASS_DEFAULT_MIN_LEVEL;
+ policy->default_min_level = policy->min_level;
- if (!policy.max_level)
- policy.max_level = policy.num_levels - 1;
- policy.default_max_level = policy.max_level;
+ if (!policy->max_level)
+ policy->max_level = policy->num_levels - 1;
+ policy->default_max_level = policy->max_level;
- if (!policy.init_level)
- policy.init_level = PASS_DEFAULT_MIN_LEVEL;
+ if (!policy->init_level)
+ policy->init_level = PASS_DEFAULT_MIN_LEVEL;
- if (!policy.pass_cpu_threshold)
- policy.pass_cpu_threshold = PASS_DEFAULT_CPU_THRESHOLD;
+ if (!policy->pass_cpu_threshold)
+ policy->pass_cpu_threshold = PASS_DEFAULT_CPU_THRESHOLD;
- if (!policy.up_threshold)
- policy.up_threshold = PASS_DEFAULT_LEVEL_UP_THRESHOLD;
+ if (!policy->up_threshold)
+ policy->up_threshold = PASS_DEFAULT_LEVEL_UP_THRESHOLD;
- if (!policy.down_threshold)
- policy.down_threshold = PASS_DEFAULT_LEVEL_DOWN_THRESHOLD;
+ if (!policy->down_threshold)
+ policy->down_threshold = PASS_DEFAULT_LEVEL_DOWN_THRESHOLD;
- if (!policy.level_up_threshold)
- policy.level_up_threshold = policy.max_level;
+ if (!policy->level_up_threshold)
+ policy->level_up_threshold = policy->max_level;
- if (!policy.num_pass_cpu_stats)
- policy.num_pass_cpu_stats = PASS_CPU_STATS_DEFAULT;
+ if (!policy->num_pass_cpu_stats)
+ policy->num_pass_cpu_stats = PASS_CPU_STATS_DEFAULT;
- for (i = 0; i < policy.num_levels; i++) {
- if (max_freq < policy.pass_table[i].limit_max_freq)
- max_freq = policy.pass_table[i].limit_max_freq;
- if (max_cpu < policy.pass_table[i].limit_max_cpu)
- max_cpu = policy.pass_table[i].limit_max_cpu;
+ for (i = 0; i < policy->num_levels; i++) {
+ if (max_freq < policy->pass_table[i].limit_max_freq)
+ max_freq = policy->pass_table[i].limit_max_freq;
+ if (max_cpu < policy->pass_table[i].limit_max_cpu)
+ max_cpu = policy->pass_table[i].limit_max_cpu;
}
- policy.cpufreq.max_freq = max_freq;
- policy.cpufreq.num_nr_cpus = max_cpu;
+ policy->cpufreq.max_freq = max_freq;
+ policy->cpufreq.num_nr_cpus = max_cpu;
/* Allocate memory according to the number of data and cpu */
- policy.pass_cpu_stats = malloc(sizeof(struct pass_cpu_stats)
- * policy.num_pass_cpu_stats);
-
- for (i = 0; i < policy.num_pass_cpu_stats; i++) {
- policy.pass_cpu_stats[i].load =
- malloc(sizeof(unsigned int) * policy.cpufreq.num_nr_cpus);
- policy.pass_cpu_stats[i].nr_running =
- malloc(sizeof(unsigned int) * policy.cpufreq.num_nr_cpus);
- policy.pass_cpu_stats[i].runnable_load =
- malloc(sizeof(unsigned int) * policy.cpufreq.num_nr_cpus);
+ policy->pass_cpu_stats = malloc(sizeof(struct pass_cpu_stats)
+ * policy->num_pass_cpu_stats);
+
+ for (i = 0; i < policy->num_pass_cpu_stats; i++) {
+ policy->pass_cpu_stats[i].load =
+ malloc(sizeof(unsigned int) * policy->cpufreq.num_nr_cpus);
+ policy->pass_cpu_stats[i].nr_running =
+ malloc(sizeof(unsigned int) * policy->cpufreq.num_nr_cpus);
+ policy->pass_cpu_stats[i].runnable_load =
+ malloc(sizeof(unsigned int) * policy->cpufreq.num_nr_cpus);
}
/* Get the instance of PASS governor */
- policy.governor = pass_get_governor(&policy, policy.gov_type);
- if (!policy.governor) {
+ policy->governor = pass_get_governor(policy, policy->gov_type);
+ if (!policy->governor) {
_E("cannot get the instance of PASS governor");
- return;
+ return -1;
}
- policy.governor->gov_timeout = policy.gov_timeout;
+ policy->governor->gov_timeout = policy->gov_timeout;
/* Get the instance of PASS hotplulg */
- policy.hotplug = pass_get_hotplug(&policy, policy.gov_type);
- if (!policy.hotplug) {
+ policy->hotplug = pass_get_hotplug(policy, policy->gov_type);
+ if (!policy->hotplug) {
_E("cannot get the instance of PASS hotplug");
} else {
- policy.hotplug->sequence = malloc(sizeof(int)
- * policy.cpufreq.num_nr_cpus);
- for (i = 0; i < policy.cpufreq.num_nr_cpus; i++)
- policy.hotplug->sequence[i] = i;
+ policy->hotplug->sequence = malloc(sizeof(int)
+ * policy->cpufreq.num_nr_cpus);
+ for (i = 0; i < policy->cpufreq.num_nr_cpus; i++)
+ policy->hotplug->sequence[i] = i + policy->cluster.cpu;
}
- if (policy.governor->init) {
- ret = policy.governor->init(&policy);
+ if (policy->governor->init) {
+ ret = policy->governor->init(policy);
if (ret < 0) {
_E("cannot initialize PASS governor");
- return;
+ return -1;
}
} else {
_E("cannot execute init() of PASS governor");
- return;
+ return -1;
}
+
+ return 0;
}
-/*
- * pass_exit - Exit PASS
- *
- * @data: the instance of structre pass_policy
- */
-static void pass_exit(void *data)
+static int pass_cluster_exit(struct pass_policy *policy)
{
int ret;
- if (!policy.governor) {
+ if (!policy->governor) {
_E("cannot exit PASS");
- return;
+ return -1;
}
- put_pass_table(&policy);
+ put_pass_table(policy);
- if (policy.governor->exit) {
- ret = policy.governor->exit(&policy);
+ if (policy->governor->exit) {
+ ret = policy->governor->exit(policy);
if (ret < 0) {
_E("cannot exit PASS governor");
- return;
+ return -1;
}
} else {
_E("cannot execute exit() of PASS governor");
+ return -1;
+ }
+
+ policy->governor = NULL;
+
+ return 0;
+}
+
+/*
+ * pass_init - Initialize PASS(Power Aware System Service)
+ *
+ * @data: the instance of structre pass_policy
+ */
+
+static void pass_init(void *data2)
+{
+ int i, ret;
+
+ /*
+ * Initialize pass cluster data by parsing pass.conf
+ */
+ ret = get_pass_cluster(&cluster, "/etc/deviced/pass.conf");
+ if (ret < 0) {
+ _E("cannot parse /etc/deviced/pass.conf\n");
+ return -1;
+ }
+
+ policy_list = malloc(sizeof(struct pass_policy)
+ * cluster.num_cpu_clusters);
+ if (!policy_list) {
+ _E("cannot allocate the memory for pass_policy array\n");
+ return;
+ }
+
+ if (!policy_list) {
+ _E("cannot allocate the memory for pass_policy array\n");
+ return;
+ }
+
+ for (i = 0; i < cluster.num_cpu_clusters; i++) {
+ policy_list[i].cluster.id = cluster.cpu[i].id;
+ policy_list[i].cluster.cpu = cluster.cpu[i].cpu;
+ strcpy(policy_list[i].cluster.path_conf_file, cluster.cpu[i].path_conf_file);
+ strcpy(policy_list[i].cluster.path_load_table, cluster.cpu[i].path_load_table);
+
+ _I("i(%d) PASS: %d\n", i, policy_list[i].cluster.id);
+ _I("i(%d) PASS: %d\n", i, policy_list[i].cluster.cpu);
+ _I("i(%d) PASS: %s\n", i, policy_list[i].cluster.path_conf_file);
+ _I("i(%d) PASS: %s\n", i, policy_list[i].cluster.path_load_table);
+ }
+
+ /*
+ * Initialzie D-Bus interface of PASS. User can be able to
+ * turn on/off PASS through D-Bus interface.
+ */
+ ret = register_edbus_interface_and_method(DEVICED_PATH_PASS,
+ DEVICED_INTERFACE_PASS,
+ edbus_methods,
+ ARRAY_SIZE(edbus_methods));
+ if (ret < 0) {
+ _I("cannot initialize PASS D-Bus (%d)", ret);
return;
}
- policy.governor = NULL;
+ for (i = 0; i < cluster.num_cpu_clusters; i++) {
+ ret = pass_cluster_init(&policy_list[i]);
+ if (ret < 0) {
+ _E("cannot initialize the pass cluster\n");
+ return;
+ }
+ }
+}
+
+/*
+ * pass_exit - Exit PASS
+ *
+ * @data: the instance of structre pass_policy
+ */
+static void pass_exit(void *data)
+{
+ int i;
+
+ for (i = 0; i < cluster.num_cpu_clusters; i++) {
+ pass_cluster_exit(&policy_list[i]);
}
static const struct device_ops pass_device_ops = {
#define PASS_LEVEL_COND_MAX 3
#define PASS_CPU_STATS_DEFAULT 20
#define PASS_MIN_GOV_TIMEOUT 0.2
+#define PASS_MAX_CLUSTER 2
-#define PASS_CONF_PATH "/etc/deviced/pass.conf"
+#define PASS_CLUSTER_0 0
+#define PASS_CLUSTER_1 1
+#define PASS_CLUSTER_MAX 2
struct pass_policy;
/*
* struct pass_cpu_stats
*
+ * @path: the path of load_table on kernel interface
* @time: current time
* @freq: current cpu frequency
* @freq: new cpu frequency
* @avg_thread_runnable_load: the Per-thread runnable load
*/
struct pass_cpu_stats {
+ const char *path;
+
int64_t time;
unsigned int freq;
unsigned int freq_new;
unsigned int avg_thread_runnable_load;
};
+/******************************************************
+ * PASS cluster data *
+ ******************************************************/
+/*
+ * struct pass_cluster_data - Include the specific data of each cluster
+ *
+ * @id: the unique id of cluster
+ * @cpu: the first cpu in cluster
+ * @path_conf_file: the path for PASS configuration file
+ * @path_load_table: the path for load_table entry from kernel
+ */
+struct pass_cluster_data {
+ unsigned int id;
+ unsigned int cpu;
+ char path_conf_file[128];
+ char path_load_table[128];
+};
+
+/*
+ * struct pass_cluster - Include the information of all clusters
+ *
+ * @num_cluster: the number of supported clusters
+ */
+struct pass_cluster {
+ unsigned int num_cpu_clusters;
+ struct pass_cluster_data cpu[PASS_MAX_CLUSTER];
+};
+
/******************************************************
* PASS interface *
******************************************************/
struct pass_governor *governor;
double gov_timeout;
struct pass_hotplug *hotplug;
+
+ struct pass_cluster_data cluster;
};
#endif /* __pass__ */