All of lore.kernel.org
 help / color / mirror / Atom feed
From: Srinivas Pandruvada <srinivas.pandruvada@linux.intel.com>
To: rui.zhang@intel.com, daniel.lezcano@linaro.org,
	rjw@rjwysocki.net, lenb@kernel.org, amitk@kernel.org
Cc: linux-pm@vger.kernel.org,
	Srinivas Pandruvada <srinivas.pandruvada@linux.intel.com>
Subject: [RFC PATCH 1/3] thermal/drivers/cpuidle_cooling: Reorganize cpuidle cooling driver
Date: Mon, 23 Aug 2021 22:17:29 -0700	[thread overview]
Message-ID: <20210824051731.2495462-2-srinivas.pandruvada@linux.intel.com> (raw)
In-Reply-To: <20210824051731.2495462-1-srinivas.pandruvada@linux.intel.com>

Reorganize cpuidle cooling driver, so that it can be reused for non
DT/ARM implementations.

No functional changes are expected.

To reorganize:
- Split cpuidle cooling driver into two parts, one common and on DT
specific
- The common part is moved to cpuidle_cooling_core.c
- The DT specific part is left in cpuidle_cooling.c
- cpuidle_cooling_device structure is moved to a header file
- Created interface cpuidle_cooling_get_ops() to get cdev callbacks

While here, fixed some checkpatch warnings.

Signed-off-by: Srinivas Pandruvada <srinivas.pandruvada@linux.intel.com>
---
 drivers/thermal/Kconfig                |   6 +-
 drivers/thermal/Makefile               |   1 +
 drivers/thermal/cpuidle_cooling.c      | 141 +----------------------
 drivers/thermal/cpuidle_cooling_core.c | 148 +++++++++++++++++++++++++
 drivers/thermal/cpuidle_cooling_core.h |  24 ++++
 5 files changed, 180 insertions(+), 140 deletions(-)
 create mode 100644 drivers/thermal/cpuidle_cooling_core.c
 create mode 100644 drivers/thermal/cpuidle_cooling_core.h

diff --git a/drivers/thermal/Kconfig b/drivers/thermal/Kconfig
index d7f44deab5b1..3d669a1774d3 100644
--- a/drivers/thermal/Kconfig
+++ b/drivers/thermal/Kconfig
@@ -167,6 +167,10 @@ config CPU_THERMAL
 	  cooling device available, this option allows to use the CPU
 	  as a cooling device.
 
+config CPU_IDLE_THERMAL_CORE
+	bool
+	depends on IDLE_INJECT
+
 if CPU_THERMAL
 
 config CPU_FREQ_THERMAL
@@ -182,7 +186,7 @@ config CPU_FREQ_THERMAL
 
 config CPU_IDLE_THERMAL
 	bool "CPU idle cooling device"
-	depends on IDLE_INJECT
+	select CPU_IDLE_THERMAL_CORE
 	help
 	  This implements the CPU cooling mechanism through
 	  idle injection. This will throttle the CPU by injecting
diff --git a/drivers/thermal/Makefile b/drivers/thermal/Makefile
index 82fc3e616e54..769d025beb11 100644
--- a/drivers/thermal/Makefile
+++ b/drivers/thermal/Makefile
@@ -23,6 +23,7 @@ thermal_sys-$(CONFIG_THERMAL_GOV_POWER_ALLOCATOR)	+= gov_power_allocator.o
 
 # cpufreq cooling
 thermal_sys-$(CONFIG_CPU_FREQ_THERMAL)	+= cpufreq_cooling.o
+thermal_sys-$(CONFIG_CPU_IDLE_THERMAL_CORE)	+= cpuidle_cooling_core.o
 thermal_sys-$(CONFIG_CPU_IDLE_THERMAL)	+= cpuidle_cooling.o
 
 # devfreq cooling
diff --git a/drivers/thermal/cpuidle_cooling.c b/drivers/thermal/cpuidle_cooling.c
index 4f41102e8b16..863c811e0d26 100644
--- a/drivers/thermal/cpuidle_cooling.c
+++ b/drivers/thermal/cpuidle_cooling.c
@@ -9,150 +9,13 @@
 
 #include <linux/cpu_cooling.h>
 #include <linux/cpuidle.h>
-#include <linux/device.h>
 #include <linux/err.h>
 #include <linux/idle_inject.h>
 #include <linux/of_device.h>
 #include <linux/slab.h>
 #include <linux/thermal.h>
 
