Re: [patch 1/5] drivers/cpuidle: add cpuidle-haltpoll driver

Rafael J. Wysocki
2019-06-26T08:40:16Z

On Fri, Jun 14, 2019 at 12:55 AM Marcelo Tosatti <mtosatti@redhat.com> wrote:
>
> Add a cpuidle driver that calls the architecture default_idle routine.
>
> To be used in conjunction with the haltpoll governor.
>
> Signed-off-by: Marcelo Tosatti <mtosatti@redhat.com>
>
> ---
> arch/x86/kernel/process.c | 2 -
> drivers/cpuidle/Kconfig | 9 +++++
> drivers/cpuidle/Makefile | 1
> drivers/cpuidle/cpuidle-haltpoll.c | 65 +++++++++++++++++++++++++++++++++++++
> 4 files changed, 76 insertions(+), 1 deletion(-)
>
> Index: linux-2.6.git/arch/x86/kernel/process.c
> ===================================================================
> --- linux-2.6.git.orig/arch/x86/kernel/process.c 2019-06-13 16:19:27.877064340 -0400
> +++ linux-2.6.git/arch/x86/kernel/process.c 2019-06-13 16:19:48.795544892 -0400
> @@ -580,7 +580,7 @@
> safe_halt();
> trace_cpu_idle_rcuidle(PWR_EVENT_EXIT, smp_processor_id());
> }
> -#ifdef CONFIG_APM_MODULE
> +#if defined(CONFIG_APM_MODULE) || defined(CONFIG_HALTPOLL_CPUIDLE_MODULE)
> EXPORT_SYMBOL(default_idle);
> #endif
>
> Index: linux-2.6.git/drivers/cpuidle/Kconfig
> ===================================================================
> --- linux-2.6.git.orig/drivers/cpuidle/Kconfig 2019-06-13 16:19:27.878064316 -0400
> +++ linux-2.6.git/drivers/cpuidle/Kconfig 2019-06-13 18:41:40.599912671 -0400
> @@ -51,6 +51,15 @@
> source "drivers/cpuidle/Kconfig.powerpc"
> endmenu
>
> +config HALTPOLL_CPUIDLE
> + tristate "Halt poll cpuidle driver"
> + depends on X86
> + default y
> + help
> + This option enables halt poll cpuidle driver, which allows to poll
> + before halting in the guest (more efficient than polling in the
> + host via halt_poll_ns for some scenarios).
> +
> endif
>
> config ARCH_NEEDS_CPU_IDLE_COUPLED
> Index: linux-2.6.git/drivers/cpuidle/Makefile
> ===================================================================
> --- linux-2.6.git.orig/drivers/cpuidle/Makefile 2019-06-13 16:19:27.878064316 -0400
> +++ linux-2.6.git/drivers/cpuidle/Makefile 2019-06-13 16:19:48.796544867 -0400
> @@ -7,6 +7,7 @@
> obj-$(CONFIG_ARCH_NEEDS_CPU_IDLE_COUPLED) += coupled.o
> obj-$(CONFIG_DT_IDLE_STATES) += dt_idle_states.o
> obj-$(CONFIG_ARCH_HAS_CPU_RELAX) += poll_state.o
> +obj-$(CONFIG_HALTPOLL_CPUIDLE) += cpuidle-haltpoll.o
>
> ##################################################################################
> # ARM SoC drivers
> Index: linux-2.6.git/drivers/cpuidle/cpuidle-haltpoll.c
> ===================================================================
> --- /dev/null 1970-01-01 00:00:00.000000000 +0000
> +++ linux-2.6.git/drivers/cpuidle/cpuidle-haltpoll.c 2019-06-13 18:41:39.305933413 -0400
> @@ -0,0 +1,65 @@
> +// SPDX-License-Identifier: GPL-2.0
> +/*
> + * cpuidle driver for haltpoll governor.
> + *
> + * Copyright 2019 Red Hat, Inc. and/or its affiliates.
> + *
> + * This work is licensed under the terms of the GNU GPL, version 2. See
> + * the COPYING file in the top-level directory.
> + *
> + * Authors: Marcelo Tosatti <mtosatti@redhat.com>
> + */
> +
> +#include <linux/init.h>
> +#include <linux/cpuidle.h>
> +#include <linux/module.h>
> +#include <linux/sched/idle.h>
> +
> +static int default_enter_idle(struct cpuidle_device *dev,
> + struct cpuidle_driver *drv, int index)
> +{
> + if (current_clr_polling_and_test()) {
> + local_irq_enable();
> + return index;
> + }
> + default_idle();
> + return index;
> +}
> +
> +static struct cpuidle_driver haltpoll_driver = {
> + .name = "haltpoll",
> + .owner = THIS_MODULE,
> + .states = {
> + { /* entry 0 is for polling */ },
> + {
> + .enter = default_enter_idle,
> + .exit_latency = 0,
> + .target_residency = 0,

On a second thought, I think that you need a target residency of at
least 1 (and an exit latency of at least 1) here to distinguish this
state from the polling one.

And if they both really were 0, polling wouldn't be needed at all ...

> + .power_usage = -1,
> + .name = "haltpoll idle",
> + .desc = "default architecture idle",
> + },
> + },
> + .safe_state_index = 0,
> + .state_count = 2,
> +};
> +
> +static int __init haltpoll_init(void)
> +{
> + struct cpuidle_driver *drv = &haltpoll_driver;
> +
> + cpuidle_poll_state_init(drv);
> +
> + return cpuidle_register(&haltpoll_driver, NULL);
> +}
> +
> +static void __exit haltpoll_exit(void)
> +{
> + cpuidle_unregister(&haltpoll_driver);
> +}
> +
> +module_init(haltpoll_init);
> +module_exit(haltpoll_exit);
> +MODULE_LICENSE("GPL");
> +MODULE_AUTHOR("Marcelo Tosatti <mtosatti@redhat.com>");
> +
>
>