Linux Kernel  3.7.1
 All Data Structures Namespaces Files Functions Variables Typedefs Enumerations Enumerator Macros Groups Pages
governor.c
Go to the documentation of this file.
1 /*
2  * governor.c - governor support
3  *
4  * (C) 2006-2007 Venkatesh Pallipadi <[email protected]>
5  * Shaohua Li <[email protected]>
6  * Adam Belay <[email protected]>
7  *
8  * This code is licenced under the GPL.
9  */
10 
11 #include <linux/mutex.h>
12 #include <linux/module.h>
13 #include <linux/cpuidle.h>
14 
15 #include "cpuidle.h"
16 
17 LIST_HEAD(cpuidle_governors);
19 
26 static struct cpuidle_governor * __cpuidle_find_governor(const char *str)
27 {
28  struct cpuidle_governor *gov;
29 
31  if (!strnicmp(str, gov->name, CPUIDLE_NAME_LEN))
32  return gov;
33 
34  return NULL;
35 }
36 
45 {
46  struct cpuidle_device *dev;
47 
48  if (gov == cpuidle_curr_governor)
49  return 0;
50 
52 
53  if (cpuidle_curr_governor) {
56  module_put(cpuidle_curr_governor->owner);
57  }
58 
59  cpuidle_curr_governor = gov;
60 
61  if (gov) {
62  if (!try_module_get(cpuidle_curr_governor->owner))
63  return -EINVAL;
67  printk(KERN_INFO "cpuidle: using governor %s\n", gov->name);
68  }
69 
70  return 0;
71 }
72 
78 {
79  int ret = -EEXIST;
80 
81  if (!gov || !gov->select)
82  return -EINVAL;
83 
84  if (cpuidle_disabled())
85  return -ENODEV;
86 
88  if (__cpuidle_find_governor(gov->name) == NULL) {
89  ret = 0;
91  if (!cpuidle_curr_governor ||
92  cpuidle_curr_governor->rating < gov->rating)
94  }
96 
97  return ret;
98 }
99 
105 static struct cpuidle_governor *cpuidle_replace_governor(int exclude_rating)
106 {
107  struct cpuidle_governor *gov;
108  struct cpuidle_governor *ret_gov = NULL;
109  unsigned int max_rating = 0;
110 
111  list_for_each_entry(gov, &cpuidle_governors, governor_list) {
112  if (gov->rating == exclude_rating)
113  continue;
114  if (gov->rating > max_rating) {
115  max_rating = gov->rating;
116  ret_gov = gov;
117  }
118  }
119 
120  return ret_gov;
121 }
122 
128 {
129  if (!gov)
130  return;
131 
133  if (gov == cpuidle_curr_governor) {
134  struct cpuidle_governor *new_gov;
135  new_gov = cpuidle_replace_governor(gov->rating);
136  cpuidle_switch_governor(new_gov);
137  }
138  list_del(&gov->governor_list);
140 }
141