[PATCH v3 09/12] PM: EM: Add RCU mechanism which safely cleans the old data

From: Lukasz Luba
Date: Fri Jul 21 2023 - 11:51:07 EST


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@xxxxxxx>
---
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