// 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/cpu.h>
#include <linux/cpuidle.h>
#include <linux/module.h>
#include <linux/sched/idle.h>
#include <linux/kvm_para.h>
#include <linux/cpuidle_haltpoll.h>

static bool force __read_mostly;
module_param(force, bool, 0444);
MODULE_PARM_DESC(force, "Load unconditionally");

static struct cpuidle_device __percpu *haltpoll_cpuidle_devices;
static enum cpuhp_state haltpoll_hp_state;

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;
	}
	arch_cpu_idle();
	return index;
}

static struct cpuidle_driver haltpoll_driver = {
	.name = "haltpoll",
	.governor = "haltpoll",
	.states = {
		{ /* entry 0 is for polling */ },
		{
			.enter			= default_enter_idle,
			.exit_latency		= 1,
			.target_residency	= 1,
			.power_usage		= -1,
			.name			= "haltpoll idle",
			.desc			= "default architecture idle",
		},
	},
	.safe_state_index = 0,
	.state_count = 2,
};

static int haltpoll_cpu_online(unsigned int cpu)
{
	struct cpuidle_device *dev;

	dev = per_cpu_ptr(haltpoll_cpuidle_devices, cpu);
	if (!dev->registered) {
		dev->cpu = cpu;
		if (cpuidle_register_device(dev)) {
			pr_notice("cpuidle_register_device %d failed!\n", cpu);
			return -EIO;
		}
		arch_haltpoll_enable(cpu);
	}

	return 0;
}

static int haltpoll_cpu_offline(unsigned int cpu)
{
	struct cpuidle_device *dev;

	dev = per_cpu_ptr(haltpoll_cpuidle_devices, cpu);
	if (dev->registered) {
		arch_haltpoll_disable(cpu);
		cpuidle_unregister_device(dev);
	}

	return 0;
}

static void haltpoll_uninit(void)
{
	if (haltpoll_hp_state)
		cpuhp_remove_state(haltpoll_hp_state);
	cpuidle_unregister_driver(&haltpoll_driver);

	free_percpu(haltpoll_cpuidle_devices);
	haltpoll_cpuidle_devices = NULL;
}

static bool haltpoll_want(void)
{
	return kvm_para_has_hint(KVM_HINTS_REALTIME) || force;
}

static int __init haltpoll_init(void)
{
	int ret;
	struct cpuidle_driver *drv = &haltpoll_driver;

	/* Do not load haltpoll if idle= is passed */
	if (boot_option_idle_override != IDLE_NO_OVERRIDE)
		return -ENODEV;

	if (!kvm_para_available() || !haltpoll_want())
		return -ENODEV;

	cpuidle_poll_state_init(drv);

	ret = cpuidle_register_driver(drv);
	if (ret < 0)
		return ret;

	haltpoll_cpuidle_devices = alloc_percpu(struct cpuidle_device);
	if (haltpoll_cpuidle_devices == NULL) {
		cpuidle_unregister_driver(drv);
		return -ENOMEM;
	}

	ret = cpuhp_setup_state(CPUHP_AP_ONLINE_DYN, "cpuidle/haltpoll:online",
				haltpoll_cpu_online, haltpoll_cpu_offline);
	if (ret < 0) {
		haltpoll_uninit();
	} else {
		haltpoll_hp_state = ret;
		ret = 0;
	}

	return ret;
}

static void __exit haltpoll_exit(void)
{
	haltpoll_uninit();
}

module_init(haltpoll_init);
module_exit(haltpoll_exit);
MODULE_LICENSE("GPL");
MODULE_AUTHOR("Marcelo Tosatti <mtosatti@redhat.com>");
