0001
0002
0003
0004
0005
0006
0007
0008
0009
0010
0011 #include <linux/cpu.h>
0012 #include <linux/cpuidle.h>
0013 #include <linux/mutex.h>
0014 #include <linux/module.h>
0015 #include <linux/pm_qos.h>
0016
0017 #include "cpuidle.h"
0018
0019 char param_governor[CPUIDLE_NAME_LEN];
0020
0021 LIST_HEAD(cpuidle_governors);
0022 struct cpuidle_governor *cpuidle_curr_governor;
0023 struct cpuidle_governor *cpuidle_prev_governor;
0024
0025
0026
0027
0028
0029
0030
0031 struct cpuidle_governor *cpuidle_find_governor(const char *str)
0032 {
0033 struct cpuidle_governor *gov;
0034
0035 list_for_each_entry(gov, &cpuidle_governors, governor_list)
0036 if (!strncasecmp(str, gov->name, CPUIDLE_NAME_LEN))
0037 return gov;
0038
0039 return NULL;
0040 }
0041
0042
0043
0044
0045
0046
0047 int cpuidle_switch_governor(struct cpuidle_governor *gov)
0048 {
0049 struct cpuidle_device *dev;
0050
0051 if (!gov)
0052 return -EINVAL;
0053
0054 if (gov == cpuidle_curr_governor)
0055 return 0;
0056
0057 cpuidle_uninstall_idle_handler();
0058
0059 if (cpuidle_curr_governor) {
0060 list_for_each_entry(dev, &cpuidle_detected_devices, device_list)
0061 cpuidle_disable_device(dev);
0062 }
0063
0064 cpuidle_curr_governor = gov;
0065
0066 if (gov) {
0067 list_for_each_entry(dev, &cpuidle_detected_devices, device_list)
0068 cpuidle_enable_device(dev);
0069 cpuidle_install_idle_handler();
0070 printk(KERN_INFO "cpuidle: using governor %s\n", gov->name);
0071 }
0072
0073 return 0;
0074 }
0075
0076
0077
0078
0079
0080 int cpuidle_register_governor(struct cpuidle_governor *gov)
0081 {
0082 int ret = -EEXIST;
0083
0084 if (!gov || !gov->select)
0085 return -EINVAL;
0086
0087 if (cpuidle_disabled())
0088 return -ENODEV;
0089
0090 mutex_lock(&cpuidle_lock);
0091 if (cpuidle_find_governor(gov->name) == NULL) {
0092 ret = 0;
0093 list_add_tail(&gov->governor_list, &cpuidle_governors);
0094 if (!cpuidle_curr_governor ||
0095 !strncasecmp(param_governor, gov->name, CPUIDLE_NAME_LEN) ||
0096 (cpuidle_curr_governor->rating < gov->rating &&
0097 strncasecmp(param_governor, cpuidle_curr_governor->name,
0098 CPUIDLE_NAME_LEN)))
0099 cpuidle_switch_governor(gov);
0100 }
0101 mutex_unlock(&cpuidle_lock);
0102
0103 return ret;
0104 }
0105
0106
0107
0108
0109
0110 s64 cpuidle_governor_latency_req(unsigned int cpu)
0111 {
0112 struct device *device = get_cpu_device(cpu);
0113 int device_req = dev_pm_qos_raw_resume_latency(device);
0114 int global_req = cpu_latency_qos_limit();
0115
0116 if (device_req > global_req)
0117 device_req = global_req;
0118
0119 return (s64)device_req * NSEC_PER_USEC;
0120 }