1 /* 2 * governor.c - governor support 3 * 4 * (C) 2006-2007 Venkatesh Pallipadi <venkatesh.pallipadi@intel.com> 5 * Shaohua Li <shaohua.li@intel.com> 6 * Adam Belay <abelay@novell.com> 7 * 8 * This code is licenced under the GPL. 9 */ 10 11 #include <linux/cpu.h> 12 #include <linux/cpuidle.h> 13 #include <linux/mutex.h> 14 #include <linux/module.h> 15 #include <linux/pm_qos.h> 16 17 #include "cpuidle.h" 18 19 char param_governor[CPUIDLE_NAME_LEN]; 20 21 LIST_HEAD(cpuidle_governors); 22 struct cpuidle_governor *cpuidle_curr_governor; 23 24 /** 25 * __cpuidle_find_governor - finds a governor of the specified name 26 * @str: the name 27 * 28 * Must be called with cpuidle_lock acquired. 29 */ 30 static struct cpuidle_governor * __cpuidle_find_governor(const char *str) 31 { 32 struct cpuidle_governor *gov; 33 34 list_for_each_entry(gov, &cpuidle_governors, governor_list) 35 if (!strncasecmp(str, gov->name, CPUIDLE_NAME_LEN)) 36 return gov; 37 38 return NULL; 39 } 40 41 /** 42 * cpuidle_switch_governor - changes the governor 43 * @gov: the new target governor 44 * Must be called with cpuidle_lock acquired. 45 */ 46 int cpuidle_switch_governor(struct cpuidle_governor *gov) 47 { 48 struct cpuidle_device *dev; 49 50 if (!gov) 51 return -EINVAL; 52 53 if (gov == cpuidle_curr_governor) 54 return 0; 55 56 cpuidle_uninstall_idle_handler(); 57 58 if (cpuidle_curr_governor) { 59 list_for_each_entry(dev, &cpuidle_detected_devices, device_list) 60 cpuidle_disable_device(dev); 61 } 62 63 cpuidle_curr_governor = gov; 64 65 if (gov) { 66 list_for_each_entry(dev, &cpuidle_detected_devices, device_list) 67 cpuidle_enable_device(dev); 68 cpuidle_install_idle_handler(); 69 printk(KERN_INFO "cpuidle: using governor %s\n", gov->name); 70 } 71 72 return 0; 73 } 74 75 /** 76 * cpuidle_register_governor - registers a governor 77 * @gov: the governor 78 */ 79 int cpuidle_register_governor(struct cpuidle_governor *gov) 80 { 81 int ret = -EEXIST; 82 83 if (!gov || !gov->select) 84 return -EINVAL; 85 86 if (cpuidle_disabled()) 87 return -ENODEV; 88 89 mutex_lock(&cpuidle_lock); 90 if (__cpuidle_find_governor(gov->name) == NULL) { 91 ret = 0; 92 if (!cpuidle_curr_governor || 93 !strncasecmp(param_governor, gov->name, CPUIDLE_NAME_LEN) || 94 (cpuidle_curr_governor->rating < gov->rating && 95 strncasecmp(param_governor, cpuidle_curr_governor->name, 96 CPUIDLE_NAME_LEN))) 97 cpuidle_switch_governor(gov); 98 } 99 mutex_unlock(&cpuidle_lock); 100 101 return ret; 102 } 103 104 /** 105 * cpuidle_governor_latency_req - Compute a latency constraint for CPU 106 * @cpu: Target CPU 107 */ 108 int cpuidle_governor_latency_req(unsigned int cpu) 109 { 110 int global_req = pm_qos_request(PM_QOS_CPU_DMA_LATENCY); 111 struct device *device = get_cpu_device(cpu); 112 int device_req = dev_pm_qos_raw_read_value(device); 113 114 return device_req < global_req ? device_req : global_req; 115 } 116