All of lore.kernel.org
 help / color / mirror / Atom feed
* [RFC PATCH 0/3] Reuse cpuidle cooling for non DT/ARM
@ 2021-08-24  5:17 Srinivas Pandruvada
  2021-08-24  5:17 ` [RFC PATCH 1/3] thermal/drivers/cpuidle_cooling: Reorganize cpuidle cooling driver Srinivas Pandruvada
                   ` (2 more replies)
  0 siblings, 3 replies; 5+ messages in thread
From: Srinivas Pandruvada @ 2021-08-24  5:17 UTC (permalink / raw)
  To: rui.zhang, daniel.lezcano, rjw, lenb, amitk; +Cc: linux-pm, Srinivas Pandruvada

This patchset reused existing cpuidle cooling implementation and
develops a new driver which can be used in non DT/ARM platforms.

This has added advantage for per cpu idle injection instead of
a global one using Intel powerclamp driver.

Srinivas Pandruvada (3):
  thermal/drivers/cpuidle_cooling: Reorganize cpuidle cooling driver
  powercap: idle_inject: Export symbols
  thermal/drivers/cpuidle_cooling: cpuidle cooling driver for non DT/ARM

 drivers/powercap/idle_inject.c            |   4 +
 drivers/thermal/Kconfig                   |  18 ++-
 drivers/thermal/Makefile                  |   3 +
 drivers/thermal/cpuidle_cooling.c         | 141 +-------------------
 drivers/thermal/cpuidle_cooling_core.c    | 148 +++++++++++++++++++++
 drivers/thermal/cpuidle_cooling_core.h    |  24 ++++
 drivers/thermal/cpuidle_cooling_generic.c | 155 ++++++++++++++++++++++
 7 files changed, 353 insertions(+), 140 deletions(-)
 create mode 100644 drivers/thermal/cpuidle_cooling_core.c
 create mode 100644 drivers/thermal/cpuidle_cooling_core.h
 create mode 100644 drivers/thermal/cpuidle_cooling_generic.c

-- 
2.30.2


^ permalink raw reply	[flat|nested] 5+ messages in thread

* [RFC PATCH 1/3] thermal/drivers/cpuidle_cooling: Reorganize cpuidle cooling driver
  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
  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
  2 siblings, 0 replies; 5+ messages in thread
From: Srinivas Pandruvada @ 2021-08-24  5:17 UTC (permalink / raw)
  To: rui.zhang, daniel.lezcano, rjw, lenb, amitk; +Cc: linux-pm, Srinivas Pandruvada

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


^ permalink raw reply related	[flat|nested] 5+ messages in thread

