diff options
author | Rusty Russell <rusty@rustcorp.com.au> | 2009-03-17 00:20:34 -0400 |
---|---|---|
committer | Ingo Molnar <mingo@elte.hu> | 2009-03-18 04:40:35 -0400 |
commit | 30e1e6d1af2b67558bccf322af2b3e0676b209ae (patch) | |
tree | dae658631d0bb038c373cc2ba34ecf43f31ebd25 /arch/x86/kernel/process.c | |
parent | 082edb7bf443eb8eda15b482d16ad9dd8137ad24 (diff) |
cpumask: fix CONFIG_CPUMASK_OFFSTACK=y cpu hotunplug crash
Impact: Fix cpu offline when CONFIG_MAXSMP=y
Changeset bc9b83dd1f66402b870301c3c7117b9c1484abb4 "cpumask: convert
c1e_mask in arch/x86/kernel/process.c to cpumask_var_t" contained a
bug: c1e_mask is manipulated even if C1E isn't detected (and hence
not allocated).
This is simply fixed by checking for NULL (which gcc optimizes out
anyway of CONFIG_CPUMASK_OFFSTACK=n, since it knows ce1_mask can never
be NULL).
In addition, fix a leak where select_idle_routine re-allocates
(and re-clears) c1e_mask on every cpu init.
Reported-by: Ingo Molnar <mingo@elte.hu>
Signed-off-by: Rusty Russell <rusty@rustcorp.com.au>
Cc: Mike Travis <travis@sgi.com>
LKML-Reference: <200903171450.34549.rusty@rustcorp.com.au>
Signed-off-by: Ingo Molnar <mingo@elte.hu>
Diffstat (limited to 'arch/x86/kernel/process.c')
-rw-r--r-- | arch/x86/kernel/process.c | 14 |
1 files changed, 11 insertions, 3 deletions
diff --git a/arch/x86/kernel/process.c b/arch/x86/kernel/process.c index 6638294cec8d..78533a519d8f 100644 --- a/arch/x86/kernel/process.c +++ b/arch/x86/kernel/process.c | |||
@@ -479,7 +479,8 @@ static int c1e_detected; | |||
479 | 479 | ||
480 | void c1e_remove_cpu(int cpu) | 480 | void c1e_remove_cpu(int cpu) |
481 | { | 481 | { |
482 | cpumask_clear_cpu(cpu, c1e_mask); | 482 | if (c1e_mask != NULL) |
483 | cpumask_clear_cpu(cpu, c1e_mask); | ||
483 | } | 484 | } |
484 | 485 | ||
485 | /* | 486 | /* |
@@ -556,13 +557,20 @@ void __cpuinit select_idle_routine(const struct cpuinfo_x86 *c) | |||
556 | pm_idle = mwait_idle; | 557 | pm_idle = mwait_idle; |
557 | } else if (check_c1e_idle(c)) { | 558 | } else if (check_c1e_idle(c)) { |
558 | printk(KERN_INFO "using C1E aware idle routine\n"); | 559 | printk(KERN_INFO "using C1E aware idle routine\n"); |
559 | alloc_cpumask_var(&c1e_mask, GFP_KERNEL); | ||
560 | cpumask_clear(c1e_mask); | ||
561 | pm_idle = c1e_idle; | 560 | pm_idle = c1e_idle; |
562 | } else | 561 | } else |
563 | pm_idle = default_idle; | 562 | pm_idle = default_idle; |
564 | } | 563 | } |
565 | 564 | ||
565 | void __init init_c1e_mask(void) | ||
566 | { | ||
567 | /* If we're using c1e_idle, we need to allocate c1e_mask. */ | ||
568 | if (pm_idle == c1e_idle) { | ||
569 | alloc_cpumask_var(&c1e_mask, GFP_KERNEL); | ||
570 | cpumask_clear(c1e_mask); | ||
571 | } | ||
572 | } | ||
573 | |||
566 | static int __init idle_setup(char *str) | 574 | static int __init idle_setup(char *str) |
567 | { | 575 | { |
568 | if (!str) | 576 | if (!str) |