thermal: Support multiple thermal resources 11/262411/3
authorDongwoo Lee <dwoo08.lee@samsung.com>
Tue, 3 Aug 2021 07:44:49 +0000 (16:44 +0900)
committerDongwoo Lee <dwoo08.lee@samsung.com>
Fri, 20 Aug 2021 02:57:26 +0000 (11:57 +0900)
To handle thermal scenario from multiple resources, manage the
thermal data along with its own property.

Change-Id: I933205f17dd7dc2e264fa2322b3a301b8f8e01d5
Signed-off-by: Dongwoo Lee <dwoo08.lee@samsung.com>
include/pass/device-notifier.h
src/pass/pass-thermal.c
src/thermal/thermal.c
src/thermal/thermal.h

index e1165eaf2efd8bef608463bed74dc656cad47a83..e72907a29065360aed59ad5ff3c6b8f38f05cad2 100644 (file)
@@ -41,6 +41,7 @@ struct device_notifier {
 struct device_notifier_thermal_data {
        char *name;
        char *scenario;
+       int priority;
 };
 
 /*
index 2a122aca92c4b774428d38f6d0c14c393a734a86..f6ae26a57b52de61a811d806ee7df8a934839e0c 100644 (file)
@@ -34,6 +34,7 @@
 #include "pass-resmon.h"
 
 #define DEFAULT_TEMPERATURE            (-1000)
+#define DEFAULT_THERMAL_PRIORITY       (INT_MAX)
 
 static int thermal_update(struct pass_resource *res,
                        struct resmon_result_src_thermal *thermal_result)
@@ -170,6 +171,7 @@ static int thermal_monitor_func(void *result, void *user_data)
        thermal_data.name = res->config_data.res_thermal_name;
        thermal_data.scenario =
                thermal->scenarios[thermal->curr_scenario_idx].name;
+       thermal_data.priority = DEFAULT_THERMAL_PRIORITY;
 
        /*
         * Send notification with thermal scenario name according to
index e4a55495c4e7b5d76d882ca9a3d0be4b5d2bbc77..6b9a04efcd42cc832e65d3085eaa975500dc089c 100644 (file)
@@ -91,6 +91,8 @@ static void thermal_free(void)
        if (ret < 0)
                _E("failed to pet Thermal Monitor scenario\n");
 
+       g_ptr_array_free(g_thermal->resources, TRUE);
+
        free(g_thermal);
        g_thermal = NULL;
 }
@@ -134,16 +136,26 @@ static int thermal_init_done(void *data, void *user_data)
                return ret;
        }
 
+       g_thermal->resources = g_ptr_array_new_with_free_func(free);
+
        for (i = 0; i < g_thermal->num; i++) {
                if (g_thermal->list[i].support)
                        _I("Support \'%-12s\' thermal scenario",
                                        g_thermal->list[i].name);
        }
 
+       /* FIXME:
+        * Currently, initial thermal scenario among multiple resources are not
+        * settled properly; it is rather determined by one of scenario initialized
+        * lastly. So, it is required that the method for retrieving the current
+        * state of each device here.
+        */
+
        device_notify(DEVICE_NOTIFIER_THERMAL_GET_SCENARIO, &scenario);
 
        if (!scenario) {
                _E("failed to get current scenario for thermal\n");
+               g_ptr_array_free(g_thermal->resources, TRUE);
                free(g_thermal);
                g_thermal = NULL;
                return -EINVAL;
@@ -163,6 +175,7 @@ static int thermal_init_done(void *data, void *user_data)
                ret = thermal_put_scenario(g_thermal);
                if (ret < 0) {
                        _E("failed to put Thermal Monitor scenario\n");
+                       g_ptr_array_free(g_thermal->resources, TRUE);
                        free(g_thermal);
                        g_thermal = NULL;
                }
@@ -249,6 +262,60 @@ static struct pass_gdbus_signal_info g_gdbus_signal_infos[] = {
        },
 };
 
+/**
+ * @brief      Add thermal devices using key as thermal_device_name from
+ *             thermal data, or update current scenario of each thermal device
+ *
+ * @param      [in] data thermal data from thermal monitors
+ */
+static int thermal_handle_notifier_data(struct device_notifier_thermal_data *data)
+{
+       struct device_notifier_thermal_data *entry = NULL;
+       int priority = data->priority;
+       int i;
+
+       if (priority < 0)
+               return -EINVAL;
+
+       /*
+        * If current notification has highest priority, then discards
+        * previous ones and makes the new list. Otherwise, check existence
+        * of current thermal data and if so, updates scenario, or else adds
+        * data into current resource list.
+        */
+       if (priority > g_thermal->cur_priority) {
+               g_thermal->cur_priority = priority;
+               g_ptr_array_free(g_thermal->resources, TRUE);
+               g_thermal->resources = g_ptr_array_new_with_free_func(free);
+       } else {
+               int n = strlen(data->name);
+
+               for (i = 0; i < g_thermal->resources->len; i++) {
+                       struct device_notifier_thermal_data *e;
+
+                       e = g_ptr_array_index(g_thermal->resources, i);
+                       if (!strncmp(e->name, data->name, n)) {
+                               entry = e;
+                               break;
+                       }
+               }
+       }
+
+       if (entry) {
+               strncpy(entry->scenario, data->scenario, strlen(data->scenario) + 1);
+       } else {
+               entry = malloc(sizeof(*data));
+               if (!entry)
+                       return -ENOMEM;
+
+               memcpy(entry, data, sizeof(*data));
+
+               g_ptr_array_add(g_thermal->resources, entry);
+       }
+
+       return 0;
+}
+
 /**
  * @brief      Send broadcasting signal with the decided scenario name from
  *             pass-thermal before checking whether the scenario is supported
@@ -260,9 +327,10 @@ static int thermal_notifier_cb(void *data, void *user_data)
 {
        struct device_notifier_thermal_data *thermal_data = data;
        GVariant *gvar;
-       const char *scenario;
+       const char *scenario = "Undefined";
+       int scenario_idx = -1;
        int ret;
-       int i;
+       int i, j;
 
        if (!g_thermal || !g_thermal->support || g_thermal->num <= 0) {
                _I("Thermal Monitor is stopped\n");
@@ -274,21 +342,39 @@ static int thermal_notifier_cb(void *data, void *user_data)
 
        scenario = thermal_data->scenario;
 
-       /* Find the available thermal scenario */
-       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;
+       /* Ignore the notification of lower priority resources */
+       if (thermal_data->priority < g_thermal->cur_priority)
+               return 0;
+
+       ret = thermal_handle_notifier_data(thermal_data);
+       if (ret)
+               return ret;
+
+       /* Find the highest scenario among available thermal resources */
+       for (i = 0; i < g_thermal->resources->len; i++) {
+               struct device_notifier_thermal_data *e;
+
+               e = (g_ptr_array_index(g_thermal->resources, i));
+               for (j = 0; j < g_thermal->num; j++) {
+                       if (!strncmp(g_thermal->list[j].name,
+                                    e->scenario, strlen(e->scenario))) {
+                               if (j > scenario_idx) {
+                                       if (g_thermal->list[j].support)
+                                               scenario_idx = j;
+                                       scenario = e->scenario;
+                               }
+                               break;
+                       }
+               }
        }
 
        /* If there is no available thermal scenario, just return */
-       if (i >= g_thermal->num) {
+       if (scenario_idx < 0) {
                _I("Not supported \'%s\' scenario", scenario);
                return 0;
        }
 
-       g_thermal->cur_scenario_idx = i;
+       g_thermal->cur_scenario_idx = scenario_idx;
 
        /* If there is available thermal scenario, send the broadcast signal */
        gvar = g_variant_new("(s)", scenario);
index c65ec75d42b6c1dc6a5152810ae03f55ad113a6d..4257bbb13509972b4e7995c19cb7e1b035c19970 100644 (file)
@@ -32,6 +32,7 @@
 
 #include <stdbool.h>
 #include <limits.h>
+#include <glib.h>
 
 /**
  * @brief      Represent Thermal Monitor feature of PASS(Power Aware System
@@ -50,6 +51,10 @@ struct thermal_scenario {
        bool support;
        /** Represent current idx of thermal scenario */
        int cur_scenario_idx;
+       /** List of state of thermal devices */
+       GPtrArray *resources;
+       /** Represent current highest priority level of thermal devices */
+       int cur_priority;
 };
 
 int thermal_get_scenario(const char *path, struct thermal_scenario *scenarios);