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