pass: pmqos: Split out the pm_qos feature from core driver
authorChanwoo Choi <cw00.choi@samsung.com>
Mon, 20 Jun 2016 11:50:32 +0000 (20:50 +0900)
committerChanwoo Choi <cw00.choi@samsung.com>
Mon, 16 Jan 2017 11:35:37 +0000 (20:35 +0900)
This patch split out the pm_qos feature from the core driver of PASS.
The pass-pmqos.c handles the h/w resource according to user scenario.

Change-Id: Iab5880696838394d4c03b8458b910665e9dbe759
Signed-off-by: Chanwoo Choi <cw00.choi@samsung.com>
src/pass/pass-core.c
src/pass/pass-core.h
src/pass/pass-pmqos.c [new file with mode: 0644]
src/pass/pass-pmqos.h [new file with mode: 0644]

index 6890444b6e97369ee82eb49f382a5c2a12a74c3f..34b143cd3200c2d41faa61f52cf426b0495479d9 100644 (file)
@@ -23,6 +23,7 @@
 
 #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
@@ -68,210 +40,58 @@ 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
+ * 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);
                }
        }
 
@@ -472,38 +292,6 @@ static int pass_governor_change_level(struct pass_policy *policy, int new_level)
        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
@@ -826,6 +614,38 @@ static int pass_governor_update(struct pass_policy *policy,
        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
  *
index 4c201facd15ce8f08a6f1f1ac2a2a70acb7f43c5..78defab9db5a8b3f4f761c5236589835b5ec851b 100644 (file)
@@ -18,6 +18,7 @@
 
 #ifndef __PASS_CORE__
 #define __PASS_CORE__
+
 /*
  * pass_get_governor - Return specific governor instance according to type
  *
@@ -36,4 +37,14 @@ struct pass_governor* pass_get_governor(struct pass_policy *policy,
 struct pass_hotplug* pass_get_hotplug(struct pass_policy *policy,
                                                enum pass_gov_type type);
 
+/*
+ * 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);
+
 #endif /* __PASS_CORE__ */
diff --git a/src/pass/pass-pmqos.c b/src/pass/pass-pmqos.c
new file mode 100644 (file)
index 0000000..87ebbd3
--- /dev/null
@@ -0,0 +1,206 @@
+/*
+ * 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;
+}
diff --git a/src/pass/pass-pmqos.h b/src/pass/pass-pmqos.h
new file mode 100644 (file)
index 0000000..a6991c1
--- /dev/null
@@ -0,0 +1,28 @@
+/*
+ * 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.
+ */
+
+#ifndef __PASS_PMQOS__
+#define __PASS_PMQOS__
+
+/*
+ * 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);
+
+#endif /* __PASS_PMQOS__ */