aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--drivers/idle/intel_idle.c82
-rw-r--r--include/linux/cpuidle.h7
2 files changed, 49 insertions, 40 deletions
diff --git a/drivers/idle/intel_idle.c b/drivers/idle/intel_idle.c
index 5d2f8e13cf0e..ef0c04d8dc22 100644
--- a/drivers/idle/intel_idle.c
+++ b/drivers/idle/intel_idle.c
@@ -478,64 +478,60 @@ static int intel_idle_cpuidle_driver_init(void)
478 478
479 479
480/* 480/*
481 * intel_idle_cpuidle_devices_init() 481 * intel_idle_cpu_init()
482 * allocate, initialize, register cpuidle_devices 482 * allocate, initialize, register cpuidle_devices
483 * @cpu: cpu/core to initialize
483 */ 484 */
484static int intel_idle_cpuidle_devices_init(void) 485int intel_idle_cpu_init(int cpu)
485{ 486{
486 int i, cstate; 487 int cstate;
487 struct cpuidle_device *dev; 488 struct cpuidle_device *dev;
488 489
489 intel_idle_cpuidle_devices = alloc_percpu(struct cpuidle_device); 490 dev = per_cpu_ptr(intel_idle_cpuidle_devices, cpu);
490 if (intel_idle_cpuidle_devices == NULL)
491 return -ENOMEM;
492
493 for_each_online_cpu(i) {
494 dev = per_cpu_ptr(intel_idle_cpuidle_devices, i);
495 491
496 dev->state_count = 1; 492 dev->state_count = 1;
497 493
498 for (cstate = 1; cstate < MWAIT_MAX_NUM_CSTATES; ++cstate) { 494 for (cstate = 1; cstate < MWAIT_MAX_NUM_CSTATES; ++cstate) {
499 int num_substates; 495 int num_substates;
500 496
501 if (cstate > max_cstate) { 497 if (cstate > max_cstate) {
502 printk(PREFIX "max_cstate %d reached\n", 498 printk(PREFIX "max_cstate %d reached\n",
503 max_cstate); 499 max_cstate);
504 break; 500 break;
505 } 501 }
506 502
507 /* does the state exist in CPUID.MWAIT? */ 503 /* does the state exist in CPUID.MWAIT? */
508 num_substates = (mwait_substates >> ((cstate) * 4)) 504 num_substates = (mwait_substates >> ((cstate) * 4))
509 & MWAIT_SUBSTATE_MASK; 505 & MWAIT_SUBSTATE_MASK;
510 if (num_substates == 0) 506 if (num_substates == 0)
511 continue; 507 continue;
512 /* is the state not enabled? */ 508 /* is the state not enabled? */
513 if (cpuidle_state_table[cstate].enter == NULL) { 509 if (cpuidle_state_table[cstate].enter == NULL)
514 continue; 510 continue;
515 }
516 511
517 dev->states_usage[dev->state_count].driver_data = 512 dev->states_usage[dev->state_count].driver_data =
518 (void *)get_driver_data(cstate); 513 (void *)get_driver_data(cstate);
519 514
520 dev->state_count += 1; 515 dev->state_count += 1;
521 } 516 }
517 dev->cpu = cpu;
522 518
523 dev->cpu = i; 519 if (cpuidle_register_device(dev)) {
524 if (cpuidle_register_device(dev)) { 520 pr_debug(PREFIX "cpuidle_register_device %d failed!\n", cpu);
525 pr_debug(PREFIX "cpuidle_register_device %d failed!\n", 521 intel_idle_cpuidle_devices_uninit();
526 i); 522 return -EIO;
527 intel_idle_cpuidle_devices_uninit();
528 return -EIO;
529 }
530 } 523 }
531 524
525 if (auto_demotion_disable_flags)
526 smp_call_function_single(cpu, auto_demotion_disable, NULL, 1);
527
532 return 0; 528 return 0;
533} 529}
534 530
535 531
536static int __init intel_idle_init(void) 532static int __init intel_idle_init(void)
537{ 533{
538 int retval; 534 int retval, i;
539 535
540 /* Do not load intel_idle at all for now if idle= is passed */ 536 /* Do not load intel_idle at all for now if idle= is passed */
541 if (boot_option_idle_override != IDLE_NO_OVERRIDE) 537 if (boot_option_idle_override != IDLE_NO_OVERRIDE)
@@ -553,10 +549,16 @@ static int __init intel_idle_init(void)
553 return retval; 549 return retval;
554 } 550 }
555 551
556 retval = intel_idle_cpuidle_devices_init(); 552 intel_idle_cpuidle_devices = alloc_percpu(struct cpuidle_device);
557 if (retval) { 553 if (intel_idle_cpuidle_devices == NULL)
558 cpuidle_unregister_driver(&intel_idle_driver); 554 return -ENOMEM;
559 return retval; 555
556 for_each_online_cpu(i) {
557 retval = intel_idle_cpu_init(i);
558 if (retval) {
559 cpuidle_unregister_driver(&intel_idle_driver);
560 return retval;
561 }
560 } 562 }
561 563
562 return 0; 564 return 0;
diff --git a/include/linux/cpuidle.h b/include/linux/cpuidle.h
index 7408af843b8a..93df66ea794a 100644
--- a/include/linux/cpuidle.h
+++ b/include/linux/cpuidle.h
@@ -188,7 +188,14 @@ struct cpuidle_governor {
188extern int cpuidle_register_governor(struct cpuidle_governor *gov); 188extern int cpuidle_register_governor(struct cpuidle_governor *gov);
189extern void cpuidle_unregister_governor(struct cpuidle_governor *gov); 189extern void cpuidle_unregister_governor(struct cpuidle_governor *gov);
190 190
191#ifdef CONFIG_INTEL_IDLE
192extern int intel_idle_cpu_init(int cpu);
191#else 193#else
194static inline int intel_idle_cpu_init(int cpu) { return -1; }
195#endif
196
197#else
198static inline int intel_idle_cpu_init(int cpu) { return -1; }
192 199
193static inline int cpuidle_register_governor(struct cpuidle_governor *gov) 200static inline int cpuidle_register_governor(struct cpuidle_governor *gov)
194{return 0;} 201{return 0;}