tuntap: switch to use rtnl_dereference()
[linux-2.6/linux-acpi-2.6/ibm-acpi-2.6.git] / drivers / cpuidle / driver.c
blobc2b281afe0ed03ce13a3a3122d96084319a93635
1 /*
2 * driver.c - driver support
4 * (C) 2006-2007 Venkatesh Pallipadi <venkatesh.pallipadi@intel.com>
5 * Shaohua Li <shaohua.li@intel.com>
6 * Adam Belay <abelay@novell.com>
8 * This code is licenced under the GPL.
9 */
11 #include <linux/mutex.h>
12 #include <linux/module.h>
13 #include <linux/cpuidle.h>
15 #include "cpuidle.h"
17 DEFINE_SPINLOCK(cpuidle_driver_lock);
19 static void __cpuidle_set_cpu_driver(struct cpuidle_driver *drv, int cpu);
20 static struct cpuidle_driver * __cpuidle_get_cpu_driver(int cpu);
22 static void set_power_states(struct cpuidle_driver *drv)
24 int i;
27 * cpuidle driver should set the drv->power_specified bit
28 * before registering if the driver provides
29 * power_usage numbers.
31 * If power_specified is not set,
32 * we fill in power_usage with decreasing values as the
33 * cpuidle code has an implicit assumption that state Cn
34 * uses less power than C(n-1).
36 * With CONFIG_ARCH_HAS_CPU_RELAX, C0 is already assigned
37 * an power value of -1. So we use -2, -3, etc, for other
38 * c-states.
40 for (i = CPUIDLE_DRIVER_STATE_START; i < drv->state_count; i++)
41 drv->states[i].power_usage = -1 - i;
44 static void __cpuidle_driver_init(struct cpuidle_driver *drv)
46 drv->refcnt = 0;
48 if (!drv->power_specified)
49 set_power_states(drv);
52 static int __cpuidle_register_driver(struct cpuidle_driver *drv, int cpu)
54 if (!drv || !drv->state_count)
55 return -EINVAL;
57 if (cpuidle_disabled())
58 return -ENODEV;
60 if (__cpuidle_get_cpu_driver(cpu))
61 return -EBUSY;
63 __cpuidle_driver_init(drv);
65 __cpuidle_set_cpu_driver(drv, cpu);
67 return 0;
70 static void __cpuidle_unregister_driver(struct cpuidle_driver *drv, int cpu)
72 if (drv != __cpuidle_get_cpu_driver(cpu))
73 return;
75 if (!WARN_ON(drv->refcnt > 0))
76 __cpuidle_set_cpu_driver(NULL, cpu);
79 #ifdef CONFIG_CPU_IDLE_MULTIPLE_DRIVERS
81 static DEFINE_PER_CPU(struct cpuidle_driver *, cpuidle_drivers);
83 static void __cpuidle_set_cpu_driver(struct cpuidle_driver *drv, int cpu)
85 per_cpu(cpuidle_drivers, cpu) = drv;
88 static struct cpuidle_driver *__cpuidle_get_cpu_driver(int cpu)
90 return per_cpu(cpuidle_drivers, cpu);
93 static void __cpuidle_unregister_all_cpu_driver(struct cpuidle_driver *drv)
95 int cpu;
96 for_each_present_cpu(cpu)
97 __cpuidle_unregister_driver(drv, cpu);
100 static int __cpuidle_register_all_cpu_driver(struct cpuidle_driver *drv)
102 int ret = 0;
103 int i, cpu;
105 for_each_present_cpu(cpu) {
106 ret = __cpuidle_register_driver(drv, cpu);
107 if (ret)
108 break;
111 if (ret)
112 for_each_present_cpu(i) {
113 if (i == cpu)
114 break;
115 __cpuidle_unregister_driver(drv, i);
119 return ret;
122 int cpuidle_register_cpu_driver(struct cpuidle_driver *drv, int cpu)
124 int ret;
126 spin_lock(&cpuidle_driver_lock);
127 ret = __cpuidle_register_driver(drv, cpu);
128 spin_unlock(&cpuidle_driver_lock);
130 return ret;
133 void cpuidle_unregister_cpu_driver(struct cpuidle_driver *drv, int cpu)
135 spin_lock(&cpuidle_driver_lock);
136 __cpuidle_unregister_driver(drv, cpu);
137 spin_unlock(&cpuidle_driver_lock);
141 * cpuidle_register_driver - registers a driver
142 * @drv: the driver
144 int cpuidle_register_driver(struct cpuidle_driver *drv)
146 int ret;
148 spin_lock(&cpuidle_driver_lock);
149 ret = __cpuidle_register_all_cpu_driver(drv);
150 spin_unlock(&cpuidle_driver_lock);
152 return ret;
154 EXPORT_SYMBOL_GPL(cpuidle_register_driver);
157 * cpuidle_unregister_driver - unregisters a driver
158 * @drv: the driver
160 void cpuidle_unregister_driver(struct cpuidle_driver *drv)
162 spin_lock(&cpuidle_driver_lock);
163 __cpuidle_unregister_all_cpu_driver(drv);
164 spin_unlock(&cpuidle_driver_lock);
166 EXPORT_SYMBOL_GPL(cpuidle_unregister_driver);
168 #else
170 static struct cpuidle_driver *cpuidle_curr_driver;
172 static inline void __cpuidle_set_cpu_driver(struct cpuidle_driver *drv, int cpu)
174 cpuidle_curr_driver = drv;
177 static inline struct cpuidle_driver *__cpuidle_get_cpu_driver(int cpu)
179 return cpuidle_curr_driver;
183 * cpuidle_register_driver - registers a driver
184 * @drv: the driver
186 int cpuidle_register_driver(struct cpuidle_driver *drv)
188 int ret, cpu;
190 cpu = get_cpu();
191 spin_lock(&cpuidle_driver_lock);
192 ret = __cpuidle_register_driver(drv, cpu);
193 spin_unlock(&cpuidle_driver_lock);
194 put_cpu();
196 return ret;
198 EXPORT_SYMBOL_GPL(cpuidle_register_driver);
201 * cpuidle_unregister_driver - unregisters a driver
202 * @drv: the driver
204 void cpuidle_unregister_driver(struct cpuidle_driver *drv)
206 int cpu;
208 cpu = get_cpu();
209 spin_lock(&cpuidle_driver_lock);
210 __cpuidle_unregister_driver(drv, cpu);
211 spin_unlock(&cpuidle_driver_lock);
212 put_cpu();
214 EXPORT_SYMBOL_GPL(cpuidle_unregister_driver);
215 #endif
218 * cpuidle_get_driver - return the current driver
220 struct cpuidle_driver *cpuidle_get_driver(void)
222 struct cpuidle_driver *drv;
223 int cpu;
225 cpu = get_cpu();
226 drv = __cpuidle_get_cpu_driver(cpu);
227 put_cpu();
229 return drv;
231 EXPORT_SYMBOL_GPL(cpuidle_get_driver);
234 * cpuidle_get_cpu_driver - return the driver tied with a cpu
236 struct cpuidle_driver *cpuidle_get_cpu_driver(struct cpuidle_device *dev)
238 if (!dev)
239 return NULL;
241 return __cpuidle_get_cpu_driver(dev->cpu);
243 EXPORT_SYMBOL_GPL(cpuidle_get_cpu_driver);
245 struct cpuidle_driver *cpuidle_driver_ref(void)
247 struct cpuidle_driver *drv;
249 spin_lock(&cpuidle_driver_lock);
251 drv = cpuidle_get_driver();
252 drv->refcnt++;
254 spin_unlock(&cpuidle_driver_lock);
255 return drv;
258 void cpuidle_driver_unref(void)
260 struct cpuidle_driver *drv = cpuidle_get_driver();
262 spin_lock(&cpuidle_driver_lock);
264 if (drv && !WARN_ON(drv->refcnt <= 0))
265 drv->refcnt--;
267 spin_unlock(&cpuidle_driver_lock);