DEVICE_NOTIFIER_INIT_DONE,
DEVICE_NOTIFIER_PMQOS,
DEVICE_NOTIFIER_THERMAL,
+ DEVICE_NOTIFIER_THERMAL_GET_SCENARIO,
DEVICE_NOTIFIER_MAX,
};
static int resmon_thermal_init(struct resmon *monitor)
{
struct resmon_result_src_thermal *result;
+ struct pass_resmon *resmon = monitor->resmon;
+ struct pass_resource *res =
+ container_of(resmon, struct pass_resource, resmon);
if (monitor->result)
return 0;
result = calloc(1, sizeof(*result));
if (!result)
return -ENOMEM;
+ /*
+ * To handle GetCoolDownStatus method before the first timer of
+ * resource monitor for thermal is ticked, get current temperature
+ * in advance.
+ */
+ result->temp = pass_get_temp(res);
monitor->result = result;
return true;
}
+void *pass_resmon_get_result(struct pass_resource *res,
+ enum resmon_src_type src_type)
+{
+ struct resmon *monitor;
+
+ if (!res)
+ return NULL;
+
+ monitor = resmon_find_monitor(&res->resmon, RESMON_TIMER, src_type);
+ if (!monitor)
+ return NULL;
+
+ return monitor->result;
+}
+
/**
* @brief Register a timer-based resource monitor.
* @param [in] res Instance of a resource monitor
unsigned int avg_thread_runnable_load;
};
+void *pass_resmon_get_result(struct pass_resource *res,
+ enum resmon_src_type src_type);
+
/*
* pass_resmon_register_timer - Register timer-based resource monitor.
*
return 0;
}
+static inline void *get_thermal_result(struct pass_resource *res)
+{
+ return pass_resmon_get_result(res, RESMON_SRC_THERMAL);
+}
+
+static int thermal_get_scenario(void **scenario, void *user_data)
+{
+ struct pass_resource *res = user_data;
+ struct resmon_result_src_thermal *thermal_result;
+ struct pass_thermal *thermal;
+ int curr_temp, temp;
+ int i, scenario_idx;
+
+ if (!res) {
+ _E("invalid parameter\n");
+ return -EINVAL;
+ }
+
+ thermal = &res->thermal;
+
+ thermal_result = get_thermal_result(res);
+ if (!thermal_result)
+ return -EINVAL;
+
+ curr_temp = thermal_result->temp;
+
+ for (i = thermal->num_scenarios - 1; i > 0; i--) {
+ temp = thermal->scenarios[i].thermal.temperature;
+
+ if (thermal->scenarios[i].state != PASS_ON)
+ continue;
+
+ if (temp <= curr_temp)
+ break;
+ }
+ scenario_idx = i;
+
+ *scenario = (void *)thermal->scenarios[scenario_idx].name;
+
+ thermal->curr_temp = curr_temp;
+ thermal->curr_scenario_idx = scenario_idx;
+
+ return 0;
+}
+
/**
* @brief Initialize PASS_MODULE_THERMAL(Thermal Monitor) module.
* @param [in] res Instance of h/w resource
res->thermal.curr_scenario_idx = -1;
res->thermal.curr_temp = DEFAULT_TEMPERATURE;
+ ret = register_notifier(DEVICE_NOTIFIER_THERMAL_GET_SCENARIO,
+ thermal_get_scenario, res);
+ if (ret < 0) {
+ _E("failed to register a notifier callback\n");
+ goto err_uevent;
+ }
+
return 0;
+err_uevent:
+ ret = pass_resmon_unregister_uevent(res, RESMON_SRC_THERMAL);
+ if (ret < 0)
+ _E("failed to unregister uevent-based monitor\n");
+
err_timer:
ret = pass_resmon_unregister_timer(res, RESMON_SRC_THERMAL);
if (ret < 0) {
if (res->thermal.state != PASS_ON)
return 0;
+ ret = unregister_notifier(DEVICE_NOTIFIER_THERMAL_GET_SCENARIO,
+ thermal_get_scenario, res);
+ if (ret < 0)
+ _E("failed to unregister a notifier callback\n");
+
ret = pass_resmon_unregister_uevent(res, RESMON_SRC_THERMAL);
if (ret < 0) {
_E("failed to unregister uevent-based monitor " \
*/
static int thermal_init_done(void *data, void *user_data)
{
- int ret;
- int i;
+ char *scenario = NULL;
+ int ret, i;
if (g_thermal)
return 0;
return ret;
}
- g_thermal->cur_scenario_idx = -1;
-
for (i = 0; i < g_thermal->num; i++)
if (g_thermal->list[i].support)
_I("Support \'%s\' scenario", g_thermal->list[i].name);
+ device_notify(DEVICE_NOTIFIER_THERMAL_GET_SCENARIO, &scenario);
+
+ if (!scenario) {
+ _E("failed to get current scenario for thermal\n");
+ free(g_thermal);
+ g_thermal = NULL;
+ return -EINVAL;
+ }
+
+ for (i = 0; i < g_thermal->num; i++) {
+ if (!g_thermal->list[i].support)
+ continue;
+ if (!strncmp(g_thermal->list[i].name,
+ scenario, strlen(scenario)))
+ break;
+ }
+
+ if (i >= g_thermal->num) {
+ _E("failed to match current thermal scenario");
+
+ ret = thermal_put_scenario(g_thermal);
+ if (ret < 0) {
+ _E("failed to put Thermal Monitor scenario\n");
+ free(g_thermal);
+ g_thermal = NULL;
+ }
+
+ return -EINVAL;
+ }
+
+ g_thermal->cur_scenario_idx = i;
+
return 0;
}