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.
11 #include <linux/mutex.h>
12 #include <linux/module.h>
13 #include <linux/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 __cpuidle_driver_init(struct cpuidle_driver *drv)
27 static int __cpuidle_register_driver(struct cpuidle_driver *drv, int cpu)
29 if (!drv || !drv->state_count)
32 if (cpuidle_disabled())
35 if (__cpuidle_get_cpu_driver(cpu))
38 __cpuidle_driver_init(drv);
40 __cpuidle_set_cpu_driver(drv, cpu);
45 static void __cpuidle_unregister_driver(struct cpuidle_driver *drv, int cpu)
47 if (drv != __cpuidle_get_cpu_driver(cpu))
50 if (!WARN_ON(drv->refcnt > 0))
51 __cpuidle_set_cpu_driver(NULL, cpu);
54 #ifdef CONFIG_CPU_IDLE_MULTIPLE_DRIVERS
56 static DEFINE_PER_CPU(struct cpuidle_driver *, cpuidle_drivers);
58 static void __cpuidle_set_cpu_driver(struct cpuidle_driver *drv, int cpu)
60 per_cpu(cpuidle_drivers, cpu) = drv;
63 static struct cpuidle_driver *__cpuidle_get_cpu_driver(int cpu)
65 return per_cpu(cpuidle_drivers, cpu);
68 static void __cpuidle_unregister_all_cpu_driver(struct cpuidle_driver *drv)
71 for_each_present_cpu(cpu)
72 __cpuidle_unregister_driver(drv, cpu);
75 static int __cpuidle_register_all_cpu_driver(struct cpuidle_driver *drv)
80 for_each_present_cpu(cpu) {
81 ret = __cpuidle_register_driver(drv, cpu);
87 for_each_present_cpu(i) {
90 __cpuidle_unregister_driver(drv, i);
97 int cpuidle_register_cpu_driver(struct cpuidle_driver *drv, int cpu)
101 spin_lock(&cpuidle_driver_lock);
102 ret = __cpuidle_register_driver(drv, cpu);
103 spin_unlock(&cpuidle_driver_lock);
108 void cpuidle_unregister_cpu_driver(struct cpuidle_driver *drv, int cpu)
110 spin_lock(&cpuidle_driver_lock);
111 __cpuidle_unregister_driver(drv, cpu);
112 spin_unlock(&cpuidle_driver_lock);
116 * cpuidle_register_driver - registers a driver
119 int cpuidle_register_driver(struct cpuidle_driver *drv)
123 spin_lock(&cpuidle_driver_lock);
124 ret = __cpuidle_register_all_cpu_driver(drv);
125 spin_unlock(&cpuidle_driver_lock);
129 EXPORT_SYMBOL_GPL(cpuidle_register_driver);
132 * cpuidle_unregister_driver - unregisters a driver
135 void cpuidle_unregister_driver(struct cpuidle_driver *drv)
137 spin_lock(&cpuidle_driver_lock);
138 __cpuidle_unregister_all_cpu_driver(drv);
139 spin_unlock(&cpuidle_driver_lock);
141 EXPORT_SYMBOL_GPL(cpuidle_unregister_driver);
145 static struct cpuidle_driver *cpuidle_curr_driver;
147 static inline void __cpuidle_set_cpu_driver(struct cpuidle_driver *drv, int cpu)
149 cpuidle_curr_driver = drv;
152 static inline struct cpuidle_driver *__cpuidle_get_cpu_driver(int cpu)
154 return cpuidle_curr_driver;
158 * cpuidle_register_driver - registers a driver
161 int cpuidle_register_driver(struct cpuidle_driver *drv)
166 spin_lock(&cpuidle_driver_lock);
167 ret = __cpuidle_register_driver(drv, cpu);
168 spin_unlock(&cpuidle_driver_lock);
173 EXPORT_SYMBOL_GPL(cpuidle_register_driver);
176 * cpuidle_unregister_driver - unregisters a driver
179 void cpuidle_unregister_driver(struct cpuidle_driver *drv)
184 spin_lock(&cpuidle_driver_lock);
185 __cpuidle_unregister_driver(drv, cpu);
186 spin_unlock(&cpuidle_driver_lock);
189 EXPORT_SYMBOL_GPL(cpuidle_unregister_driver);
193 * cpuidle_get_driver - return the current driver
195 struct cpuidle_driver *cpuidle_get_driver(void)
197 struct cpuidle_driver *drv;
201 drv = __cpuidle_get_cpu_driver(cpu);
206 EXPORT_SYMBOL_GPL(cpuidle_get_driver);
209 * cpuidle_get_cpu_driver - return the driver tied with a cpu
211 struct cpuidle_driver *cpuidle_get_cpu_driver(struct cpuidle_device *dev)
216 return __cpuidle_get_cpu_driver(dev->cpu);
218 EXPORT_SYMBOL_GPL(cpuidle_get_cpu_driver);
220 struct cpuidle_driver *cpuidle_driver_ref(void)
222 struct cpuidle_driver *drv;
224 spin_lock(&cpuidle_driver_lock);
226 drv = cpuidle_get_driver();
229 spin_unlock(&cpuidle_driver_lock);
233 void cpuidle_driver_unref(void)
235 struct cpuidle_driver *drv = cpuidle_get_driver();
237 spin_lock(&cpuidle_driver_lock);
239 if (drv && !WARN_ON(drv->refcnt <= 0))
242 spin_unlock(&cpuidle_driver_lock);