* [RFC PATCH 2/3] powercap: idle_inject: Export symbols
  2021-08-24  5:17 [RFC PATCH 0/3] Reuse cpuidle cooling for non DT/ARM Srinivas Pandruvada
  2021-08-24  5:17 ` [RFC PATCH 1/3] thermal/drivers/cpuidle_cooling: Reorganize cpuidle cooling driver Srinivas Pandruvada
@ 2021-08-24  5:17 ` Srinivas Pandruvada
  2021-08-24  5:17 ` [RFC PATCH 3/3] thermal/drivers/cpuidle_cooling: cpuidle cooling driver for non DT/ARM Srinivas Pandruvada
  2 siblings, 0 replies; 5+ messages in thread
From: Srinivas Pandruvada @ 2021-08-24  5:17 UTC (permalink / raw)
  To: rui.zhang, daniel.lezcano, rjw, lenb, amitk; +Cc: linux-pm, Srinivas Pandruvada

Export symbols for interfaces used in other files. In this way the
caller can be a module.

Signed-off-by: Srinivas Pandruvada <srinivas.pandruvada@linux.intel.com>
---
 drivers/powercap/idle_inject.c | 4 ++++
 1 file changed, 4 insertions(+)

diff --git a/drivers/powercap/idle_inject.c b/drivers/powercap/idle_inject.c
index 6e1a0043c411..204783dfc432 100644
--- a/drivers/powercap/idle_inject.c
+++ b/drivers/powercap/idle_inject.c
@@ -159,6 +159,7 @@ void idle_inject_set_duration(struct idle_inject_device *ii_dev,
 		WRITE_ONCE(ii_dev->idle_duration_us, idle_duration_us);
 	}
 }
+EXPORT_SYMBOL_GPL(idle_inject_set_duration);
 
 /**
  * idle_inject_get_duration - idle and run duration retrieval helper
@@ -182,6 +183,7 @@ void idle_inject_set_latency(struct idle_inject_device *ii_dev,
 {
 	WRITE_ONCE(ii_dev->latency_us, latency_us);
 }
+EXPORT_SYMBOL(idle_inject_set_latency);
 
 /**
  * idle_inject_start - start idle injections
@@ -334,6 +336,7 @@ struct idle_inject_device *idle_inject_register(struct cpumask *cpumask)
 
 	return NULL;
 }
+EXPORT_SYMBOL_GPL(idle_inject_register);
 
 /**
  * idle_inject_unregister - unregister idle injection control device
@@ -354,6 +357,7 @@ void idle_inject_unregister(struct idle_inject_device *ii_dev)
 
 	kfree(ii_dev);
 }
+EXPORT_SYMBOL_GPL(idle_inject_unregister);
 
 static struct smp_hotplug_thread idle_inject_threads = {
 	.store = &idle_inject_thread.tsk,
-- 
2.30.2


^ permalink raw reply related	[flat|nested] 5+ messages in thread

* [RFC PATCH 3/3] thermal/drivers/cpuidle_cooling: cpuidle cooling driver for non DT/ARM
  2021-08-24  5:17 [RFC PATCH 0/3] Reuse cpuidle cooling for non DT/ARM Srinivas Pandruvada
  2021-08-24  5:17 ` [RFC PATCH 1/3] thermal/drivers/cpuidle_cooling: Reorganize cpuidle cooling driver Srinivas Pandruvada
  2021-08-24  5:17 ` [RFC PATCH 2/3] powercap: idle_inject: Export symbols Srinivas Pandruvada
@ 2021-08-24  5:17 ` Srinivas Pandruvada
  2021-08-24 10:34   ` kernel test robot
  2 siblings, 1 reply; 5+ messages in thread
From: Srinivas Pandruvada @ 2021-08-24  5:17 UTC (permalink / raw)
  To: rui.zhang, daniel.lezcano, rjw, lenb, amitk; +Cc: linux-pm, Srinivas Pandruvada

This driver has same functionality as existing cpuidle_cooling driver.
This uses idle injection to cool a CPU. This driver reuses all the code
from the existing driver, except the DT specific function.

Each CPU is registered as a cooling device, with type = idle-x, where
x is the cpu number.

It registers two module parameters:
idle_duration_us : To change default idle duration
idle_latency_us : To change default latency

The meaning of these parameters is same as in the existing code. It is
described in the header of file drivers/powercap/idle_inject.c.

Signed-off-by: Srinivas Pandruvada <srinivas.pandruvada@linux.intel.com>
---
 drivers/thermal/Kconfig                   |  12 ++
 drivers/thermal/Makefile                  |   2 +
 drivers/thermal/cpuidle_cooling_generic.c | 155 ++++++++++++++++++++++
 3 files changed, 169 insertions(+)
 create mode 100644 drivers/thermal/cpuidle_cooling_generic.c

diff --git a/drivers/thermal/Kconfig b/drivers/thermal/Kconfig
index 3d669a1774d3..3efe3df75337 100644
--- a/drivers/thermal/Kconfig
+++ b/drivers/thermal/Kconfig
@@ -193,6 +193,18 @@ config CPU_IDLE_THERMAL
 	  idle cycle.
 endif
 
+config CPU_IDLE_THERMAL_GENERIC
+	tristate "CPU idle cooling device"
+	depends on !CPU_THERMAL
+	select CPU_IDLE_THERMAL_CORE
+	help
+	  This implements the CPU cooling mechanism through
+	  idle injection. This will throttle the CPU by injecting
+	  idle cycle.
+
+	  This driver can also be built as a module. If so, the module will
+          be called cpuidle_cooling_generic.
+
 config DEVFREQ_THERMAL
 	bool "Generic device cooling support"
 	depends on PM_DEVFREQ
diff --git a/drivers/thermal/Makefile b/drivers/thermal/Makefile
index 769d025beb11..c6dce523ab2b 100644
--- a/drivers/thermal/Makefile
+++ b/drivers/thermal/Makefile
@@ -26,6 +26,8 @@ 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
 
+obj-$(CONFIG_CPU_IDLE_THERMAL_GENERIC) += cpuidle_cooling_generic.o
+
 # devfreq cooling
 thermal_sys-$(CONFIG_DEVFREQ_THERMAL) += devfreq_cooling.o
 
diff --git a/drivers/thermal/cpuidle_cooling_generic.c b/drivers/thermal/cpuidle_cooling_generic.c
new file mode 100644
index 000000000000..adb33dfba2e7
--- /dev/null
+++ b/drivers/thermal/cpuidle_cooling_generic.c
@@ -0,0 +1,155 @@
+// SPDX-License-Identifier: GPL-2.0
+/*
+ * Generic cpu idle cooling driver
+ * Copyright (c) 2021, Intel Corporation.
+ * All rights reserved.
+ *
+ */
+
+#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
+
+#include <linux/cpufeature.h>
+#include <linux/cpuhotplug.h>
+#include <linux/idle_inject.h>
+#include <linux/module.h>
+#include <linux/kernel.h>
+#include <linux/slab.h>
+#include <linux/thermal.h>
+#include <linux/topology.h>
+
+#include "cpuidle_cooling_core.h"
+
+#define IDLE_DURATION   10000
+#define IDLE_LATENCY    5000
+
+static int idle_duration_us = IDLE_DURATION;
+static int idle_latency_us = IDLE_LATENCY;
+
+module_param(idle_duration_us, int, 0644);
+MODULE_PARM_DESC(idle_duration_us,
+		 "Idle duration in us.");
+
+module_param(idle_latency_us, int, 0644);
+MODULE_PARM_DESC(idle_latency_us,
+		 "Idle latency in us.");
+
+struct cpuidle_cooling {
+	struct thermal_cooling_device *cdev;
+	struct idle_inject_device *ii_dev;
+	struct cpuidle_cooling_device *idle_cdev;
+};
+static DEFINE_PER_CPU(struct cpuidle_cooling, cooling_devs);
+static cpumask_t cpuidle_cpu_mask;
+
+static int cpuidle_cooling_register(int cpu)
+{
+	struct cpuidle_cooling *cooling_dev = &per_cpu(cooling_devs, cpu);
+	struct cpuidle_cooling_device *idle_cdev;
+	struct thermal_cooling_device *cdev;
+	struct idle_inject_device *ii_dev;
+	char *name;
+	int ret;
+
+	if (cpumask_test_cpu(cpu, &cpuidle_cpu_mask))
+		return 0;
+
+	idle_cdev = kzalloc(sizeof(*idle_cdev), GFP_KERNEL);
+	if (!idle_cdev) {
+		ret = -ENOMEM;
+		goto out;
+	}
+
+	ii_dev = idle_inject_register((struct cpumask *)cpumask_of(cpu));
+	if (!ii_dev) {
+		pr_err("idle_inject_register failed for cpu:%d\n", cpu);
+		ret = -EINVAL;
+		goto out_kfree;
+	}
+
+	idle_inject_set_duration(ii_dev, TICK_USEC, idle_duration_us);
+	idle_inject_set_latency(ii_dev, idle_latency_us);
+
+	idle_cdev->ii_dev = ii_dev;
+
+	name = kasprintf(GFP_KERNEL, "idle-%d", cpu);
+	if (!name) {
+		ret = -ENOMEM;
+		goto out_unregister;
+	}
+
+	cdev = thermal_cooling_device_register(name, idle_cdev,
+					       cpuidle_cooling_get_ops());
+	if (IS_ERR(cdev)) {
+		ret = PTR_ERR(cdev);
+		goto out_kfree_name;
+	}
+
+	pr_debug("%s: Idle injection set with idle duration=%u, latency=%u\n",
+		 name, idle_duration_us, idle_latency_us);
+
+	kfree(name);
+
+	cooling_dev->cdev = cdev;
+	cooling_dev->ii_dev = ii_dev;
+	cooling_dev->idle_cdev = idle_cdev;
+	cpumask_set_cpu(cpu, &cpuidle_cpu_mask);
+
+	return 0;
+
+out_kfree_name:
+	kfree(name);
+out_unregister:
+	idle_inject_unregister(ii_dev);
+out_kfree:
+	kfree(idle_cdev);
+out:
+	return ret;
+}
+
+static void cpuidle_cooling_unregister(int cpu)
+{
+	struct cpuidle_cooling *cooling_dev = &per_cpu(cooling_devs, cpu);
+
+	thermal_cooling_device_unregister(cooling_dev->cdev);
+	idle_inject_unregister(cooling_dev->ii_dev);
+	kfree(cooling_dev->idle_cdev);
+}
+
+static int cpuidle_cooling_cpu_online(unsigned int cpu)
+{
+	cpuidle_cooling_register(cpu);
+
+	return 0;
+}
+
+static enum cpuhp_state cpuidle_cooling_hp_state __read_mostly;
+
+static int __init cpuidle_cooling_init(void)
+{
+	int ret;
+
+	ret = cpuhp_setup_state(CPUHP_AP_ONLINE_DYN,
+				"thermal/cpuidle_cooling:online",
+				cpuidle_cooling_cpu_online, NULL);
+	if (ret < 0)
+		return ret;
+
+	cpuidle_cooling_hp_state = ret;
+
+	return 0;
+}
+module_init(cpuidle_cooling_init)
+
+static void __exit cpuidle_cooling_exit(void)
+{
+	int i;
+
+	cpuhp_remove_state(cpuidle_cooling_hp_state);
+
+	for_each_cpu(i,	&cpuidle_cpu_mask) {
+		cpuidle_cooling_unregister(i);
+	}
+}
+module_exit(cpuidle_cooling_exit)
+
+MODULE_LICENSE("GPL v2");
-- 
2.30.2


^ permalink raw reply related	[flat|nested] 5+ messages in thread

* Re: [RFC PATCH 3/3] thermal/drivers/cpuidle_cooling: cpuidle cooling driver for non DT/ARM
  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
  0 siblings, 0 replies; 5+ messages in thread
From: kernel test robot @ 2021-08-24 10:34 UTC (permalink / raw)
  To: kbuild-all

[-- Attachment #1: Type: text/plain, Size: 3244 bytes --]

Hi Srinivas,

[FYI, it's a private test report for your RFC patch.]
[auto build test ERROR on pm/linux-next]
[also build test ERROR on linus/master v5.14-rc7 next-20210823]
[If your patch is applied to the wrong git tree, kindly drop us a note.
And when submitting patch, we suggest to use '--base' as documented in
https://git-scm.com/docs/git-format-patch]

url:    https://github.com/0day-ci/linux/commits/Srinivas-Pandruvada/Reuse-cpuidle-cooling-for-non-DT-ARM/20210824-131908
base:   https://git.kernel.org/pub/scm/linux/kernel/git/rafael/linux-pm.git linux-next
config: mips-randconfig-p001-20210824 (attached as .config)
compiler: mipsel-linux-gcc (GCC) 11.2.0
reproduce (this is a W=1 build):
        wget https://raw.githubusercontent.com/intel/lkp-tests/master/sbin/make.cross -O ~/bin/make.cross
        chmod +x ~/bin/make.cross
        # https://github.com/0day-ci/linux/commit/c61d8d9d2a308863b1b618e2ff1ff6187af26d96
        git remote add linux-review https://github.com/0day-ci/linux
        git fetch --no-tags linux-review Srinivas-Pandruvada/Reuse-cpuidle-cooling-for-non-DT-ARM/20210824-131908
        git checkout c61d8d9d2a308863b1b618e2ff1ff6187af26d96
        # save the attached .config to linux build tree
        mkdir build_dir
        COMPILER_INSTALL_PATH=$HOME/0day COMPILER=gcc-11.2.0 make.cross O=build_dir ARCH=mips SHELL=/bin/bash

If you fix the issue, kindly add following tag as appropriate
Reported-by: kernel test robot <lkp@intel.com>

All errors (new ones prefixed by >>):

   mipsel-linux-ld: drivers/thermal/cpuidle_cooling_core.o: in function `cpuidle_cooling_set_cur_state':
   cpuidle_cooling_core.c:(.text+0xc0): undefined reference to `idle_inject_get_duration'
>> mipsel-linux-ld: cpuidle_cooling_core.c:(.text+0xe8): undefined reference to `idle_inject_set_duration'
   mipsel-linux-ld: cpuidle_cooling_core.c:(.text+0x12c): undefined reference to `idle_inject_set_duration'
>> mipsel-linux-ld: cpuidle_cooling_core.c:(.text+0x13c): undefined reference to `idle_inject_stop'
>> mipsel-linux-ld: cpuidle_cooling_core.c:(.text+0x14c): undefined reference to `idle_inject_start'
   mipsel-linux-ld: drivers/thermal/cpuidle_cooling_generic.o: in function `cpuidle_cooling_register.isra.0':
