From: Mete Durlu <meted@linux.ibm.com>
To: Heiko Carstens <hca@linux.ibm.com>,
Vasily Gorbik <gor@linux.ibm.com>,
Alexander Gordeev <agordeev@linux.ibm.com>,
Sven Schnelle <svens@linux.ibm.com>,
Anna-Maria Behnsen <anna-maria@linutronix.de>,
Frederic Weisbecker <frederic@kernel.org>,
Ingo Molnar <mingo@kernel.org>, Thomas Gleixner <tglx@kernel.org>,
"Rafael J. Wysocki" <rafael@kernel.org>,
Daniel Lezcano <daniel.lezcano@kernel.org>,
Christian Loehle <christian.loehle@arm.com>
Cc: Mete Durlu <meted@linux.ibm.com>,
Christian Borntraeger <borntraeger@linux.ibm.com>,
Ilya Leoshkevich <iii@linux.ibm.com>,
linux-s390@vger.kernel.org, linux-kernel@vger.kernel.org,
linux-pm@vger.kernel.org
Subject: [PATCH v3 4/5] s390/idle: Introduce cpuidle for s390
Date: Thu, 18 Jun 2026 14:00:18 +0200 [thread overview]
Message-ID: <20260618-idledriver-v3-4-684061eecbcb@linux.ibm.com> (raw)
In-Reply-To: <20260618-idledriver-v3-0-684061eecbcb@linux.ibm.com>
Introduce generic cpuidle driver on s390. Use a two stage approach to
handle idle scenarios and use idle governor for idle stage selection.
Two stages are, from shallow to deep, idle polling and enabled wait.
Suggested-by: Christian Borntraeger <borntraeger@linux.ibm.com>
Suggested-by: Heiko Carstens <hca@linux.ibm.com>
Signed-off-by: Mete Durlu <meted@linux.ibm.com>
---
MAINTAINERS | 8 +++
arch/s390/Kconfig | 5 ++
drivers/cpuidle/Kconfig | 5 ++
drivers/cpuidle/Kconfig.s390 | 11 ++++
drivers/cpuidle/Makefile | 4 ++
drivers/cpuidle/cpuidle-s390.c | 115 +++++++++++++++++++++++++++++++++++++++++
6 files changed, 148 insertions(+)
diff --git a/MAINTAINERS b/MAINTAINERS
index e035a3be797c..127e32c5fb4e 100644
--- a/MAINTAINERS
+++ b/MAINTAINERS
@@ -6766,6 +6766,13 @@ L: linux-riscv@lists.infradead.org
S: Maintained
F: drivers/cpuidle/cpuidle-riscv-sbi.c
+CPUIDLE DRIVER - S390
+M: Mete Durlu <meted@linux.ibm.com>
+L: linux-pm@vger.kernel.org
+L: linux-s390@vger.kernel.org
+S: Maintained
+F: drivers/cpuidle/cpuidle-s390.c
+
CPUMASK API [RUST]
M: Viresh Kumar <viresh.kumar@linaro.org>
R: Yury Norov <yury.norov@gmail.com>
@@ -23497,6 +23504,7 @@ T: git git://git.kernel.org/pub/scm/linux/kernel/git/s390/linux.git
F: Documentation/driver-api/s390-drivers.rst
F: Documentation/arch/s390/
F: arch/s390/
+F: drivers/cpuidle/cpuidle-s390.c
F: drivers/s390/
F: drivers/watchdog/diag288_wdt.c
diff --git a/arch/s390/Kconfig b/arch/s390/Kconfig
index ecbcbb781e40..8548f5b6b247 100644
--- a/arch/s390/Kconfig
+++ b/arch/s390/Kconfig
@@ -20,6 +20,9 @@ config ARCH_HAS_ILOG2_U64
config ARCH_PROC_KCORE_TEXT
def_bool y
+config ARCH_HAS_CPU_RELAX
+ def_bool y
+
config GENERIC_HWEIGHT
def_bool !HAVE_MARCH_Z196_FEATURES
@@ -708,6 +711,8 @@ config KERNEL_IMAGE_BASE
endmenu
+source "drivers/cpuidle/Kconfig"
+
menu "Memory setup"
config ARCH_SPARSEMEM_ENABLE
diff --git a/drivers/cpuidle/Kconfig b/drivers/cpuidle/Kconfig
index d6d8386d3f02..00e2562041fd 100644
--- a/drivers/cpuidle/Kconfig
+++ b/drivers/cpuidle/Kconfig
@@ -71,6 +71,11 @@ depends on RISCV
source "drivers/cpuidle/Kconfig.riscv"
endmenu
+menu "S390 CPU Idle Drivers"
+depends on S390
+source "drivers/cpuidle/Kconfig.s390"
+endmenu
+
config HALTPOLL_CPUIDLE
tristate "Halt poll cpuidle driver"
depends on X86 && KVM_GUEST
diff --git a/drivers/cpuidle/Kconfig.s390 b/drivers/cpuidle/Kconfig.s390
new file mode 100644
index 000000000000..0b170d9a190b
--- /dev/null
+++ b/drivers/cpuidle/Kconfig.s390
@@ -0,0 +1,11 @@
+# SPDX-License-Identifier: GPL-2.0-only
+#
+# S390 CPU Idle drivers
+#
+
+config S390_CPUIDLE
+ bool "S390 CPU idle driver"
+ default y
+ help
+ Select this option to enable processor idle state management
+ through cpuidle subsystem.
diff --git a/drivers/cpuidle/Makefile b/drivers/cpuidle/Makefile
index 1de9e92c5b0f..88cbc2a7aea8 100644
--- a/drivers/cpuidle/Makefile
+++ b/drivers/cpuidle/Makefile
@@ -42,3 +42,7 @@ obj-$(CONFIG_POWERNV_CPUIDLE) += cpuidle-powernv.o
###############################################################################
# RISC-V drivers
obj-$(CONFIG_RISCV_SBI_CPUIDLE) += cpuidle-riscv-sbi.o
+
+###############################################################################
+# S390 drivers
+obj-$(CONFIG_S390_CPUIDLE) += cpuidle-s390.o
diff --git a/drivers/cpuidle/cpuidle-s390.c b/drivers/cpuidle/cpuidle-s390.c
new file mode 100644
index 000000000000..1d02a77ebce0
--- /dev/null
+++ b/drivers/cpuidle/cpuidle-s390.c
@@ -0,0 +1,115 @@
+// SPDX-License-Identifier: GPL-2.0-only
+/*
+ * s390 generic CPU idle driver.
+ *
+ * Copyright IBM Corp. 2026
+ */
+
+#define pr_fmt(fmt) "CPUidle s390: " fmt
+
+#include <linux/init.h>
+#include <linux/cpuidle.h>
+#include <linux/cpu.h>
+#include <linux/sched/clock.h>
+
+static __cpuidle int s390_enter_idle(struct cpuidle_device *dev,
+ struct cpuidle_driver *drv,
+ int index)
+{
+ arch_cpu_idle();
+ return index;
+}
+
+static struct cpuidle_driver s390_cpuidle_driver = {
+ .cpumask = (struct cpumask *)cpu_present_mask,
+ .name = "s390-idle",
+ .states = {
+ { /* entry 0 is for polling */},
+ {
+ .enter = s390_enter_idle,
+ .name = "IDLE",
+ .desc = "ENABLED WAIT",
+ },
+ },
+ .safe_state_index = 0,
+ .state_count = 2,
+};
+
+static int s390_cpuidle_cpu_online(unsigned int cpu)
+{
+ struct cpuidle_device *dev = &per_cpu(cpuidle_dev, cpu);
+ int rc;
+
+ if (dev->registered) {
+ cpuidle_pause_and_lock();
+ rc = cpuidle_enable_device(dev);
+ cpuidle_resume_and_unlock();
+ if (rc)
+ pr_err("Failed to enable cpuidle device on cpu %u\n", cpu);
+ } else {
+ dev->cpu = cpu;
+ rc = cpuidle_register_device(dev);
+ if (rc)
+ pr_err("Failed to register cpuidle driver on cpu %u\n", cpu);
+ }
+ return rc;
+}
+
+static int s390_cpuidle_cpu_dead(unsigned int cpu)
+{
+ struct cpuidle_device *dev = &per_cpu(cpuidle_dev, cpu);
+
+ if (!dev->registered)
+ return 0;
+ cpuidle_pause_and_lock();
+ cpuidle_disable_device(dev);
+ cpuidle_resume_and_unlock();
+ return 0;
+}
+
+/*
+ * The target_residency and exit_latency values are benchmark-derived estimates
+ * that remain non-deterministic due to s390's virtualized architecture.
+ *
+ * Configuration strategy:
+ * - Poll idle state: Values derived from the next enabled idle state (EW)
+ * - Enabled Wait state: Values selected based on idle behavior and empirical
+ * measurement data
+ *
+ * Goal is to improve responsiveness for workloads with frequent sleep/wakeup
+ * cycles while minimizing any side effects.
+ */
+static void __init s390_cpuidle_ew_tune(void)
+{
+ struct cpuidle_state *state = &s390_cpuidle_driver.states[1];
+
+ if (machine_is_lpar()) {
+ state->target_residency = 5;
+ state->exit_latency = 5;
+ } else {
+ state->target_residency = 1;
+ state->exit_latency = 1;
+ }
+}
+
+static int __init s390_cpuidle_init(void)
+{
+ int rc;
+
+ s390_cpuidle_ew_tune();
+ cpuidle_poll_state_init(&s390_cpuidle_driver);
+ rc = cpuidle_register(&s390_cpuidle_driver, NULL);
+ if (rc)
+ return rc;
+ rc = cpuhp_setup_state_nocalls(CPUHP_AP_ONLINE_DYN,
+ "cpuidle/s390:online",
+ s390_cpuidle_cpu_online,
+ s390_cpuidle_cpu_dead);
+ if (rc < 0) {
+ cpuidle_unregister(&s390_cpuidle_driver);
+ pr_err("Failed to allocate hotplug state: cpuidle/s390:online\n");
+ return rc;
+ }
+ return 0;
+}
+device_initcall(s390_cpuidle_init);
--
2.54.0
next prev parent reply other threads:[~2026-06-18 12:01 UTC|newest]
Thread overview: 14+ messages / expand[flat|nested] mbox.gz Atom feed top
2026-06-18 12:00 [PATCH v3 0/5] s390/idle: CPU idle driver Mete Durlu
2026-06-18 12:00 ` [PATCH v3 1/5] s390/tick: Remove CIF_NOHZ_DELAY flag Mete Durlu
2026-06-18 12:00 ` [PATCH v3 2/5] tick: Remove arch_needs_cpu Mete Durlu
2026-06-18 12:00 ` [PATCH v3 3/5] s390: Enable TIF_POLLING_NRFLAG Mete Durlu
2026-06-18 12:00 ` Mete Durlu [this message]
2026-06-18 14:41 ` [PATCH v3 4/5] s390/idle: Introduce cpuidle for s390 Christian Loehle
2026-06-18 14:47 ` Mete Durlu
2026-06-18 16:06 ` Christian Loehle
2026-06-19 8:01 ` Heiko Carstens
2026-06-18 12:00 ` [PATCH v3 5/5] s390/configs: Enable cpuidle driver on s390 Mete Durlu
2026-06-18 13:18 ` Christian Borntraeger
2026-06-19 9:29 ` [PATCH v3 0/5] s390/idle: CPU idle driver Alexander Gordeev
2026-06-19 10:38 ` Christian Loehle
2026-06-19 11:34 ` Alexander Gordeev
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=20260618-idledriver-v3-4-684061eecbcb@linux.ibm.com \
--to=meted@linux.ibm.com \
--cc=agordeev@linux.ibm.com \
--cc=anna-maria@linutronix.de \
--cc=borntraeger@linux.ibm.com \
--cc=christian.loehle@arm.com \
--cc=daniel.lezcano@kernel.org \
--cc=frederic@kernel.org \
--cc=gor@linux.ibm.com \
--cc=hca@linux.ibm.com \
--cc=iii@linux.ibm.com \
--cc=linux-kernel@vger.kernel.org \
--cc=linux-pm@vger.kernel.org \
--cc=linux-s390@vger.kernel.org \
--cc=mingo@kernel.org \
--cc=rafael@kernel.org \
--cc=svens@linux.ibm.com \
--cc=tglx@kernel.org \
/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.