]> git.karo-electronics.de Git - karo-tx-linux.git/commitdiff
intel_idle: disable auto_demotion for hotplugged CPUs
authorShaohua Li <shaohua.li@intel.com>
Mon, 24 Oct 2011 14:58:34 +0000 (01:58 +1100)
committerStephen Rothwell <sfr@canb.auug.org.au>
Mon, 7 Nov 2011 02:40:29 +0000 (13:40 +1100)
auto_demotion_disable is called only for online CPUs.  For hotplugged
CPUs, we should disable it too.

Signed-off-by: Shaohua Li <shaohua.li@intel.com>
Cc: Len Brown <lenb@kernel.org>
Signed-off-by: Andrew Morton <akpm@linux-foundation.org>
drivers/idle/intel_idle.c

index 0a53882609566865aea95e145477530a3850289f..86e1850e1380a72f9cc0a44e7a5700e7b94e2d21 100644 (file)
@@ -271,33 +271,42 @@ static void __setup_broadcast_timer(void *arg)
        clockevents_notify(reason, &cpu);
 }
 
-static int setup_broadcast_cpuhp_notify(struct notifier_block *n,
+static void auto_demotion_disable(void *dummy)
+{
+       unsigned long long msr_bits;
+
+       rdmsrl(MSR_NHM_SNB_PKG_CST_CFG_CTL, msr_bits);
+       msr_bits &= ~auto_demotion_disable_flags;
+       wrmsrl(MSR_NHM_SNB_PKG_CST_CFG_CTL, msr_bits);
+}
+
+static void __intel_idle_notify_handler(void *arg)
+{
+       if (auto_demotion_disable_flags)
+               auto_demotion_disable(NULL);
+
+       if (lapic_timer_reliable_states != LAPIC_TIMER_ALWAYS_RELIABLE)
+               __setup_broadcast_timer((void *)true);
+}
+
+static int setup_intelidle_cpuhp_notify(struct notifier_block *n,
                unsigned long action, void *hcpu)
 {
        int hotcpu = (unsigned long)hcpu;
 
        switch (action & 0xf) {
        case CPU_ONLINE:
-               smp_call_function_single(hotcpu, __setup_broadcast_timer,
-                       (void *)true, 1);
+               smp_call_function_single(hotcpu, __intel_idle_notify_handler,
+                       NULL, 1);
                break;
        }
        return NOTIFY_OK;
 }
 
-static struct notifier_block setup_broadcast_notifier = {
-       .notifier_call = setup_broadcast_cpuhp_notify,
+static struct notifier_block setup_intelidle_notifier = {
+       .notifier_call = setup_intelidle_cpuhp_notify,
 };
 
-static void auto_demotion_disable(void *dummy)
-{
-       unsigned long long msr_bits;
-
-       rdmsrl(MSR_NHM_SNB_PKG_CST_CFG_CTL, msr_bits);
-       msr_bits &= ~auto_demotion_disable_flags;
-       wrmsrl(MSR_NHM_SNB_PKG_CST_CFG_CTL, msr_bits);
-}
-
 /*
  * intel_idle_probe()
  */
@@ -367,10 +376,8 @@ static int intel_idle_probe(void)
 
        if (boot_cpu_has(X86_FEATURE_ARAT))     /* Always Reliable APIC Timer */
                lapic_timer_reliable_states = LAPIC_TIMER_ALWAYS_RELIABLE;
-       else {
+       else
                on_each_cpu(__setup_broadcast_timer, (void *)true, 1);
-               register_cpu_notifier(&setup_broadcast_notifier);
-       }
 
        pr_debug(PREFIX "v" INTEL_IDLE_VERSION
                " model 0x%X\n", boot_cpu_data.x86_model);
@@ -491,6 +498,10 @@ static int __init intel_idle_init(void)
                return retval;
        }
 
+       if (auto_demotion_disable_flags || lapic_timer_reliable_states !=
+           LAPIC_TIMER_ALWAYS_RELIABLE)
+               register_cpu_notifier(&setup_intelidle_notifier);
+
        return 0;
 }
 
@@ -499,10 +510,12 @@ static void __exit intel_idle_exit(void)
        intel_idle_cpuidle_devices_uninit();
        cpuidle_unregister_driver(&intel_idle_driver);
 
-       if (lapic_timer_reliable_states != LAPIC_TIMER_ALWAYS_RELIABLE) {
+       if (lapic_timer_reliable_states != LAPIC_TIMER_ALWAYS_RELIABLE)
                on_each_cpu(__setup_broadcast_timer, (void *)false, 1);
-               unregister_cpu_notifier(&setup_broadcast_notifier);
-       }
+
+       if (auto_demotion_disable_flags || lapic_timer_reliable_states !=
+           LAPIC_TIMER_ALWAYS_RELIABLE)
+               unregister_cpu_notifier(&setup_intelidle_notifier);
 
        return;
 }