pass: parser: Verify properties of pass_level before using 15/224715/7
authorChanwoo Choi <cw00.choi@samsung.com>
Tue, 28 Jan 2020 04:40:38 +0000 (13:40 +0900)
committerChanwoo Choi <cw00.choi@samsung.com>
Wed, 26 Feb 2020 04:26:05 +0000 (13:26 +0900)
Prior to that there are no any restrictions about adding properties
to pass_level in the configuration file such as /etc/pass/pass-resource-*.conf
for each h/w resource.

Add some restrictions of pass_level as following:
- In case of CPU,
  If there is either limit_min_cpu or limit_max_cpu in pass_level,
  have to add both limit_min_cpu and limit_max_cpu to pass_level.
- In case of CPU/GPU/BUS,
  if there is either limit_min_freq or limit_max_freq in pass_level,
  have to add both limit_min_freq and limit_max_frewq to pass_level.

Change-Id: I899121c433432ad92800f741f2b8df78dc135de0
Signed-off-by: Chanwoo Choi <cw00.choi@samsung.com>
src/pass/pass-cpuhp-radiation.c
src/pass/pass-cpuhp-step.c
src/pass/pass-parser.c
src/pass/pass-rescon.c

index 058c251ab44724b0258f0b3e69c73d72a92dcb8b..f1af3026ae3ed8c705ed85bb29ac320e579c6d53 100644 (file)
@@ -96,7 +96,7 @@ int pass_cpuhp_radiation_governor(struct pass_resource *res, void *result)
                                up_condition = false;
                }
 
