xref: /openbmc/linux/drivers/cpuidle/cpuidle-haltpoll.c (revision a1c4423b02b2121108e3ea9580741e0f26309a48)
1fa86ee90SMarcelo Tosatti // SPDX-License-Identifier: GPL-2.0
2fa86ee90SMarcelo Tosatti /*
3fa86ee90SMarcelo Tosatti  * cpuidle driver for haltpoll governor.
4fa86ee90SMarcelo Tosatti  *
5fa86ee90SMarcelo Tosatti  * Copyright 2019 Red Hat, Inc. and/or its affiliates.
6fa86ee90SMarcelo Tosatti  *
7fa86ee90SMarcelo Tosatti  * This work is licensed under the terms of the GNU GPL, version 2.  See
8fa86ee90SMarcelo Tosatti  * the COPYING file in the top-level directory.
9fa86ee90SMarcelo Tosatti  *
10fa86ee90SMarcelo Tosatti  * Authors: Marcelo Tosatti <mtosatti@redhat.com>
11fa86ee90SMarcelo Tosatti  */
12fa86ee90SMarcelo Tosatti 
13fa86ee90SMarcelo Tosatti #include <linux/init.h>
14fa86ee90SMarcelo Tosatti #include <linux/cpuidle.h>
15fa86ee90SMarcelo Tosatti #include <linux/module.h>
16fa86ee90SMarcelo Tosatti #include <linux/sched/idle.h>
17fa86ee90SMarcelo Tosatti #include <linux/kvm_para.h>
18*a1c4423bSMarcelo Tosatti #include <linux/cpuidle_haltpoll.h>
19fa86ee90SMarcelo Tosatti 
20fa86ee90SMarcelo Tosatti static int default_enter_idle(struct cpuidle_device *dev,
21fa86ee90SMarcelo Tosatti 			      struct cpuidle_driver *drv, int index)
22fa86ee90SMarcelo Tosatti {
23fa86ee90SMarcelo Tosatti 	if (current_clr_polling_and_test()) {
24fa86ee90SMarcelo Tosatti 		local_irq_enable();
25fa86ee90SMarcelo Tosatti 		return index;
26fa86ee90SMarcelo Tosatti 	}
27fa86ee90SMarcelo Tosatti 	default_idle();
28fa86ee90SMarcelo Tosatti 	return index;
29fa86ee90SMarcelo Tosatti }
30fa86ee90SMarcelo Tosatti 
31fa86ee90SMarcelo Tosatti static struct cpuidle_driver haltpoll_driver = {
32fa86ee90SMarcelo Tosatti 	.name = "haltpoll",
33fa86ee90SMarcelo Tosatti 	.owner = THIS_MODULE,
34fa86ee90SMarcelo Tosatti 	.states = {
35fa86ee90SMarcelo Tosatti 		{ /* entry 0 is for polling */ },
36fa86ee90SMarcelo Tosatti 		{
37fa86ee90SMarcelo Tosatti 			.enter			= default_enter_idle,
38fa86ee90SMarcelo Tosatti 			.exit_latency		= 1,
39fa86ee90SMarcelo Tosatti 			.target_residency	= 1,
40fa86ee90SMarcelo Tosatti 			.power_usage		= -1,
41fa86ee90SMarcelo Tosatti 			.name			= "haltpoll idle",
42fa86ee90SMarcelo Tosatti 			.desc			= "default architecture idle",
43fa86ee90SMarcelo Tosatti 		},
44fa86ee90SMarcelo Tosatti 	},
45fa86ee90SMarcelo Tosatti 	.safe_state_index = 0,
46fa86ee90SMarcelo Tosatti 	.state_count = 2,
47fa86ee90SMarcelo Tosatti };
48fa86ee90SMarcelo Tosatti 
49fa86ee90SMarcelo Tosatti static int __init haltpoll_init(void)
50fa86ee90SMarcelo Tosatti {
51*a1c4423bSMarcelo Tosatti 	int ret;
52fa86ee90SMarcelo Tosatti 	struct cpuidle_driver *drv = &haltpoll_driver;
53fa86ee90SMarcelo Tosatti 
54fa86ee90SMarcelo Tosatti 	cpuidle_poll_state_init(drv);
55fa86ee90SMarcelo Tosatti 
56fa86ee90SMarcelo Tosatti 	if (!kvm_para_available())
57fa86ee90SMarcelo Tosatti 		return 0;
58fa86ee90SMarcelo Tosatti 
59*a1c4423bSMarcelo Tosatti 	ret = cpuidle_register(&haltpoll_driver, NULL);
60*a1c4423bSMarcelo Tosatti 	if (ret == 0)
61*a1c4423bSMarcelo Tosatti 		arch_haltpoll_enable();
62*a1c4423bSMarcelo Tosatti 
63*a1c4423bSMarcelo Tosatti 	return ret;
64fa86ee90SMarcelo Tosatti }
65fa86ee90SMarcelo Tosatti 
66fa86ee90SMarcelo Tosatti static void __exit haltpoll_exit(void)
67fa86ee90SMarcelo Tosatti {
68*a1c4423bSMarcelo Tosatti 	arch_haltpoll_disable();
69fa86ee90SMarcelo Tosatti 	cpuidle_unregister(&haltpoll_driver);
70fa86ee90SMarcelo Tosatti }
71fa86ee90SMarcelo Tosatti 
72fa86ee90SMarcelo Tosatti module_init(haltpoll_init);
73fa86ee90SMarcelo Tosatti module_exit(haltpoll_exit);
74fa86ee90SMarcelo Tosatti MODULE_LICENSE("GPL");
75fa86ee90SMarcelo Tosatti MODULE_AUTHOR("Marcelo Tosatti <mtosatti@redhat.com>");
76