usbnet: mcs7830: apply usbnet_link_change
[linux-2.6.git] / drivers / cpuidle / driver.c
blob422c7b69ba7c50e728fa3af5af346a85a553af8f
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 __cpuidle_driver_init(struct cpuidle_driver *drv)
24 drv->refcnt = 0;
27 static int __cpuidle_register_driver(struct cpuidle_driver *drv, int cpu)
29 if (!drv || !drv->state_count)
30 return -EINVAL;
32 if (cpuidle_disabled())
33 return -ENODEV;
35 if (__cpuidle_get_cpu_driver(cpu))
36 return -EBUSY;
38 __cpuidle_driver_init(drv);
40 __cpuidle_set_cpu_driver(drv, cpu);
42 return 0;
45 static void __cpuidle_unregister_driver(struct cpuidle_driver *drv, int cpu)
47 if (drv != __cpuidle_get_cpu_driver(cpu))
48 return;
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)
70 int cpu;
71 for_each_present_cpu(cpu)
72 __cpuidle_unregister_driver(drv, cpu);
75 static int __cpuidle_register_all_cpu_driver(struct cpuidle_driver *drv)
77 int ret = 0;
78 int i, cpu;
80 for_each_present_cpu(cpu) {
81 ret = __cpuidle_register_driver(drv, cpu);
82 if (ret)
83 break;
86 if (ret)
87 for_each_present_cpu(i) {
88 if (i == cpu)
89 break;
90 __cpuidle_unregister_driver(drv, i);
94 return ret;
97 int cpuidle_register_cpu_driver(struct cpuidle_driver *drv, int cpu)
99 int ret;
101 spin_lock(&cpuidle_driver_lock);
102 ret = __cpuidle_register_driver(drv, cpu);
103 spin_unlock(&cpuidle_driver_lock);
105 return ret;
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
117 * @drv: the driver
119 int cpuidle_register_driver(struct cpuidle_driver *drv)
121 int ret;
123 spin_lock(&cpuidle_driver_lock);
124 ret = __cpuidle_register_all_cpu_driver(drv);
125 spin_unlock(&cpuidle_driver_lock);
127 return ret;
129 EXPORT_SYMBOL_GPL(cpuidle_register_driver);
132 * cpuidle_unregister_driver - unregisters a driver
133 * @drv: the 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);
143 #else
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
159 * @drv: the driver
161 int cpuidle_register_driver(struct cpuidle_driver *drv)
163 int ret, cpu;
165 cpu = get_cpu();
166 spin_lock(&cpuidle_driver_lock);
167 ret = __cpuidle_register_driver(drv, cpu);
168 spin_unlock(&cpuidle_driver_lock);
169 put_cpu();
171 return ret;
173 EXPORT_SYMBOL_GPL(cpuidle_register_driver);
176 * cpuidle_unregister_driver - unregisters a driver
177 * @drv: the driver
179 void cpuidle_unregister_driver(struct cpuidle_driver *drv)
181 int cpu;
183 cpu = get_cpu();
184 spin_lock(&cpuidle_driver_lock);
185 __cpuidle_unregister_driver(drv, cpu);
186 spin_unlock(&cpuidle_driver_lock);
187 put_cpu();
189 EXPORT_SYMBOL_GPL(cpuidle_unregister_driver);
190 #endif
193 * cpuidle_get_driver - return the current driver
195 struct cpuidle_driver *cpuidle_get_driver(void)
197 struct cpuidle_driver *drv;
198 int cpu;
200 cpu = get_cpu();
201 drv = __cpuidle_get_cpu_driver(cpu);
202 put_cpu();
204 return drv;
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)
213 if (!dev)
214 return NULL;
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();
227 drv->refcnt++;
229 spin_unlock(&cpuidle_driver_lock);
230 return drv;
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))
240 drv->refcnt--;
242 spin_unlock(&cpuidle_driver_lock);