-               if (levels[level].num_up_cond && up_condition) {
+               if (levels[level].num_up_cond > 0 && up_condition) {
                        up_count++;
 
                        /*
@@ -114,7 +114,7 @@ int pass_cpuhp_radiation_governor(struct pass_resource *res, void *result)
                                down_condition = false;
                }
 
-               if (levels[level].num_down_cond && down_condition) {
+               if (levels[level].num_down_cond > 0 && down_condition) {
                        down_count++;
 
                        /*
@@ -140,7 +140,7 @@ int pass_cpuhp_radiation_governor(struct pass_resource *res, void *result)
                                right_condition = false;
                }
 
-               if (levels[level].num_right_cond && right_condition) {
+               if (levels[level].num_right_cond > 0 && right_condition) {
                        right_count++;
 
                        /*
@@ -167,7 +167,7 @@ int pass_cpuhp_radiation_governor(struct pass_resource *res, void *result)
                                left_condition = false;
                }
 
-               if (levels[level].num_left_cond && left_condition) {
+               if (levels[level].num_left_cond > 0 && left_condition) {
                        left_count++;
 
                        /*
index 405deb504ff2a489baaed9994a7e17a36ed55589..06983c40e996f1da210f581813dbe34033319da3 100644 (file)
@@ -91,7 +91,7 @@ int pass_cpuhp_step_governor(struct pass_resource *res, void *result)
                                up_condition = true;
                }
 
-               if (levels[level].num_up_cond && up_condition) {
+               if (levels[level].num_up_cond > 0 && up_condition) {
                        up_count++;
 
                        /*
@@ -116,7 +116,7 @@ int pass_cpuhp_step_governor(struct pass_resource *res, void *result)
                                down_condition = true;
                }
 
-               if (levels[level].num_down_cond && down_condition) {
+               if (levels[level].num_down_cond > 0 && down_condition) {
                        down_count++;
 
                        /*
index e72813a39f653df51e1dacefd87abefe31d7bd5e..aec23f4c9a9938ba8ce7c98c3e896eff6d58cf11 100644 (file)
@@ -47,6 +47,7 @@
 #define MAX_NUM                        255
 #define MIN_TIMEOUT_SEC                0.2     /* 200 millisecond */
 #define MAX_TIMEOUT_SEC                3600.0  /* 1 hour */
+#define INIT_VALUE             -1
 
 static int compare_compatible_name(char *compatible, char *path_compatible)
 {
@@ -145,12 +146,73 @@ static int parse_scenario(struct parse_result *result,
        return 0;
 }
 
-/**
- * @brief      Parse pass_level section to get pass_level information
- * @param      [in] result Parsed raw data from configuration
- * @param      [in] level Parsed data of a pass_level will be saved to it
- * @return     @c 0 on success, otherwise error value
- */
+static int verify_level(int res_type, int level_idx, struct pass_level *level)
+{
+       if (!level)
+               return -EINVAL;
+
+       switch (res_type) {
+       case PASS_RESOURCE_CPU_ID:
+               if ((level->limit_min_cpu >= 0 || level->limit_max_cpu >= 0)
+                       && !(level->limit_min_cpu >= 0 && level->limit_max_cpu >= 0)) {
+                       _E("Level%d doesn't contain either " \
+                               "limit_min_cpu(%d) or limit_max_cpu(%d)",
+                               level_idx,
+                               level->limit_min_cpu,
+                               level->limit_max_cpu);
+                       return -EINVAL;
+               }
+               /* fall through */
+       case PASS_RESOURCE_GPU_ID:
+       case PASS_RESOURCE_BUS_ID:
+               if ((level->limit_min_freq > 0 || level->limit_max_freq > 0)
+                       && !(level->limit_min_freq > 0 && level->limit_max_freq > 0)) {
+                       _E("Level%d doesn't contain either " \
+                               "limit_min_freq(%d) or limit_max_freq(%d)",
+                               level_idx,
+                               level->limit_min_freq,
+                               level->limit_max_freq);
+                       return -EINVAL;
+               }
+               break;
+       case PASS_RESOURCE_MEMORY_ID:
+       case PASS_RESOURCE_NONSTANDARD_ID:
+               break;
+       default:
+               return -EINVAL;
+       };
+
+       return 0;
+}
+
+static void init_level(struct pass_level *level)
+{
+       level->limit_max_freq = INIT_VALUE;
+       level->limit_min_freq = INIT_VALUE;
+       level->limit_max_cpu = INIT_VALUE;
+       level->limit_min_cpu = INIT_VALUE;
+
+       level->num_down_cond = INIT_VALUE;
+       level->down_cond[0].freq = INIT_VALUE;
+       level->down_cond[0].nr_running = INIT_VALUE;
+       level->down_cond[0].busy_cpu = INIT_VALUE;
+       level->num_up_cond = INIT_VALUE;
+       level->up_cond[0].freq = INIT_VALUE;
+       level->up_cond[0].nr_running = INIT_VALUE;
+       level->up_cond[0].busy_cpu = INIT_VALUE;
+       level->num_left_cond = INIT_VALUE;
+       level->left_cond[0].freq = INIT_VALUE;
+       level->left_cond[0].nr_running = INIT_VALUE;
+       level->left_cond[0].busy_cpu = INIT_VALUE;
+       level->num_right_cond = INIT_VALUE;
+       level->right_cond[0].freq = INIT_VALUE;
+       level->right_cond[0].nr_running = INIT_VALUE;
+       level->right_cond[0].busy_cpu = INIT_VALUE;
+       level->gov_timeout = INIT_VALUE;
+
+       level->fault_around_bytes = INIT_VALUE;
+}
+
 static int parse_level(struct parse_result *result,
                                struct pass_level *level)
 {
@@ -492,12 +554,18 @@ static int parse_core(struct parse_result *result, void *user_data)
        }
 
        if (res->config_data.num_levels > 0 && !res->config_data.levels) {
+               int i;
+
                res->config_data.levels = calloc(res->config_data.num_levels,
                                                sizeof(struct pass_level));
                if (!res->config_data.levels) {
                        _E("cannot allocate memory for levels\n");
                        return -EINVAL;
                }
+
+               /* Initialize pass_level before parsing */
+               for (i = 0; i < res->config_data.num_levels; i++)
+                       init_level(&res->config_data.levels[i]);
        }
 
        return 0;
@@ -832,7 +900,7 @@ int pass_get_each_resource_config(struct pass_resource *res, char *path)
        struct pass_cpuhp *cpuhp;
        struct pass_pmqos *pmqos;
        struct pass_thermal *thermal;
-       int ret;
+       int ret, i;
 
        if (!res)
                return -EINVAL;
@@ -865,12 +933,24 @@ int pass_get_each_resource_config(struct pass_resource *res, char *path)
        /* Initialize the Thermal's data */
        thermal->state = PASS_UNUSED;
 
+       /* Parse pass_level */
        ret = config_parse(path, parse_each_resource, res);
        if (ret < 0) {
                _E("cannot parse %s\n", path);
                return -EINVAL;
        }
 
+       /* Verify the parsed pass_level */
+       for (i = 0; i < res->config_data.num_levels; i++)
+               ret |= verify_level(res->config_data.res_type,
+                               i, &res->config_data.levels[i]);
+
+       if (ret < 0) {
+               _E("failed to verify Level of '%s' resource\n",
+                               res->config_data.res_name);
+               return -EINVAL;
+       }
+
        if (res->config_data.state == PASS_UNUSED)
                return -EINVAL;
 
index a2bfd97e745f86019de552505197deda87942a98..c156a17319fd4895d844d53d0c916deedae16d02 100644 (file)
@@ -84,7 +84,7 @@ static int rescon_set_level(struct pass_resource *res, int new_level)
        }
 
        /* Set maximum frequency */
-       if (limit_max_freq) {
+       if (limit_max_freq > 0) {
                ret = pass_set_max_freq(res, limit_max_freq);
                if (ret < 0) {
                        _E("cannot set the maximum frequency of %s",
@@ -94,7 +94,7 @@ static int rescon_set_level(struct pass_resource *res, int new_level)
        }
 
        /* Set minimum frequency */
-       if (limit_min_freq) {
+       if (limit_min_freq > 0) {
                ret = pass_set_min_freq(res, limit_min_freq);
                if (ret < 0) {
                        _E("cannot set the minimum frequency of %s",
@@ -104,7 +104,7 @@ static int rescon_set_level(struct pass_resource *res, int new_level)
        }
 
        /* Set fault_around_bytes for the memory h/w */
-       if (fault_around_bytes) {
+       if (fault_around_bytes > 0) {
                ret = pass_set_fault_around_bytes(res, fault_around_bytes);
                if (ret < 0) {
                        _E("cannot set the fault_around_bytes of %s",