[<prev] [next>] [day] [month] [year] [list]
Message-Id: <20250930060504.806813-1-tianyaxiong@kylinos.cn>
Date: Tue, 30 Sep 2025 14:05:04 +0800
From: Yaxiong Tian <tianyaxiong@...inos.cn>
To: myungjoo.ham@...sung.com,
kyungmin.park@...sung.com,
cw00.choi@...sung.com
Cc: linux-pm@...r.kernel.org,
linux-kernel@...r.kernel.org,
Yaxiong Tian <tianyaxiong@...inos.cn>
Subject: [PATCH] PM / devfreq: Optimize simple_ondemand by avoiding redundant checks in devfreq_simple_ondemand_func()
The current implementation performs unnecessary validation checks for
dfso_upthreshold and dfso_downdifferential on every call to
devfreq_simple_ondemand_func(). This is inefficient since this function
is called very frequently during normal operation.
The validation logic should be handled during governor initialization
rather than during each performance evaluation.
To resolve this issue:
- Initialize and store the threshold values in governor_data during D
EVFREQ_GOV_START
- Use the pre-validated values directly from governor_data in
devfreq_simple_ondemand_func()
- Clean up and free governor_data during DEVFREQ_GOV_STOP
This optimization reduces overhead in the hot path and improves
overall performance of the simple_ondemand governor.
Signed-off-by: Yaxiong Tian <tianyaxiong@...inos.cn>
---
drivers/devfreq/governor_simpleondemand.c | 65 ++++++++++++++++++-----
1 file changed, 53 insertions(+), 12 deletions(-)
diff --git a/drivers/devfreq/governor_simpleondemand.c b/drivers/devfreq/governor_simpleondemand.c
index c23435736367..40803888e420 100644
--- a/drivers/devfreq/governor_simpleondemand.c
+++ b/drivers/devfreq/governor_simpleondemand.c
@@ -10,6 +10,7 @@
#include <linux/module.h>
#include <linux/devfreq.h>
#include <linux/math64.h>
+#include <linux/slab.h>
#include "governor.h"
/* Default constants for DevFreq-Simple-Ondemand (DFSO) */
@@ -21,9 +22,11 @@ static int devfreq_simple_ondemand_func(struct devfreq *df,
int err;
struct devfreq_dev_status *stat;
unsigned long long a, b;
- unsigned int dfso_upthreshold = DFSO_UPTHRESHOLD;
- unsigned int dfso_downdifferential = DFSO_DOWNDIFFERENCTIAL;
- struct devfreq_simple_ondemand_data *data = df->data;
+ unsigned int dfso_upthreshold, dfso_downdifferential;
+ struct devfreq_simple_ondemand_data *data = df->governor_data;
+
+ if (unlikely(!data))
+ return -ENOMEM;
err = devfreq_update_stats(df);
if (err)
@@ -31,12 +34,9 @@ static int devfreq_simple_ondemand_func(struct devfreq *df,
stat = &df->last_status;
- if (data) {
- if (data->upthreshold)
- dfso_upthreshold = data->upthreshold;
- if (data->downdifferential)
- dfso_downdifferential = data->downdifferential;
- }
+ dfso_upthreshold = data->upthreshold;
+ dfso_downdifferential = data->downdifferential;
+
if (dfso_upthreshold > 100 ||
dfso_upthreshold < dfso_downdifferential)
return -EINVAL;
@@ -84,16 +84,57 @@ static int devfreq_simple_ondemand_func(struct devfreq *df,
return 0;
}
+static int simple_ondemand_init(struct devfreq *devfreq)
+{
+ struct devfreq_simple_ondemand_data *gov_data, *df_data;
+
+
+ gov_data = kzalloc(sizeof(struct devfreq_simple_ondemand_data),
+ GFP_KERNEL);
+
+ if (!gov_data) {
+ dev_err(&devfreq->dev, "Can't alloc devfreq_simple_ondemand_data\n");
+ return -ENOMEM;
+ }
+
+
+ df_data = devfreq->data;
+ gov_data->upthreshold = DFSO_UPTHRESHOLD;
+ gov_data->downdifferential = DFSO_DOWNDIFFERENCTIAL;
+
+ if (df_data) {
+ if (df_data->upthreshold)
+ gov_data->upthreshold = df_data->upthreshold;
+
+ if (df_data->downdifferential)
+ gov_data->downdifferential = df_data->downdifferential;
+ }
+
+ devfreq->governor_data = gov_data;
+ devfreq_monitor_start(devfreq);
+
+ return 0;
+}
+
+static void simple_ondemand_exit(struct devfreq *devfreq)
+{
+ devfreq_monitor_stop(devfreq);
+ kfree(devfreq->governor_data);
+ devfreq->governor_data = NULL;
+}
+
static int devfreq_simple_ondemand_handler(struct devfreq *devfreq,
unsigned int event, void *data)
{
+ int ret = 0;
+
switch (event) {
case DEVFREQ_GOV_START:
- devfreq_monitor_start(devfreq);
+ ret = simple_ondemand_init(devfreq);
break;
case DEVFREQ_GOV_STOP:
- devfreq_monitor_stop(devfreq);
+ simple_ondemand_exit(devfreq);
break;
case DEVFREQ_GOV_UPDATE_INTERVAL:
@@ -112,7 +153,7 @@ static int devfreq_simple_ondemand_handler(struct devfreq *devfreq,
break;
}
- return 0;
+ return ret;
}
static struct devfreq_governor devfreq_simple_ondemand = {
--
2.25.1
Powered by blists - more mailing lists