[<prev] [next>] [<thread-prev] [thread-next>] [day] [month] [year] [list]
Message-Id: <20230721155022.2339982-10-lukasz.luba@arm.com>
Date: Fri, 21 Jul 2023 16:50:19 +0100
From: Lukasz Luba <lukasz.luba@....com>
To: linux-kernel@...r.kernel.org, linux-pm@...r.kernel.org,
rafael@...nel.org
Cc: lukasz.luba@....com, dietmar.eggemann@....com, rui.zhang@...el.com,
amit.kucheria@...durent.com, amit.kachhap@...il.com,
daniel.lezcano@...aro.org, viresh.kumar@...aro.org,
len.brown@...el.com, pavel@....cz, Pierre.Gondois@....com,
ionela.voinescu@....com, mhiramat@...nel.org
Subject: [PATCH v3 09/12] PM: EM: Add RCU mechanism which safely cleans the old data
The EM is going to support runtime modifications of the power data.
Introduce RCU safe mechanism to clean up the old allocated EM data.
It also adds a mutex for the EM structure to serialize the modifiers.
Signed-off-by: Lukasz Luba <lukasz.luba@....com>
---
kernel/power/energy_model.c | 42 +++++++++++++++++++++++++++++++++++++
1 file changed, 42 insertions(+)
diff --git a/kernel/power/energy_model.c b/kernel/power/energy_model.c
index c2f8a0046f8a..4596bfe7398e 100644
--- a/kernel/power/energy_model.c
+++ b/kernel/power/energy_model.c
@@ -23,6 +23,9 @@
*/
static DEFINE_MUTEX(em_pd_mutex);
+static void em_cpufreq_update_efficiencies(struct device *dev,
+ struct em_perf_state *table);
+
static bool _is_cpu_device(struct device *dev)
{
return (dev->bus == &cpu_subsys);
@@ -104,6 +107,45 @@ static void em_debug_create_pd(struct device *dev) {}
static void em_debug_remove_pd(struct device *dev) {}
#endif
+static void em_destroy_rt_table_rcu(struct rcu_head *rp)
+{
+ struct em_perf_table *runtime_table;
+
+ runtime_table = container_of(rp, struct em_perf_table, rcu);
+ kfree(runtime_table->state);
+ kfree(runtime_table);
+}
+
+static void em_destroy_tmp_setup_rcu(struct rcu_head *rp)
+{
+ struct em_perf_table *runtime_table;
+
+ runtime_table = container_of(rp, struct em_perf_table, rcu);
+ kfree(runtime_table);
+}
+
+static void em_perf_runtime_table_set(struct device *dev,
+ struct em_perf_table *runtime_table)
+{
+ struct em_perf_domain *pd = dev->em_pd;
+ struct em_perf_table *tmp;
+
+ tmp = pd->runtime_table;
+
+ rcu_assign_pointer(pd->runtime_table, runtime_table);
+
+ em_cpufreq_update_efficiencies(dev, runtime_table->state);
+
+ /*
+ * Check if the 'state' array is not actually the one from setup.
+ * If it is then don't free it.
+ */
+ if (tmp->state == pd->default_table->state)
+ call_rcu(&tmp->rcu, em_destroy_tmp_setup_rcu);
+ else
+ call_rcu(&tmp->rcu, em_destroy_rt_table_rcu);
+}
+
static int em_compute_costs(struct device *dev, struct em_perf_state *table,
struct em_data_callback *cb, int nr_states,
unsigned long flags)
--
2.25.1
Powered by blists - more mailing lists