aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--drivers/cpuidle/cpuidle-pseries.c78
1 files changed, 11 insertions, 67 deletions
diff --git a/drivers/cpuidle/cpuidle-pseries.c b/drivers/cpuidle/cpuidle-pseries.c
index 21154782402a..32d86bc5d3f7 100644
--- a/drivers/cpuidle/cpuidle-pseries.c
+++ b/drivers/cpuidle/cpuidle-pseries.c
@@ -27,7 +27,6 @@ struct cpuidle_driver pseries_idle_driver = {
27#define MAX_IDLE_STATE_COUNT 2 27#define MAX_IDLE_STATE_COUNT 2
28 28
29static int max_idle_state = MAX_IDLE_STATE_COUNT - 1; 29static int max_idle_state = MAX_IDLE_STATE_COUNT - 1;
30static struct cpuidle_device __percpu *pseries_cpuidle_devices;
31static struct cpuidle_state *cpuidle_state_table; 30static struct cpuidle_state *cpuidle_state_table;
32 31
33static inline void idle_loop_prolog(unsigned long *in_purr) 32static inline void idle_loop_prolog(unsigned long *in_purr)
@@ -55,13 +54,12 @@ static int snooze_loop(struct cpuidle_device *dev,
55 int index) 54 int index)
56{ 55{
57 unsigned long in_purr; 56 unsigned long in_purr;
58 int cpu = dev->cpu;
59 57
60 idle_loop_prolog(&in_purr); 58 idle_loop_prolog(&in_purr);
61 local_irq_enable(); 59 local_irq_enable();
62 set_thread_flag(TIF_POLLING_NRFLAG); 60 set_thread_flag(TIF_POLLING_NRFLAG);
63 61
64 while ((!need_resched()) && cpu_online(cpu)) { 62 while (!need_resched()) {
65 HMT_low(); 63 HMT_low();
66 HMT_very_low(); 64 HMT_very_low();
67 } 65 }
@@ -188,7 +186,7 @@ static int pseries_cpuidle_add_cpu_notifier(struct notifier_block *n,
188{ 186{
189 int hotcpu = (unsigned long)hcpu; 187 int hotcpu = (unsigned long)hcpu;
190 struct cpuidle_device *dev = 188 struct cpuidle_device *dev =
191 per_cpu_ptr(pseries_cpuidle_devices, hotcpu); 189 per_cpu(cpuidle_devices, hotcpu);
192 190
193 if (dev && cpuidle_get_driver()) { 191 if (dev && cpuidle_get_driver()) {
194 switch (action) { 192 switch (action) {
@@ -245,50 +243,6 @@ static int pseries_cpuidle_driver_init(void)
245 return 0; 243 return 0;
246} 244}
247 245
248/* pseries_idle_devices_uninit(void)
249 * unregister cpuidle devices and de-allocate memory
250 */
251static void pseries_idle_devices_uninit(void)
252{
253 int i;
254 struct cpuidle_device *dev;
255
256 for_each_possible_cpu(i) {
257 dev = per_cpu_ptr(pseries_cpuidle_devices, i);
258 cpuidle_unregister_device(dev);
259 }
260
261 free_percpu(pseries_cpuidle_devices);
262 return;
263}
264
265/* pseries_idle_devices_init()
266 * allocate, initialize and register cpuidle device
267 */
268static int pseries_idle_devices_init(void)
269{
270 int i;
271 struct cpuidle_driver *drv = &pseries_idle_driver;
272 struct cpuidle_device *dev;
273
274 pseries_cpuidle_devices = alloc_percpu(struct cpuidle_device);
275 if (pseries_cpuidle_devices == NULL)
276 return -ENOMEM;
277
278 for_each_possible_cpu(i) {
279 dev = per_cpu_ptr(pseries_cpuidle_devices, i);
280 dev->state_count = drv->state_count;
281 dev->cpu = i;
282 if (cpuidle_register_device(dev)) {
283 printk(KERN_DEBUG \
284 "cpuidle_register_device %d failed!\n", i);
285 return -EIO;
286 }
287 }
288
289 return 0;
290}
291
292/* 246/*
293 * pseries_idle_probe() 247 * pseries_idle_probe()
294 * Choose state table for shared versus dedicated partition 248 * Choose state table for shared versus dedicated partition
@@ -296,9 +250,6 @@ static int pseries_idle_devices_init(void)
296static int pseries_idle_probe(void) 250static int pseries_idle_probe(void)
297{ 251{
298 252
299 if (!firmware_has_feature(FW_FEATURE_SPLPAR))
300 return -ENODEV;
301
302 if (cpuidle_disable != IDLE_NO_OVERRIDE) 253 if (cpuidle_disable != IDLE_NO_OVERRIDE)
303 return -ENODEV; 254 return -ENODEV;
304 255
@@ -307,10 +258,13 @@ static int pseries_idle_probe(void)
307 return -EPERM; 258 return -EPERM;
308 } 259 }
309 260
310 if (lppaca_shared_proc(get_lppaca())) 261 if (firmware_has_feature(FW_FEATURE_SPLPAR)) {
311 cpuidle_state_table = shared_states; 262 if (lppaca_shared_proc(get_lppaca()))
312 else 263 cpuidle_state_table = shared_states;
313 cpuidle_state_table = dedicated_states; 264 else
265 cpuidle_state_table = dedicated_states;
266 } else
267 return -ENODEV;
314 268
315 return 0; 269 return 0;
316} 270}
@@ -324,22 +278,14 @@ static int __init pseries_processor_idle_init(void)
324 return retval; 278 return retval;
325 279
326 pseries_cpuidle_driver_init(); 280 pseries_cpuidle_driver_init();
327 retval = cpuidle_register_driver(&pseries_idle_driver); 281 retval = cpuidle_register(&pseries_idle_driver, NULL);
328 if (retval) { 282 if (retval) {
329 printk(KERN_DEBUG "Registration of pseries driver failed.\n"); 283 printk(KERN_DEBUG "Registration of pseries driver failed.\n");
330 return retval; 284 return retval;
331 } 285 }
332 286
333 retval = pseries_idle_devices_init();
334 if (retval) {
335 pseries_idle_devices_uninit();
336 cpuidle_unregister_driver(&pseries_idle_driver);
337 return retval;
338 }
339
340 register_cpu_notifier(&setup_hotplug_notifier); 287 register_cpu_notifier(&setup_hotplug_notifier);
341 printk(KERN_DEBUG "pseries_idle_driver registered\n"); 288 printk(KERN_DEBUG "pseries_idle_driver registered\n");
342
343 return 0; 289 return 0;
344} 290}
345 291
@@ -347,9 +293,7 @@ static void __exit pseries_processor_idle_exit(void)
347{ 293{
348 294
349 unregister_cpu_notifier(&setup_hotplug_notifier); 295 unregister_cpu_notifier(&setup_hotplug_notifier);
350 pseries_idle_devices_uninit(); 296 cpuidle_unregister(&pseries_idle_driver);
351 cpuidle_unregister_driver(&pseries_idle_driver);
352
353 return; 297 return;
354} 298}
355 299