>> cpuidle_cooling_generic.c:(.text+0x104): undefined reference to `idle_inject_register'
>> mipsel-linux-ld: cpuidle_cooling_generic.c:(.text+0x120): undefined reference to `idle_inject_set_duration'
>> mipsel-linux-ld: cpuidle_cooling_generic.c:(.text+0x130): undefined reference to `idle_inject_set_latency'
>> mipsel-linux-ld: cpuidle_cooling_generic.c:(.text+0x238): undefined reference to `idle_inject_unregister'
   mipsel-linux-ld: drivers/thermal/cpuidle_cooling_generic.o: in function `cpuidle_cooling_exit':
>> cpuidle_cooling_generic.c:(.exit.text+0xa4): undefined reference to `idle_inject_unregister'

Kconfig warnings: (for reference only)
   WARNING: unmet direct dependencies detected for CPU_IDLE_THERMAL_CORE
   Depends on THERMAL && IDLE_INJECT
   Selected by
   - CPU_IDLE_THERMAL_GENERIC && THERMAL && !CPU_THERMAL

---
0-DAY CI Kernel Test Service, Intel Corporation
https://lists.01.org/hyperkitty/list/kbuild-all(a)lists.01.org

[-- Attachment #2: config.gz --]
[-- Type: application/gzip, Size: 31442 bytes --]

^ permalink raw reply	[flat|nested] 5+ messages in thread

end of thread, other threads:[~2021-08-24 10:34 UTC | newest]

Thread overview: 5+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2021-08-24  5:17 [RFC PATCH 0/3] Reuse cpuidle cooling for non DT/ARM Srinivas Pandruvada
2021-08-24  5:17 ` [RFC PATCH 1/3] thermal/drivers/cpuidle_cooling: Reorganize cpuidle cooling driver Srinivas Pandruvada
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

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.