#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)
{
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)
{
}
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;
struct pass_cpuhp *cpuhp;
struct pass_pmqos *pmqos;
struct pass_thermal *thermal;
- int ret;
+ int ret, i;
if (!res)
return -EINVAL;
/* 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;
}
/* 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",
}
/* 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",
}
/* 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",