4 * Copyright (c) 2012 - 2013 Samsung Electronics Co., Ltd.
6 * Licensed under the Apache License, Version 2.0 (the License);
7 * you may not use this file except in compliance with the License.
8 * You may obtain a copy of the License at
10 * http://www.apache.org/licenses/LICENSE-2.0
12 * Unless required by applicable law or agreed to in writing, software
13 * distributed under the License is distributed on an "AS IS" BASIS,
14 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
15 * See the License for the specific language governing permissions and
16 * limitations under the License.
25 #include "pass-plugin.h"
27 #include "core/config-parser.h"
31 /* Linux standard sysfs node */
32 #define CPUFREQ_SCALING_MAX_FREQ "/sys/devices/system/cpu/cpu0/cpufreq/scaling_max_freq"
33 #define CPUFREQ_SCALING_MIN_FREQ "/sys/devices/system/cpu/cpu0/cpufreq/scaling_min_freq"
34 #define CPUFREQ_SAMPLING_RATE "/sys/devices/system/cpu/cpufreq/ondemand/sampling_rate"
35 #define CPUFREQ_UP_THRESHOLD "/sys/devices/system/cpu/cpufreq/ondemand/up_threshold"
37 #define PROC_DT_COMPATIBLE "/proc/device-tree/compatible"
39 /* PASS specific sysfs node */
40 #define PASS_CPU_STATS "/sys/kernel/debug/cpufreq/cpu0/load_table"
42 int get_pass_cpu_stats(struct pass_policy *policy)
44 struct pass_cpu_stats *stats = policy->pass_cpu_stats;
45 char path[PATH_MAX] = PASS_CPU_STATS;
47 FILE *fp_stats = NULL;
52 _E("invalid parameter of structure pass_cpu_stats");
56 fp_stats = fopen(path, "r");
60 fgets(str, BUFF_MAX, fp_stats);
61 for (i = 0; i < policy->num_pass_cpu_stats; i++) {
62 ret = fscanf(fp_stats, "%lld %d %d %d",
66 &stats[i].nr_runnings);
68 for (j = 0; j < policy->cpufreq.num_nr_cpus; j++)
69 ret = fscanf(fp_stats, "%d", &stats[i].load[j]);
78 * - Read from sysfs entry
79 * - Write to sysfs entry
81 static int sys_read_buf(char *file, char *buf)
87 fd = open(file, O_RDONLY);
91 r = read(fd, buf, BUFF_MAX);
92 if ((r >= 0) && (r < BUFF_MAX))
102 static int sys_write_buf(char *file, char *buf)
108 fd = open(file, O_WRONLY);
112 r = write(fd, buf, strlen(buf));
121 static int sys_get_int(char *fname, int *val)
125 if (sys_read_buf(fname, buf) == 0) {
134 static int sys_set_int(char *fname, int val)
138 snprintf(buf, sizeof(buf), "%d", val);
140 if (sys_write_buf(fname, buf) == 0)
147 * Get/Set maximum cpu frequency
149 #define GET_VALUE(name, path) \
150 int get_##name(void) \
154 ret = sys_get_int(path, &value); \
161 #define SET_VALUE(name, path) \
162 int set_##name(int value) \
164 return sys_set_int(path, value); \
167 GET_VALUE(cpufreq_scaling_max_freq, CPUFREQ_SCALING_MAX_FREQ);
168 SET_VALUE(cpufreq_scaling_max_freq, CPUFREQ_SCALING_MAX_FREQ);
170 GET_VALUE(cpufreq_scaling_min_freq, CPUFREQ_SCALING_MIN_FREQ);
171 SET_VALUE(cpufreq_scaling_min_freq, CPUFREQ_SCALING_MIN_FREQ);
173 GET_VALUE(cpufreq_sampling_rate, CPUFREQ_SAMPLING_RATE);
174 SET_VALUE(cpufreq_sampling_rate, CPUFREQ_SAMPLING_RATE);
176 GET_VALUE(cpufreq_up_threshold, CPUFREQ_UP_THRESHOLD);
177 SET_VALUE(cpufreq_up_threshold, CPUFREQ_UP_THRESHOLD);
179 int get_cpu_online(int cpu)
185 ret = sprintf(path, "/sys/devices/system/cpu/cpu%d/online", cpu);
189 ret = sys_get_int(path, &online);
195 int set_cpu_online(int cpu, int online)
200 ret = sprintf(path, "/sys/devices/system/cpu/cpu%d/online", cpu);
204 ret = sys_set_int(path, online);
211 /***************************************************************************
213 ***************************************************************************/
215 static enum pass_state is_supported(char *value)
217 enum pass_state state;
222 if (MATCH(value, "yes"))
224 else if (MATCH(value, "no"))
232 static int pass_parse_scenario(struct parse_result *result, void *user_data,
235 struct pass_policy *policy = user_data;
236 struct pass_scenario_policy *scenario = &policy->scenario;
237 char section_name[BUFF_MAX];
240 if (!policy && !scenario && !result)
243 if (!result->section || !result->name || !result->value)
246 /* Parse 'PassScenario' section */
247 if (MATCH(result->section, "PassScenario")) {
248 if (MATCH(result->name, "pass_scenario_support")) {
249 scenario->state = is_supported(result->value);
250 if (scenario->state < 0)
253 } else if (MATCH(result->name, "pass_num_scenarios")) {
254 scenario->num_scenarios = atoi(result->value);
256 if (scenario->num_scenarios > 0 && !scenario->list) {
257 scenario->list = malloc(sizeof(struct pass_scenario)
258 * scenario->num_scenarios);
259 if (!scenario->list) {
260 _E("cannot allocate memory for Scenario\n");
267 if (scenario->state != PASS_ON)
270 if (!scenario->num_scenarios)
273 if (index > scenario->num_scenarios || index == PASS_UNUSED)
276 /* Parse 'Scenario' section */
277 if (MATCH(result->name, "name")) {
278 strcpy(scenario->list[index].name, result->value);
279 } else if (MATCH(result->name, "support")) {
280 scenario->list[index].state = is_supported(result->value);
281 if (scenario->list[index].state < 0)
283 } else if (MATCH(result->name, "cpufreq_min_level")) {
284 scenario->list[index].cpufreq_min_level = atoi(result->value);
285 } else if (MATCH(result->name, "cpufreq_max_level")) {
286 scenario->list[index].cpufreq_max_level = atoi(result->value);
287 } else if (MATCH(result->name, "busfreq_min_level")) {
288 scenario->list[index].busfreq_min_level = atoi(result->value);
289 } else if (MATCH(result->name, "busfreq_max_level")) {
290 scenario->list[index].busfreq_max_level = atoi(result->value);
291 } else if (MATCH(result->name, "gpufreq_min_level")) {
292 scenario->list[index].gpufreq_min_level = atoi(result->value);
293 } else if (MATCH(result->name, "gpufreq_max_level")) {
294 scenario->list[index].gpufreq_max_level = atoi(result->value);
300 static int pass_parse_cpufreq_level(struct parse_result *result,
301 void *user_data, int level)
303 struct pass_policy *policy = user_data;
304 char section_name[BUFF_MAX];
310 if (!result->section || !result->name || !result->value)
313 if (MATCH(result->name, "limit_max_freq"))
314 policy->pass_table[level].limit_max_freq = atoi(result->value);
315 else if (MATCH(result->name, "limit_max_cpu"))
316 policy->pass_table[level].limit_max_cpu = atoi(result->value);
318 else if (MATCH(result->name, "num_down_cond"))
319 policy->pass_table[level].num_down_cond = atoi(result->value);
320 else if (MATCH(result->name, "num_down_cond_freq"))
321 policy->pass_table[level].down_cond[0].freq = atoi(result->value);
322 else if (MATCH(result->name, "num_down_cond_nr_running"))
323 policy->pass_table[level].down_cond[0].nr_running = atoi(result->value);
324 else if (MATCH(result->name, "num_down_cond_busy_cpu"))
325 policy->pass_table[level].down_cond[0].busy_cpu = atoi(result->value);
327 else if (MATCH(result->name, "num_up_cond"))
328 policy->pass_table[level].num_up_cond = atoi(result->value);
329 else if (MATCH(result->name, "num_up_cond_freq"))
330 policy->pass_table[level].up_cond[0].freq = atoi(result->value);
331 else if (MATCH(result->name, "num_up_cond_nr_running"))
332 policy->pass_table[level].up_cond[0].nr_running = atoi(result->value);
333 else if (MATCH(result->name, "num_up_cond_busy_cpu"))
334 policy->pass_table[level].up_cond[0].busy_cpu = atoi(result->value);
336 else if (MATCH(result->name, "num_left_cond"))
337 policy->pass_table[level].num_left_cond = atoi(result->value);
338 else if (MATCH(result->name, "num_left_cond_freq"))
339 policy->pass_table[level].left_cond[0].freq = atoi(result->value);
340 else if (MATCH(result->name, "num_left_cond_nr_running"))
341 policy->pass_table[level].left_cond[0].nr_running = atoi(result->value);
342 else if (MATCH(result->name, "num_left_cond_busy_cpu"))
343 policy->pass_table[level].left_cond[0].busy_cpu = atoi(result->value);
345 else if (MATCH(result->name, "num_right_cond"))
346 policy->pass_table[level].num_right_cond = atoi(result->value);
347 else if (MATCH(result->name, "num_right_cond_freq"))
348 policy->pass_table[level].right_cond[0].freq = atoi(result->value);
349 else if (MATCH(result->name, "num_right_cond_nr_running"))
350 policy->pass_table[level].right_cond[0].nr_running = atoi(result->value);
351 else if (MATCH(result->name, "num_right_cond_busy_cpu"))
352 policy->pass_table[level].right_cond[0].busy_cpu = atoi(result->value);
357 static int pass_parse_core(struct parse_result *result, void *user_data)
359 struct pass_policy *policy = user_data;
360 char section_name[BUFF_MAX];
366 if (!result->section || !result->name || !result->value)
369 if (MATCH(result->name, "pass_compatible")) {
370 char compatible[BUFF_MAX];
372 ret = sys_read_buf(PROC_DT_COMPATIBLE, compatible);
376 if (strcmp(compatible, result->value))
379 _I("Match compatible string : %s\n", compatible);
380 } else if (MATCH(result->name, "pass_support"))
381 policy->state = atoi(result->value);
382 else if (MATCH(result->name, "pass_gov_type"))
383 policy->gov_type = atoi(result->value);
384 else if (MATCH(result->name, "pass_num_levels"))
385 policy->num_levels = atoi(result->value);
386 else if (MATCH(result->name, "pass_min_level"))
387 policy->min_level = atoi(result->value);
388 else if (MATCH(result->name, "pass_max_level"))
389 policy->max_level = atoi(result->value);
390 else if (MATCH(result->name, "pass_num_cpu_stats"))
391 policy->num_pass_cpu_stats = atoi(result->value);
392 else if (MATCH(result->name, "pass_cpu_threshold"))
393 policy->pass_cpu_threshold = atoi(result->value);
394 else if (MATCH(result->name, "pass_up_threshold"))
395 policy->up_threshold = atoi(result->value);
396 else if (MATCH(result->name, "pass_down_threshold"))
397 policy->down_threshold = atoi(result->value);
398 else if (MATCH(result->name, "pass_init_level"))
399 policy->init_level = atoi(result->value);
400 else if (MATCH(result->name, "pass_level_up_threshold"))
401 policy->level_up_threshold = atoi(result->value);
402 else if (MATCH(result->name, "pass_governor_timeout")) {
403 policy->gov_timeout = atof(result->value);
405 if (PASS_MIN_GOV_TIMEOUT > policy->gov_timeout)
406 policy->gov_timeout = PASS_MIN_GOV_TIMEOUT;
409 if (policy->num_levels > 0 && !policy->pass_table) {
410 policy->pass_table = malloc(sizeof(struct pass_table)
411 * policy->num_levels);
412 if (!policy->pass_table) {
413 _E("cannot allocate memory for pass_table\n");
421 static int pass_load_config(struct parse_result *result, void *user_data)
423 struct pass_policy *policy = user_data;
424 struct pass_scenario_policy *scenario = &policy->scenario;
425 char section_name[BUFF_MAX];
426 int level = PASS_UNUSED;
427 int index = PASS_UNUSED;
433 if (!result->section || !result->name || !result->value)
436 /* Parsing 'PASS' section */
437 if (MATCH(result->section, "Pass")) {
438 ret = pass_parse_core(result, user_data);
440 _E("cannot parse the core part\n");
447 /* Parsing 'CpufreqLevel' section to get pass-table */
448 for (level = 0; level < policy->num_levels; level++) {
449 ret = sprintf(section_name, "CpufreqLevel%d", level);
451 if (MATCH(result->section, section_name)) {
452 ret = pass_parse_cpufreq_level(result, user_data, level);
454 _E("cannot parse 'Cpufreq' section\n");
462 /* Parsing 'PassScenario' section */
463 if (MATCH(result->section, "PassScenario")) {
464 ret = pass_parse_scenario(result, user_data, PASS_UNUSED);
466 _E("cannot parse 'PassScenario' section\n");
473 /* Parsing 'Scenario' section */
474 for (index = 0; index < scenario->num_scenarios; index++) {
475 ret = sprintf(section_name, "Scenario%d", index);
477 if (MATCH(result->section, section_name)) {
478 ret = pass_parse_scenario(result, user_data, index);
480 _E("cannot parse 'Scenario' section\n");
492 int get_pass_table(struct pass_policy *policy, char *pass_conf_path)
496 policy->state = PASS_UNUSED;
497 policy->scenario.state = PASS_UNUSED;
499 ret = config_parse(pass_conf_path, pass_load_config, policy);
501 _E("cannot parse %s\n", pass_conf_path);
505 if (policy->state == PASS_UNUSED)
508 if (policy->scenario.state == PASS_UNUSED)
509 _W("%s don't include the list of pass-scenario\n");
511 _I("can%s use pass-scenario",
512 policy->scenario.state ? "" : "not");
517 void put_pass_table(struct pass_policy *policy)
519 if(policy->pass_table)
520 free(policy->pass_table);
522 if(policy->scenario.list)
523 free(policy->scenario.list);
527 * get_time_ms - Return current time (unit: millisecond)
529 int64_t get_time_ms(void)
533 gettimeofday(&now, NULL);
535 return (int64_t)(now.tv_sec * 1000 + now.tv_usec / 1000);