-/**
- * struct cpuidle_cooling_device - data for the idle cooling device
- * @ii_dev: an atomic to keep track of the last task exiting the idle cycle
- * @state: a normalized integer giving the state of the cooling device
- */
-struct cpuidle_cooling_device {
-	struct idle_inject_device *ii_dev;
-	unsigned long state;
-};
-
-/**
- * cpuidle_cooling_runtime - Running time computation
- * @idle_duration_us: CPU idle time to inject in microseconds
- * @state: a percentile based number
- *
- * The running duration is computed from the idle injection duration
- * which is fixed. If we reach 100% of idle injection ratio, that
- * means the running duration is zero. If we have a 50% ratio
- * injection, that means we have equal duration for idle and for
- * running duration.
- *
- * The formula is deduced as follows:
- *
- *  running = idle x ((100 / ratio) - 1)
- *
- * For precision purpose for integer math, we use the following:
- *
- *  running = (idle x 100) / ratio - idle
- *
- * For example, if we have an injected duration of 50%, then we end up
- * with 10ms of idle injection and 10ms of running duration.
- *
- * Return: An unsigned int for a usec based runtime duration.
- */
-static unsigned int cpuidle_cooling_runtime(unsigned int idle_duration_us,
-					    unsigned long state)
-{
-	if (!state)
-		return 0;
-
-	return ((idle_duration_us * 100) / state) - idle_duration_us;
-}
-
-/**
- * cpuidle_cooling_get_max_state - Get the maximum state
- * @cdev  : the thermal cooling device
- * @state : a pointer to the state variable to be filled
- *
- * The function always returns 100 as the injection ratio. It is
- * percentile based for consistency accross different platforms.
- *
- * Return: The function can not fail, it is always zero
- */
-static int cpuidle_cooling_get_max_state(struct thermal_cooling_device *cdev,
-					 unsigned long *state)
-{
-	/*
-	 * Depending on the configuration or the hardware, the running
-	 * cycle and the idle cycle could be different. We want to
-	 * unify that to an 0..100 interval, so the set state
-	 * interface will be the same whatever the platform is.
-	 *
-	 * The state 100% will make the cluster 100% ... idle. A 0%
-	 * injection ratio means no idle injection at all and 50%
-	 * means for 10ms of idle injection, we have 10ms of running
-	 * time.
-	 */
-	*state = 100;
-
-	return 0;
-}
-
-/**
- * cpuidle_cooling_get_cur_state - Get the current cooling state
- * @cdev: the thermal cooling device
- * @state: a pointer to the state
- *
- * The function just copies  the state value from the private thermal
- * cooling device structure, the mapping is 1 <-> 1.
- *
- * Return: The function can not fail, it is always zero
- */
-static int cpuidle_cooling_get_cur_state(struct thermal_cooling_device *cdev,
-					 unsigned long *state)
-{
-	struct cpuidle_cooling_device *idle_cdev = cdev->devdata;
-
-	*state = idle_cdev->state;
-
-	return 0;
-}
-
-/**
- * cpuidle_cooling_set_cur_state - Set the current cooling state
- * @cdev: the thermal cooling device
- * @state: the target state
- *
- * The function checks first if we are initiating the mitigation which
- * in turn wakes up all the idle injection tasks belonging to the idle
- * cooling device. In any case, it updates the internal state for the
- * cooling device.
- *
- * Return: The function can not fail, it is always zero
- */
-static int cpuidle_cooling_set_cur_state(struct thermal_cooling_device *cdev,
-					 unsigned long state)
-{
-	struct cpuidle_cooling_device *idle_cdev = cdev->devdata;
-	struct idle_inject_device *ii_dev = idle_cdev->ii_dev;
-	unsigned long current_state = idle_cdev->state;
-	unsigned int runtime_us, idle_duration_us;
-
-	idle_cdev->state = state;
-
-	idle_inject_get_duration(ii_dev, &runtime_us, &idle_duration_us);
-
-	runtime_us = cpuidle_cooling_runtime(idle_duration_us, state);
-
-	idle_inject_set_duration(ii_dev, runtime_us, idle_duration_us);
-
-	if (current_state == 0 && state > 0) {
-		idle_inject_start(ii_dev);
-	} else if (current_state > 0 && !state)  {
-		idle_inject_stop(ii_dev);
-	}
-
-	return 0;
-}
-
-/**
- * cpuidle_cooling_ops - thermal cooling device ops
- */
-static struct thermal_cooling_device_ops cpuidle_cooling_ops = {
-	.get_max_state = cpuidle_cooling_get_max_state,
-	.get_cur_state = cpuidle_cooling_get_cur_state,
-	.set_cur_state = cpuidle_cooling_set_cur_state,
-};
+#include "cpuidle_cooling_core.h"
 
 /**
  * __cpuidle_cooling_register: register the cooling device
@@ -207,7 +70,7 @@ static int __cpuidle_cooling_register(struct device_node *np,
 	}
 
 	cdev = thermal_of_cooling_device_register(np, name, idle_cdev,
-						  &cpuidle_cooling_ops);
+						  cpuidle_cooling_get_ops());
 	if (IS_ERR(cdev)) {
 		ret = PTR_ERR(cdev);
 		goto out_kfree_name;
diff --git a/drivers/thermal/cpuidle_cooling_core.c b/drivers/thermal/cpuidle_cooling_core.c
new file mode 100644
index 000000000000..20bf02b4e168
--- /dev/null
+++ b/drivers/thermal/cpuidle_cooling_core.c
@@ -0,0 +1,148 @@
+// SPDX-License-Identifier: GPL-2.0
+/*
+ *  Copyright (C) 2019 Linaro Limited.
+ *
+ *  Author: Daniel Lezcano <daniel.lezcano@linaro.org>
+ *
+ */
+#define pr_fmt(fmt) "cpuidle cooling: " fmt
+
+#include <linux/device.h>
+#include <linux/err.h>
+#include <linux/idle_inject.h>
+#include <linux/thermal.h>
+
+#include "cpuidle_cooling_core.h"
+
+/**
+ * cpuidle_cooling_runtime - Running time computation
+ * @idle_duration_us: CPU idle time to inject in microseconds
+ * @state: a percentile based number
+ *
+ * The running duration is computed from the idle injection duration
+ * which is fixed. If we reach 100% of idle injection ratio, that
+ * means the running duration is zero. If we have a 50% ratio
+ * injection, that means we have equal duration for idle and for
+ * running duration.
+ *
+ * The formula is deduced as follows:
+ *
+ *  running = idle x ((100 / ratio) - 1)
+ *
+ * For precision purpose for integer math, we use the following:
+ *
+ *  running = (idle x 100) / ratio - idle
+ *
+ * For example, if we have an injected duration of 50%, then we end up
+ * with 10ms of idle injection and 10ms of running duration.
+ *
+ * Return: An unsigned int for a usec based runtime duration.
+ */
+static unsigned int cpuidle_cooling_runtime(unsigned int idle_duration_us,
+					    unsigned long state)
+{
+	if (!state)
+		return 0;
+
+	return ((idle_duration_us * 100) / state) - idle_duration_us;
+}
+
+/**
+ * cpuidle_cooling_get_max_state - Get the maximum state
+ * @cdev  : the thermal cooling device
+ * @state : a pointer to the state variable to be filled
+ *
+ * The function always returns 100 as the injection ratio. It is
+ * percentile based for consistency across different platforms.
+ *
+ * Return: The function can not fail, it is always zero
+ */
+static int cpuidle_cooling_get_max_state(struct thermal_cooling_device *cdev,
+					 unsigned long *state)
+{
+	/*
+	 * Depending on the configuration or the hardware, the running
+	 * cycle and the idle cycle could be different. We want to
+	 * unify that to an 0..100 interval, so the set state
+	 * interface will be the same whatever the platform is.
+	 *
+	 * The state 100% will make the cluster 100% ... idle. A 0%
+	 * injection ratio means no idle injection at all and 50%
+	 * means for 10ms of idle injection, we have 10ms of running
+	 * time.
+	 */
+	*state = 100;
+
+	return 0;
+}
+
+/**
+ * cpuidle_cooling_get_cur_state - Get the current cooling state
+ * @cdev: the thermal cooling device
+ * @state: a pointer to the state
+ *
+ * The function just copies  the state value from the private thermal
+ * cooling device structure, the mapping is 1 <-> 1.
+ *
+ * Return: The function can not fail, it is always zero
+ */
+static int cpuidle_cooling_get_cur_state(struct thermal_cooling_device *cdev,
+					 unsigned long *state)
+{
+	struct cpuidle_cooling_device *idle_cdev = cdev->devdata;
+
+	*state = idle_cdev->state;
+
+	return 0;
+}
+
+/**
+ * cpuidle_cooling_set_cur_state - Set the current cooling state
+ * @cdev: the thermal cooling device
+ * @state: the target state
+ *
+ * The function checks first if we are initiating the mitigation which
+ * in turn wakes up all the idle injection tasks belonging to the idle
+ * cooling device. In any case, it updates the internal state for the
+ * cooling device.
+ *
+ * Return: The function can not fail, it is always zero
+ */
+static int cpuidle_cooling_set_cur_state(struct thermal_cooling_device *cdev,
+					 unsigned long state)
+{
+	struct cpuidle_cooling_device *idle_cdev = cdev->devdata;
+	struct idle_inject_device *ii_dev = idle_cdev->ii_dev;
+	unsigned long current_state = idle_cdev->state;
+	unsigned int runtime_us, idle_duration_us;
+
+	idle_cdev->state = state;
+
+	idle_inject_get_duration(ii_dev, &runtime_us, &idle_duration_us);
+
+	runtime_us = cpuidle_cooling_runtime(idle_duration_us, state);
+
+	idle_inject_set_duration(ii_dev, runtime_us, idle_duration_us);
+
+	if (current_state == 0 && state > 0)
+		idle_inject_start(ii_dev);
+	else if (current_state > 0 && !state)
+		idle_inject_stop(ii_dev);
+
+	return 0;
+}
+
+/**
+ * cpuidle_cooling_ops - thermal cooling device ops
+ */
+static struct thermal_cooling_device_ops cpuidle_cooling_ops = {
+	.get_max_state = cpuidle_cooling_get_max_state,
+	.get_cur_state = cpuidle_cooling_get_cur_state,
+	.set_cur_state = cpuidle_cooling_set_cur_state,
+};
+
+struct thermal_cooling_device_ops *cpuidle_cooling_get_ops(void)
+{
+	return &cpuidle_cooling_ops;
+}
+EXPORT_SYMBOL_GPL(cpuidle_cooling_get_ops);
diff --git a/drivers/thermal/cpuidle_cooling_core.h b/drivers/thermal/cpuidle_cooling_core.h
new file mode 100644
index 000000000000..9b9701334a8c
--- /dev/null
+++ b/drivers/thermal/cpuidle_cooling_core.h
@@ -0,0 +1,24 @@
+/* SPDX-License-Identifier: GPL-2.0-only */
+/*
+ *  Copyright (C) 2019 Linaro Limited.
+ *
+ *  Author: Daniel Lezcano <daniel.lezcano@linaro.org>
+ *
+ */
+
+ #ifndef _CPUIDLE_COOLING_CORE_H
+ #define _CPUIDLE_COOLING_CORE_H
+
+/**
+ * struct cpuidle_cooling_device - data for the idle cooling device
+ * @ii_dev: an atomic to keep track of the last task exiting the idle cycle
+ * @state: a normalized integer giving the state of the cooling device
+ */
+struct cpuidle_cooling_device {
+	struct idle_inject_device *ii_dev;
+	unsigned long state;
+};
+
+struct thermal_cooling_device_ops *cpuidle_cooling_get_ops(void);
+
+#endif
-- 
2.30.2


  reply	other threads:[~2021-08-24  5:17 UTC|newest]

Thread overview: 5+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2021-08-24  5:17 [RFC PATCH 0/3] Reuse cpuidle cooling for non DT/ARM Srinivas Pandruvada
2021-08-24  5:17 ` Srinivas Pandruvada [this message]
2021-08-24  5:17 ` [RFC PATCH 2/3] powercap: idle_inject: Export symbols Srinivas Pandruvada
2021-08-24  5:17 ` [RFC PATCH 3/3] thermal/drivers/cpuidle_cooling: cpuidle cooling driver for non DT/ARM Srinivas Pandruvada
2021-08-24 10:34   ` kernel test robot

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=20210824051731.2495462-2-srinivas.pandruvada@linux.intel.com \
    --to=srinivas.pandruvada@linux.intel.com \
    --cc=amitk@kernel.org \
    --cc=daniel.lezcano@linaro.org \
    --cc=lenb@kernel.org \
    --cc=linux-pm@vger.kernel.org \
    --cc=rjw@rjwysocki.net \
    --cc=rui.zhang@intel.com \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.