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