From fa7aef0bf0c7fba9e3fa4627dcb7f22d6855f728 Mon Sep 17 00:00:00 2001 From: Chanwoo Choi Date: Thu, 22 Mar 2018 19:56:26 +0900 Subject: [PATCH] pass: parser: Add support of thermal monitor for each h/w resource In order to use/support Thermal Monitor, each h/w resource (e.g., CPU/GPU) have to write the configuration such as thermal scenario name, temperature and timer interval for each thermal scenario. Parse the property for Thermal Monitor. Change-Id: I3aa08bcfbbb037897fff42cfe24aabc732610e05 Signed-off-by: Chanwoo Choi --- src/pass/pass-parser.c | 87 ++++++++++++++++++++++++++++++++++++++++++++++++++ src/pass/pass.h | 33 +++++++++++++++++++ 2 files changed, 120 insertions(+) diff --git a/src/pass/pass-parser.c b/src/pass/pass-parser.c index c14f27f..cedbf76 100644 --- a/src/pass/pass-parser.c +++ b/src/pass/pass-parser.c @@ -91,10 +91,18 @@ static int parse_scenario(struct parse_result *result, scenario->state = is_supported(result->value); if (scenario->state < 0) return -EINVAL; + + /* Parse properties for only PASS_MODULE_PMQOS */ } else if (MATCH(result->name, "min_level")) { scenario->pmqos.min_level = atoi(result->value); } else if (MATCH(result->name, "max_level")) { scenario->pmqos.max_level = atoi(result->value); + + /* Parse properties for only PASS_MODULE_THERMAL */ + } else if (MATCH(result->name, "temperature")) { + scenario->thermal.temperature = atoi(result->value); + } else if (MATCH(result->name, "timer_interval_ms")) { + scenario->thermal.timer_interval = atoi(result->value); } return 0; @@ -221,6 +229,47 @@ static int parse_pmqos(struct parse_result *result, void *user_data) return 0; } +static int parse_thermal(struct parse_result *result, void *user_data) +{ + struct pass_resource *res = user_data; + struct pass_thermal *thermal = &res->thermal; + + if (!result) + return 0; + + if (!result->section || !result->name || !result->value) + return 0; + + /* Parse 'thermal' section */ + if (MATCH(result->name, "thermal_support")) { + thermal->state = is_supported(result->value); + if (thermal->state < 0) + return -EINVAL; + } else if (MATCH(result->name, "thermal_number_of_scenario")) { + unsigned int num_scenarios; + + num_scenarios = atoi(result->value); + if (num_scenarios > MAX_NUM) { + _E("cannot parse %s\n", result->name); + return -EINVAL; + } + + if (num_scenarios > 0 && !thermal->scenarios) { + thermal->scenarios = calloc(num_scenarios, + sizeof(struct pass_scenario)); + if (!thermal->scenarios) { + _E("cannot allocate memory for Scenario\n"); + return -EINVAL; + } + thermal->num_scenarios = num_scenarios; + } + } else if (MATCH(result->name, "thermal_timer_interval_ms")) { + thermal->timer_interval = atoi(result->value); + } + + return 0; +} + static int parse_core(struct parse_result *result, void *user_data) { struct pass_resource *res = user_data; @@ -279,6 +328,7 @@ static int parse_each_resource(struct parse_result *result, void *user_data) { struct pass_resource *res = user_data; struct pass_pmqos *pmqos = &res->pmqos; + struct pass_thermal *thermal = &res->thermal; char section_name[BUFF_MAX]; int i, ret; @@ -340,6 +390,32 @@ static int parse_each_resource(struct parse_result *result, void *user_data) } } + /* Parsing 'thermal' section */ + if (MATCH(result->section, "thermal")) { + ret = parse_thermal(result, user_data); + if (ret < 0) { + _E("cannot parse 'thermal' section\n"); + return ret; + } + + goto out; + } + + /* Parsing 'thermal.scenario' section */ + for (i = 0; i < thermal->num_scenarios; i++) { + ret = snprintf(section_name, BUFF_MAX, "thermal.scenario%d", i); + + if (MATCH(result->section, section_name)) { + ret = parse_scenario(result, &thermal->scenarios[i]); + if (ret < 0) { + _E("cannot parse 'thermal.scenario%d' section\n", i); + return ret; + } + + goto out; + } + } + out: return 0; } @@ -544,6 +620,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; if (!res) @@ -551,6 +628,7 @@ int pass_get_each_resource_config(struct pass_resource *res, char *path) cpuhp = &res->cpuhp; pmqos = &res->pmqos; + thermal = &res->thermal; res->config_data.state = PASS_UNUSED; res->config_data.gov_type = 0; @@ -573,6 +651,9 @@ int pass_get_each_resource_config(struct pass_resource *res, char *path) /* Initialize the PMQoS's data */ pmqos->state = PASS_UNUSED; + /* Initialize the Thermal's data */ + thermal->state = PASS_UNUSED; + ret = config_parse(path, parse_each_resource, res); if (ret < 0) { _E("cannot parse %s\n", path); @@ -612,5 +693,11 @@ void pass_put_each_resource_config(struct pass_resource *res) res->pmqos.scenarios = NULL; } + if (res->thermal.scenarios) { + free(res->thermal.scenarios); + res->thermal.scenarios = NULL; + res->thermal.num_scenarios = 0; + } + res->pmqos.num_scenarios = 0; } diff --git a/src/pass/pass.h b/src/pass/pass.h index 7d6db7c..55c147a 100644 --- a/src/pass/pass.h +++ b/src/pass/pass.h @@ -168,6 +168,9 @@ struct pass_level { * - locked_time: the requiired locking time of scenario. * - min_level: the required minimum PASS's level. * - max_level: the required maximum PASS's level. + * @pmqos: the private data for PASS_MODULE_THERMAL + * - temperature: the temperature of the scenario. + * - timer_interval: the interval of timer-based monitor (unit: millisecond). */ struct pass_scenario { char name[BUFF_MAX]; @@ -179,6 +182,11 @@ struct pass_scenario { unsigned int min_level; unsigned int max_level; } pmqos; + + struct { + int temperature; + int timer_interval; + } thermal; }; /****************************************************** @@ -284,6 +292,29 @@ struct pass_cpuhp { struct pass_hotplug *hotplug; }; +/* + * struct pass_thermal - Represent Thermal Monitor module + * + * @state: the state of Thermal Monitor (either enabled or disabled). + * @num_scenarios: the number of scenarios. + * @scenarios: the list of scenarios. + * @timer_interval: the interval of timer-based monitor (unit: millisecond). + * @curr_scenario_idx: the index of current thermal scenario. + * @curr_temp: the current temperature. + * + * Thermal Monitor may be enabled or disabled according to configuration. + */ +struct pass_thermal { + enum pass_state state; + + unsigned int num_scenarios; + struct pass_scenario *scenarios; + + unsigned int timer_interval; + int curr_scenario_idx; + int curr_temp; +}; + /****************************************************** * PASS Resource * ******************************************************/ @@ -412,6 +443,7 @@ struct pass_resource_init_data { * @resmon: represents ResMon (Resource Monitor) module. * @cpuhp: represents CPUHP (CPU Hotplug Manager) module. * @pmqos: represents PMQoS module. + * @thermal: represents Thermal Monitor module. */ struct pass_resource { enum pass_state state; @@ -432,6 +464,7 @@ struct pass_resource { struct pass_cpuhp cpuhp; struct pass_pmqos pmqos; + struct pass_thermal thermal; }; /****************************************************** -- 2.7.4