pass: pmqos: Add the support for multiple scenarios at the same time 76/114176/2
authorChanwoo Choi <cw00.choi@samsung.com>
Fri, 10 Feb 2017 07:30:47 +0000 (16:30 +0900)
committerChanwoo Choi <cw00.choi@samsung.com>
Mon, 13 Feb 2017 01:13:17 +0000 (10:13 +0900)
The PMQoS has the following policy to support the multiple scenarios
at the same time.
- Policy to maintain the current/minimum/maximum level according to scenario:
: If there are the locked scenarios, the PMQoS maintains the largest value of
both min_level and max_level among the locked scenarios in order to support
the high-performance.

For exampel,
Default.   min_level(0) max_level(4) -> range of min/max: 0 ~ 4, curr_level (3)
Lock scn1. min_level(3) max_level(5) -> range of min/max: 3 ~ 5
Lock scn2. min_level(2) max_level(8) -> range of min/max: 3 ~ 8
Lock scn3. min_level(6) max_level(7) -> range of min/max: 6 ~ 8
Unlock scn2.                         -> range of min/max: 6 ~ 8
Unlock scn1.                         -> range of min/max: 6 ~ 8
Unlock scn3.                         -> range of min/max: 6 ~ 8
Unlock all scenarios.                -> range of min/max: 0 ~ 4, curr_level (3)

Second,
This patch changes the definition of pass_governor_change_level_scope()
as following: When this function is called, the desired level should
be passed as the first parameter.
- Before
int pass_governor_change_level_scope(struct pass_policy *policy,
int min_level, int max_level)
- After
int pass_governor_change_level_scope(struct pass_policy *policy,
int new_level, int min_level, int max_level)

Change-Id: Ib61bd408747d91d3bcb3b4326e69b56ade46daf2
Signed-off-by: Chanwoo Choi <cw00.choi@samsung.com>
src/pass/pass-gov.c
src/pass/pass-gov.h
src/pass/pass-pmqos.c
src/pass/pass.h

index dc87db60fdc3ebdd51db11fd79c46f196659cc09..506a563f53b6c06650074acabdd361c7b91a3352 100644 (file)
@@ -617,11 +617,12 @@ static int __pass_governor_update(struct pass_policy *policy,
  * pass_governor_change_level_scope - Change the scope of pass level
  *
  * @policy: the instance of struct pass_policy
+ * @new_level: the desirous pass level
  * @min_level: the minimum pass level
  * @max_level: the maximum pass level
  */
 int pass_governor_change_level_scope(struct pass_policy *policy,
-                                           int min_level, int max_level)
+                               int new_level, int min_level, int max_level)
 {
        if (!policy)
                return -EINVAL;
@@ -640,7 +641,7 @@ int pass_governor_change_level_scope(struct pass_policy *policy,
        policy->min_level = min_level;
        policy->max_level = max_level;
 
-       pass_governor_change_level(policy, policy->curr_level);
+       pass_governor_change_level(policy, new_level);
 
        return 0;
 }
index e80498f18b3da52256757785b145297428110661..d61cf953b8d3dec2503f363b1a8539e25982efa0 100644 (file)
@@ -24,7 +24,7 @@ int pass_governor_init(struct pass_policy *policy);
 int pass_governor_exit(struct pass_policy *policy);
 int pass_governor_update(struct pass_policy *policy, enum pass_gov_state state);
 int pass_governor_change_level_scope(struct pass_policy *policy,
-                                       int min_level, int max_level);
+                               int new_level, int min_level, int max_level);
 
 /* Get the governor/hotplug instance according to enum pass_gov_type */
 struct pass_governor* pass_get_governor(struct pass_policy *policy,
index 8c972ffb8472cbc004880e580d7d1ec6940f84a6..eccfd8e3b3fe4a3534ec9251ad971d11b418bd71 100644 (file)
@@ -111,6 +111,7 @@ static int find_scenario_index(struct pass_scenario_policy *scenario,
  * pass_notifier_pmqos - Callback function of DEVICE_NOTIFIER_PMQOS notifier
  * @data: the scenario name
  */
+#define MAX(a,b)       (a > b ? a : b)
 int pass_notifier_pmqos_func(struct pass_policy *policy, void *data)
 {
        struct pass_resource *pass_res = to_pass_resource(policy);
@@ -119,6 +120,7 @@ int pass_notifier_pmqos_func(struct pass_policy *policy, void *data)
        struct pass_scenario *scn = NULL;
        enum pass_state locked = PASS_UNUSED;
        char name[PASS_NAME_LEN] = {""};
+       unsigned int new_level = 0;
        unsigned int min_level = 0;
        unsigned int max_level = 0;
        int count = 0;
@@ -156,32 +158,47 @@ int pass_notifier_pmqos_func(struct pass_policy *policy, void *data)
                                name, locked ? "Locked" : "Unlocked");
                return 0;
        }
-       scenario->list[index].locked = locked;
-
-       /* 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->min_level > min_level)
-                               min_level = scn->min_level;
-                       if (scn->max_level > max_level)
-                               max_level = scn->max_level;
-                       count++;
+       scn->locked = locked;
+
+       if (scn->locked) {
+               if (scenario->num_locked_scenarios == 0)
+                       new_level = scenario->init_level = policy->curr_level;
+               else
+                       new_level = scenario->curr_level;
+               min_level = MAX(scn->min_level, scenario->min_level);
+               max_level = MAX(scn->max_level, scenario->max_level);
+
+               if (new_level < min_level)
+                       new_level = min_level;
+               else if (new_level > max_level)
+                       new_level = scn->max_level;
+
+               scenario->curr_level = new_level;
+               scenario->min_level = min_level;
+               scenario->max_level = max_level;
+
+               scenario->num_locked_scenarios++;
+       } else {
+               scenario->num_locked_scenarios--;
+
+               if (scenario->num_locked_scenarios == 0) {
+                       new_level = scenario->init_level;
+                       min_level = policy->default_min_level;
+                       max_level = policy->default_max_level;
+
+                       scenario->curr_level = 0;
+                       scenario->min_level = 0;
+                       scenario->max_level = 0;
+               } else {
+                       new_level = scenario->curr_level;
+                       min_level = scenario->min_level;
+                       max_level = scenario->max_level;
                }
        }
 
-       /*
-        * Restore default min/max level if all scenarios hasn't locked state.
-        */
-       if (!is_scenario_locked(scn) && !count) {
-               min_level = policy->default_min_level;
-               max_level = policy->default_max_level;
-       }
-
-       pass_governor_change_level_scope(policy, min_level, max_level);
+       pass_governor_change_level_scope(policy, new_level, min_level, max_level);
 
-       if (locked) {
+       if (scn->locked) {
                _I("Lock   '%s' scenario for '%s' resource\n",
                        name, cdata->res_name);
 
index fdb18b7fd985c44700799e5b60f96adeb58f8eed..081acaa7caf2cb622b54e73443798a6173ec4a9c 100644 (file)
@@ -191,8 +191,14 @@ struct pass_scenario {
 struct pass_scenario_policy {
        enum pass_state state;
        unsigned int num_scenarios;
+       unsigned int num_locked_scenarios;
 
        struct pass_scenario *list;
+
+       unsigned int init_level;
+       unsigned int curr_level;
+       unsigned int min_level;
+       unsigned int max_level;
 };
 
 /*