* [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.