#include "pass.h"
#include "pass-gov.h"
+#include "pass-pmqos.h"
#include "pass-plugin.h"
#include "core/device-notifier.h"
#define PASS_CPU_STATS_MAX_COUNT 20
-/*
- * is_enabled - Check the state of PASS governor
- * @policy: instance of pass_policy structure
- *
- * Return true if the state of PASS is PASS_GOV_START
- * Return false if the state of PASS is PASS_GOV_STOP
- */
-static bool is_enabled(struct pass_policy *policy)
-{
- if (!policy)
- return false;
-
- if (policy->gov_state != PASS_GOV_START)
- return false;
-
- return true;
-}
-
-/****************************************************************************
- * PASS Notifier *
- * - DEVICE_NOTIFIER_PMQOS *
- * - DEVICE_NOTIFIER_BOOTING_DONE *
- ****************************************************************************/
-#define PASS_LOCK "Lock"
-#define PASS_UNLOCK "Unlock"
-
-static int pass_governor_change_level_scope(struct pass_policy *policy,
- int min_level, int max_level);
-
/*
* FIXME: Current notifier of deviced didn't pass separate user_data parameter
* on callback function. So, PASS must need global pass_policy instance. This
static int num_policy_pmqos = 0;
/*
- * is_pmqos_enabled - Check state of whether to support PM_QOS for scenario
+ * is_enabled - Check the state of PASS governor
* @policy: instance of pass_policy structure
*
- * Return true if the state of PM_QOS is supported
- * Return false if the state of PM_QOS isn't supported
+ * Return true if the state of PASS is PASS_GOV_START
+ * Return false if the state of PASS is PASS_GOV_STOP
*/
-static bool is_pmqos_enabled(struct pass_policy *policy)
+static bool is_enabled(struct pass_policy *policy)
{
if (!policy)
return false;
- if (!policy->scenario.list)
- return false;
-
- if (policy->scenario.state != PASS_ON)
+ if (policy->gov_state != PASS_GOV_START)
return false;
return true;
}
/*
- * is_scenario_locked - Check locked state of each scenario
- * @policy: instance of pass_scenario structure
- *
- * Return true if scenario is locked and enabled
- * Return false if scenario is unlocked or disabled
- */
-
-static bool is_scenario_locked(struct pass_scenario *scn)
-{
- if (!scn)
- return false;
-
- if (!scn->locked || scn->state != PASS_ON)
- return false;
-
- return true;
-}
-
-static enum pass_state is_pmqos_locked(char *data, char *name)
-{
- char *unlock = NULL;
-
- if (!data)
- return PASS_OFF;
-
- unlock = strstr(data, PASS_UNLOCK);
- if (!unlock) {
- /* Lock scenario */
- strncpy(name, data, strlen(data) - strlen(PASS_LOCK));
- return PASS_ON;
- } else {
- /* Unlock scenario */
- strncpy(name, data, strlen(data) - strlen(PASS_UNLOCK));
- return PASS_OFF;
- }
-}
-
-static int find_scenario_index(struct pass_scenario_policy *scenario,
- char *name)
-{
- int index;
-
- for (index = 0; index < scenario->num_scenarios; index++)
- if (MATCH(scenario->list[index].name, name))
- return index;
-
- return -EINVAL;
-}
-
-/*
- * pass_notifier_pmqos - Callback function of DEVICE_NOTIFIER_PMQOS notifier
- * @data: the scenario name
+ * pass_notifier_booting_done - Callback function of DEVICE_NOTIFIER_BOOTING_
+ * DONE notifier
+ * @data: NULL, this parameter isn't used
*/
-
-static int pass_notifier_pmqos_func(struct pass_policy *policy, void *data)
-{
- struct pass_scenario_policy *scenario = &policy->scenario;
- struct pass_scenario *scn = NULL;
- enum pass_state locked = PASS_UNUSED;
- char name[PASS_NAME_LEN] = {""};
- unsigned int cpufreq_min_level = 0;
- unsigned int cpufreq_max_level = 0;
- int count = 0;
- int index = -1;
- int i;
-
- if (!is_enabled(policy))
- return 0;
-
- if (!is_pmqos_enabled(policy))
- return 0;
-
- /*
- * Parse scenario name(data) whether to include 'Lock' or 'Unlock'
- * string and divide correct scenario name.
- */
- locked = is_pmqos_locked(data, name);
- index = find_scenario_index(scenario, name);
- if (index < 0) {
- _W("Unknown scenario (%s)\n", data);
- return -EINVAL;
- }
- scn = &scenario->list[index];
-
- /* Check the state of each scenario whether to support or not */
- if (scn->state != PASS_ON) {
- _W("cannot support '%s' scenario (support=%d)\n",
- name, scn->state);
- return 0;
- }
-
- /*
- * Compare locked state of scenario with
- * if state is same as existing state
- */
- if (scn->locked == locked) {
- _E("'%s' scenario is already %s\n",
- name, locked ? "Locked" : "Unlocked");
- return 0;
- }
- scenario->list[index].locked = locked;
-
- if (locked)
- scenario->list[index].locked_time = get_time_ms();
-
- /* Change scaling scope according to scenario's level */
- for (i = 0; i < scenario->num_scenarios; i++) {
- struct pass_scenario *scn = &scenario->list[i];
-
- if (is_scenario_locked(scn)) {
- if (scn->cpufreq_min_level > cpufreq_min_level)
- cpufreq_min_level = scn->cpufreq_min_level;
- if (scn->cpufreq_max_level > cpufreq_max_level)
- cpufreq_max_level = scn->cpufreq_max_level;
- count++;
- }
-
- /*
- * TODO: PASS have to control busfreq/gpufreq as same as cpufreq
- */
- }
-
- /*
- * Restore default min/max level if all scenarios hasn't locked state.
- */
- if (!is_scenario_locked(scn) && !count) {
- cpufreq_min_level = policy->default_min_level;
- cpufreq_max_level = policy->default_max_level;
- }
-
- if (locked) {
- _I("Lock '%s' scenario\n", name);
- } else {
- int64_t locked_time =
- get_time_ms() - scenario->list[index].locked_time;
- scenario->list[index].locked_time = 0;
-
- _I("UnLock '%s' scenario (%lldms)\n", name, locked_time);
- }
-
- pass_governor_change_level_scope(policy, cpufreq_min_level,
- cpufreq_max_level);
-
- /* TODO: PASS have to control busfreq/gpufreq as same as cpufreq. */
-
- return 0;
-}
-
-static int pass_notifier_pmqos(void *data)
+static int pass_notifier_booting_done(void *data)
{
int i;
if (num_policy_pmqos == 0)
return 0;
+ /* Start PASS governor if 'pass_support' in pass.conf is true */
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);
+ policy_pmqos[i]->governor->update(policy_pmqos[i],
+ PASS_GOV_START);
}
}
return 0;
}
-/*
- * pass_notifier_booting_done - Callback function of DEVICE_NOTIFIER_BOOTING_
- * DONE notifier
- * @data: NULL, this parameter isn't used
- */
-static int pass_notifier_booting_done(void *data)
+static int pass_notifier_pmqos(void *data)
{
int i;
if (num_policy_pmqos == 0)
return 0;
- /* Start PASS governor if 'pass_support' in pass.conf is true */
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);
+ pass_notifier_pmqos_func(policy_pmqos[i], data);
}
}
return 0;
};
-/*
- * pass_governor_change_level_scope - Change the scope of cpufreq scaling
- *
- * @policy: the instance of struct pass_policy
- * @min_level: the minimum level of cpufreq scaling
- * @max_level: the maximum level of cpufreq scaling
- */
-static int pass_governor_change_level_scope(struct pass_policy *policy,
- int min_level, int max_level)
-{
- if (!policy)
- return -EINVAL;
-
- if (min_level > max_level) {
- _E("min_level(%d) have to be smaller than max_level(%d)\n",
- min_level, max_level);
- return -EINVAL;
- }
-
- if (min_level == policy->min_level
- && max_level == policy->max_level)
- return 0;
-
- /* Change minimum/maximum level of cpufreq scaling */
- policy->min_level = min_level;
- policy->max_level = max_level;
-
- pass_governor_change_level(policy, policy->curr_level);
-
- return 0;
-}
-
/*
* pass_calculate_busy_cpu - Count a number of busy cpu among NR_CPUS by using
* runnable_avg_sum/runnable_avg_period
return 0;
}
+/*
+ * pass_governor_change_level_scope - Change the scope of cpufreq scaling
+ *
+ * @policy: the instance of struct pass_policy
+ * @min_level: the minimum level of cpufreq scaling
+ * @max_level: the maximum level of cpufreq scaling
+ */
+int pass_governor_change_level_scope(struct pass_policy *policy,
+ int min_level, int max_level)
+{
+ if (!policy)
+ return -EINVAL;
+
+ if (min_level > max_level) {
+ _E("min_level(%d) have to be smaller than max_level(%d)\n",
+ min_level, max_level);
+ return -EINVAL;
+ }
+
+ if (min_level == policy->min_level
+ && max_level == policy->max_level)
+ return 0;
+
+ /* Change minimum/maximum level of cpufreq scaling */
+ policy->min_level = min_level;
+ policy->max_level = max_level;
+
+ pass_governor_change_level(policy, policy->curr_level);
+
+ return 0;
+}
+
/*
* Define PASS governor
*
--- /dev/null
+/*
+ * deviced
+ *
+ * Copyright (c) 2016 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.h"
+#include "pass-core.h"
+
+#include "core/device-notifier.h"
+#include "core/config-parser.h"
+
+/****************************************************************************
+ * PASS Notifier *
+ * - DEVICE_NOTIFIER_PMQOS *
+ * - DEVICE_NOTIFIER_BOOTING_DONE *
+ ****************************************************************************/
+#define PASS_LOCK "Lock"
+#define PASS_UNLOCK "Unlock"
+
+/*
+ * is_pmqos_enabled - Check state of whether to support PM_QOS for scenario
+ * @policy: instance of pass_policy structure
+ *
+ * Return true if the state of PM_QOS is supported
+ * Return false if the state of PM_QOS isn't supported
+ */
+static bool is_pmqos_enabled(struct pass_policy *policy)
+{
+ if (!policy)
+ return false;
+
+ if (!policy->scenario.list)
+ return false;
+
+ if (policy->scenario.state != PASS_ON)
+ return false;
+
+ return true;
+}
+
+/*
+ * is_scenario_locked - Check locked state of each scenario
+ * @policy: instance of pass_scenario structure
+ *
+ * Return true if scenario is locked and enabled
+ * Return false if scenario is unlocked or disabled
+ */
+
+static bool is_scenario_locked(struct pass_scenario *scn)
+{
+ if (!scn)
+ return false;
+
+ if (!scn->locked || scn->state != PASS_ON)
+ return false;
+
+ return true;
+}
+
+static enum pass_state is_pmqos_locked(char *data, char *name)
+{
+ char *unlock = NULL;
+
+ if (!data)
+ return PASS_OFF;
+
+ unlock = strstr(data, PASS_UNLOCK);
+ if (!unlock) {
+ /* Lock scenario */
+ strncpy(name, data, strlen(data) - strlen(PASS_LOCK));
+ return PASS_ON;
+ } else {
+ /* Unlock scenario */
+ strncpy(name, data, strlen(data) - strlen(PASS_UNLOCK));
+ return PASS_OFF;
+ }
+}
+
+static int find_scenario_index(struct pass_scenario_policy *scenario,
+ char *name)
+{
+ int index;
+
+ for (index = 0; index < scenario->num_scenarios; index++)
+ if (MATCH(scenario->list[index].name, name))
+ return index;
+
+ return -EINVAL;
+}
+
+/*
+ * pass_notifier_pmqos - Callback function of DEVICE_NOTIFIER_PMQOS notifier
+ * @data: the scenario name
+ */
+int pass_notifier_pmqos_func(struct pass_policy *policy, void *data)
+{
+ struct pass_scenario_policy *scenario = &policy->scenario;
+ struct pass_scenario *scn = NULL;
+ enum pass_state locked = PASS_UNUSED;
+ char name[PASS_NAME_LEN] = {""};
+ unsigned int cpufreq_min_level = 0;
+ unsigned int cpufreq_max_level = 0;
+ int count = 0;
+ int index = -1;
+ int i;
+
+#if 0
+ if (!is_enabled(policy))
+ return 0;
+#endif
+ if (!is_pmqos_enabled(policy))
+ return 0;
+
+ /*
+ * Parse scenario name(data) whether to include 'Lock' or 'Unlock'
+ * string and divide correct scenario name.
+ */
+ locked = is_pmqos_locked(data, name);
+ index = find_scenario_index(scenario, name);
+ if (index < 0) {
+ _W("Unknown scenario (%s)\n", data);
+ return -EINVAL;
+ }
+ scn = &scenario->list[index];
+
+ /* Check the state of each scenario whether to support or not */
+ if (scn->state != PASS_ON) {
+ _W("cannot support '%s' scenario (support=%d)\n",
+ name, scn->state);
+ return 0;
+ }
+
+ /*
+ * Compare locked state of scenario with
+ * if state is same as existing state
+ */
+ if (scn->locked == locked) {
+ _E("'%s' scenario is already %s\n",
+ name, locked ? "Locked" : "Unlocked");
+ return 0;
+ }
+ scenario->list[index].locked = locked;
+
+ if (locked)
+ scenario->list[index].locked_time = get_time_ms();
+
+ /* Change scaling scope according to scenario's level */
+ for (i = 0; i < scenario->num_scenarios; i++) {
+ struct pass_scenario *scn = &scenario->list[i];
+
+ if (is_scenario_locked(scn)) {
+ if (scn->cpufreq_min_level > cpufreq_min_level)
+ cpufreq_min_level = scn->cpufreq_min_level;
+ if (scn->cpufreq_max_level > cpufreq_max_level)
+ cpufreq_max_level = scn->cpufreq_max_level;
+ count++;
+ }
+
+ /*
+ * TODO: PASS have to control busfreq/gpufreq as same as cpufreq
+ */
+ }
+
+ /*
+ * Restore default min/max level if all scenarios hasn't locked state.
+ */
+ if (!is_scenario_locked(scn) && !count) {
+ cpufreq_min_level = policy->default_min_level;
+ cpufreq_max_level = policy->default_max_level;
+ }
+
+ if (locked) {
+ _I("Lock '%s' scenario\n", name);
+ } else {
+ int64_t locked_time =
+ get_time_ms() - scenario->list[index].locked_time;
+ scenario->list[index].locked_time = 0;
+
+ _I("UnLock '%s' scenario (%lldms)\n", name, locked_time);
+ }
+
+ pass_governor_change_level_scope(policy, cpufreq_min_level,
+ cpufreq_max_level);
+
+ /* TODO: PASS have to control busfreq/gpufreq as same as cpufreq. */
+
+ return 0;
+}