From 093f13e23137b9e5f7629dd5932ceea1419e2b61 Mon Sep 17 00:00:00 2001 From: "Pallipadi, Venkatesh" Date: Wed, 15 Apr 2009 10:37:33 -0700 Subject: x86, acpi_cpufreq: Fix the NULL pointer dereference in get_measured_perf Fix for a regression that was introduced by earlier commit 18b2646fe3babeb40b34a0c1751e0bf5adfdc64c on Mon Apr 6 11:26:08 2009 Regression resulted in the below error happened on systems with software coordination where per_cpu acpi data will not be initiated for secondary CPUs in a P-state domain. On Tue, 2009-04-14 at 23:01 -0700, Zhang, Yanmin wrote: My machine hanged with kernel 2.6.30-rc2 when script read > /sys/devices/system/cpu/cpu0/cpufreq/scaling_governor. > > opps happens in get_measured_perf: > > cur.aperf.whole = readin.aperf.whole - > per_cpu(drv_data, cpu)->saved_aperf; > > Because per_cpu(drv_data, cpu)=NULL. > > So function get_measured_perf should check if (per_cpu(drv_data, > cpu)==NULL) > and return 0 if it's NULL. --------------sys log------------------ BUG: unable to handle kernel NULL pointer dereference at 0000000000000020 IP: [] get_measured_perf+0x4a/0xf9 PGD a7dd88067 PUD a7ccf5067 PMD 0 Oops: 0000 [#1] SMP last sysfs file: /sys/devices/system/cpu/cpu0/cpufreq/scaling_governor CPU 0 Modules linked in: video output Pid: 2091, comm: kondemand/0 Not tainted 2.6.30-rc2 #1 MP Server RIP: 0010:[] [] get_measured_perf+0x4a/0xf9 RSP: 0018:ffff880a7d56de20 EFLAGS: 00010246 RAX: 0000000000000000 RBX: 00000046241a42b6 RCX: ffff88004d219000 RDX: 000000000000b660 RSI: 0000000000000020 RDI: 0000000000000001 RBP: ffff880a7f052000 R08: 00000046241a42b6 R09: ffffffff807639f0 R10: 00000000ffffffea R11: ffffffff802207f4 R12: ffff880a7f052000 R13: ffff88004d20e460 R14: 0000000000ddd5a6 R15: 0000000000000001 FS: 0000000000000000(0000) GS:ffff88004d200000(0000) knlGS:0000000000000000 CS: 0010 DS: 0018 ES: 0018 CR0: 000000008005003b CR2: 0000000000000020 CR3: 0000000a7f1bf000 CR4: 00000000000006e0 DR0: 0000000000000000 DR1: 0000000000000000 DR2: 0000000000000000 DR3: 0000000000000000 DR6: 00000000ffff0ff0 DR7: 0000000000000400 Process kondemand/0 (pid: 2091, threadinfo ffff880a7d56c000, task ffff880a7d4d18c0) Stack: ffff880a7f052078 ffffffff803efd54 00000046241a42b6 000000462ffa9e95 0000000000000001 0000000000000001 00000000ffffffea ffffffff8064f41a 0000000000000012 0000000000000012 ffff880a7f052000 ffffffff80650547 Call Trace: [] ? kobject_get+0x12/0x17 [] ? __cpufreq_driver_getavg+0x42/0x57 [] ? do_dbs_timer+0x147/0x272 [] ? do_dbs_timer+0x0/0x272 [] ? worker_thread+0x15b/0x1f5 [] ? autoremove_wake_function+0x0/0x2e [] ? worker_thread+0x0/0x1f5 [] ? kthread+0x54/0x83 [] ? child_rip+0xa/0x20 [] ? kthread+0x0/0x83 [] ? child_rip+0x0/0x20 Code: 99 a6 03 00 31 c9 85 c0 0f 85 c3 00 00 00 89 df 4c 8b 44 24 10 48 c7 c2 60 b6 00 00 48 8b 0c fd e0 30 a5 80 4c 89 c3 48 8b 04 0a <48> 2b 58 20 48 8b 44 24 18 48 89 1c 24 48 8b 34 0a 48 2b 46 28 RIP [] get_measured_perf+0x4a/0xf9 RSP CR2: 0000000000000020 ---[ end trace 2b8fac9a49e19ad4 ]--- Tested-by: "Zhang, Yanmin" Signed-off-by: Venkatesh Pallipadi Signed-off-by: Len Brown --- arch/x86/kernel/cpu/cpufreq/acpi-cpufreq.c | 15 ++++++++++----- 1 file changed, 10 insertions(+), 5 deletions(-) (limited to 'arch/x86/kernel/cpu') diff --git a/arch/x86/kernel/cpu/cpufreq/acpi-cpufreq.c b/arch/x86/kernel/cpu/cpufreq/acpi-cpufreq.c index ecdb682ab51..dd0bd76d14c 100644 --- a/arch/x86/kernel/cpu/cpufreq/acpi-cpufreq.c +++ b/arch/x86/kernel/cpu/cpufreq/acpi-cpufreq.c @@ -68,11 +68,16 @@ struct acpi_cpufreq_data { unsigned int max_freq; unsigned int resume; unsigned int cpu_feature; - u64 saved_aperf, saved_mperf; }; static DEFINE_PER_CPU(struct acpi_cpufreq_data *, drv_data); +struct acpi_msr_data { + u64 saved_aperf, saved_mperf; +}; + +static DEFINE_PER_CPU(struct acpi_msr_data, msr_data); + DEFINE_TRACE(power_mark); /* acpi_perf_data is a pointer to percpu data. */ @@ -287,11 +292,11 @@ static unsigned int get_measured_perf(struct cpufreq_policy *policy, return 0; cur.aperf.whole = readin.aperf.whole - - per_cpu(drv_data, cpu)->saved_aperf; + per_cpu(msr_data, cpu).saved_aperf; cur.mperf.whole = readin.mperf.whole - - per_cpu(drv_data, cpu)->saved_mperf; - per_cpu(drv_data, cpu)->saved_aperf = readin.aperf.whole; - per_cpu(drv_data, cpu)->saved_mperf = readin.mperf.whole; + per_cpu(msr_data, cpu).saved_mperf; + per_cpu(msr_data, cpu).saved_aperf = readin.aperf.whole; + per_cpu(msr_data, cpu).saved_mperf = readin.mperf.whole; #ifdef __i386__ /* -- cgit v1.2.3-70-g09d2 From e0e8c4e512e92bc25c19bd8d4926de17d2f8fbf2 Mon Sep 17 00:00:00 2001 From: Thomas Renninger Date: Fri, 17 Apr 2009 16:22:06 +0200 Subject: acpi-cpufreq: Cleanup: Use printk_once Signed-off-by: Thomas Renninger Signed-off-by: Len Brown --- arch/x86/kernel/cpu/cpufreq/acpi-cpufreq.c | 8 ++------ 1 file changed, 2 insertions(+), 6 deletions(-) (limited to 'arch/x86/kernel/cpu') diff --git a/arch/x86/kernel/cpu/cpufreq/acpi-cpufreq.c b/arch/x86/kernel/cpu/cpufreq/acpi-cpufreq.c index dd0bd76d14c..4eab747a896 100644 --- a/arch/x86/kernel/cpu/cpufreq/acpi-cpufreq.c +++ b/arch/x86/kernel/cpu/cpufreq/acpi-cpufreq.c @@ -693,13 +693,9 @@ static int acpi_cpufreq_cpu_init(struct cpufreq_policy *policy) /* Check for high latency (>20uS) from buggy BIOSes, like on T42 */ if (perf->control_register.space_id == ACPI_ADR_SPACE_FIXED_HARDWARE && policy->cpuinfo.transition_latency > 20 * 1000) { - static int print_once; policy->cpuinfo.transition_latency = 20 * 1000; - if (!print_once) { - print_once = 1; - printk(KERN_INFO "Capping off P-state tranision latency" - " at 20 uS\n"); - } + printk_once(KERN_INFO "Capping off P-state tranision" + " latency at 20 uS\n"); } data->max_freq = perf->states[0].core_frequency * 1000; -- cgit v1.2.3-70-g09d2 From d91758f5ddb80e91176fa2cf80c88c1633950b3d Mon Sep 17 00:00:00 2001 From: Thomas Renninger Date: Fri, 17 Apr 2009 16:22:07 +0200 Subject: acpi-cpufreq: style-only: add parens to math expression Signed-off-by: Thomas Renninger Signed-off-by: Len Brown --- arch/x86/kernel/cpu/cpufreq/acpi-cpufreq.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'arch/x86/kernel/cpu') diff --git a/arch/x86/kernel/cpu/cpufreq/acpi-cpufreq.c b/arch/x86/kernel/cpu/cpufreq/acpi-cpufreq.c index 4eab747a896..aec3161abed 100644 --- a/arch/x86/kernel/cpu/cpufreq/acpi-cpufreq.c +++ b/arch/x86/kernel/cpu/cpufreq/acpi-cpufreq.c @@ -340,7 +340,7 @@ static unsigned int get_measured_perf(struct cpufreq_policy *policy, #endif - retval = per_cpu(drv_data, policy->cpu)->max_freq * perf_percent / 100; + retval = (per_cpu(drv_data, policy->cpu)->max_freq * perf_percent) / 100; return retval; } -- cgit v1.2.3-70-g09d2 From d876dfbbf5c8728102fb4f683450fa9ae3259cda Mon Sep 17 00:00:00 2001 From: Thomas Renninger Date: Fri, 17 Apr 2009 16:22:08 +0200 Subject: acpi-cpufreq: Do not let get_measured perf depend on internal variable Take already available policy->cpuinfo.max_freq and get rid of acpi-cpufreq specific max_freq variable. This implies that P0 is always the highest frequency which should always be true as ACPI spec says: As a result, the zeroth entry describes the highest performance state Signed-off-by: Thomas Renninger Acked-by: Venkatesh Pallipadi Signed-off-by: Len Brown --- arch/x86/kernel/cpu/cpufreq/acpi-cpufreq.c | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) (limited to 'arch/x86/kernel/cpu') diff --git a/arch/x86/kernel/cpu/cpufreq/acpi-cpufreq.c b/arch/x86/kernel/cpu/cpufreq/acpi-cpufreq.c index aec3161abed..208ecf6643d 100644 --- a/arch/x86/kernel/cpu/cpufreq/acpi-cpufreq.c +++ b/arch/x86/kernel/cpu/cpufreq/acpi-cpufreq.c @@ -65,7 +65,6 @@ enum { struct acpi_cpufreq_data { struct acpi_processor_performance *acpi_data; struct cpufreq_frequency_table *freq_table; - unsigned int max_freq; unsigned int resume; unsigned int cpu_feature; }; @@ -340,7 +339,7 @@ static unsigned int get_measured_perf(struct cpufreq_policy *policy, #endif - retval = (per_cpu(drv_data, policy->cpu)->max_freq * perf_percent) / 100; + retval = (policy->cpuinfo.max_freq * perf_percent) / 100; return retval; } @@ -698,7 +697,6 @@ static int acpi_cpufreq_cpu_init(struct cpufreq_policy *policy) " latency at 20 uS\n"); } - data->max_freq = perf->states[0].core_frequency * 1000; /* table init */ for (i = 0; i < perf->state_count; i++) { if (i > 0 && perf->states[i].core_frequency >= @@ -717,6 +715,9 @@ static int acpi_cpufreq_cpu_init(struct cpufreq_policy *policy) if (result) goto err_freqfree; + if (perf->states[0].core_frequency * 1000 != policy->cpuinfo.max_freq) + printk(KERN_WARNING FW_WARN "P-state 0 is not max freq\n"); + switch (perf->control_register.space_id) { case ACPI_ADR_SPACE_SYSTEM_IO: /* Current speed is unknown and not detectable by IO port */ -- cgit v1.2.3-70-g09d2 From 6298c512bc1007c3ff5c9ce20e6996781651cc45 Mon Sep 17 00:00:00 2001 From: Andi Kleen Date: Thu, 9 Apr 2009 12:28:22 +0200 Subject: x86, mce: make polling timer interval per CPU The polling timer while running per CPU still uses a global next_interval variable, which lead to some CPUs either polling too fast or too slow. This was not a serious problem because all errors get picked up eventually, but it's still better to avoid it. Turn next_interval into a per cpu variable. v2: Fix check_interval == 0 case (Hidetoshi Seto) [ Impact: minor bug fix ] Signed-off-by: Andi Kleen Reviewed-by: Hidetoshi Seto Signed-off-by: H. Peter Anvin --- arch/x86/kernel/cpu/mcheck/mce_64.c | 24 ++++++++++++------------ 1 file changed, 12 insertions(+), 12 deletions(-) (limited to 'arch/x86/kernel/cpu') diff --git a/arch/x86/kernel/cpu/mcheck/mce_64.c b/arch/x86/kernel/cpu/mcheck/mce_64.c index 863f89568b1..82614f1b923 100644 --- a/arch/x86/kernel/cpu/mcheck/mce_64.c +++ b/arch/x86/kernel/cpu/mcheck/mce_64.c @@ -452,13 +452,14 @@ void mce_log_therm_throt_event(__u64 status) */ static int check_interval = 5 * 60; /* 5 minutes */ -static int next_interval; /* in jiffies */ +static DEFINE_PER_CPU(int, next_interval); /* in jiffies */ static void mcheck_timer(unsigned long); static DEFINE_PER_CPU(struct timer_list, mce_timer); static void mcheck_timer(unsigned long data) { struct timer_list *t = &per_cpu(mce_timer, data); + int *n; WARN_ON(smp_processor_id() != data); @@ -470,14 +471,14 @@ static void mcheck_timer(unsigned long data) * Alert userspace if needed. If we logged an MCE, reduce the * polling interval, otherwise increase the polling interval. */ + n = &__get_cpu_var(next_interval); if (mce_notify_user()) { - next_interval = max(next_interval/2, HZ/100); + *n = max(*n/2, HZ/100); } else { - next_interval = min(next_interval * 2, - (int)round_jiffies_relative(check_interval*HZ)); + *n = min(*n*2, (int)round_jiffies_relative(check_interval*HZ)); } - t->expires = jiffies + next_interval; + t->expires = jiffies + *n; add_timer(t); } @@ -632,14 +633,13 @@ static void mce_cpu_features(struct cpuinfo_x86 *c) static void mce_init_timer(void) { struct timer_list *t = &__get_cpu_var(mce_timer); + int *n = &__get_cpu_var(next_interval); - /* data race harmless because everyone sets to the same value */ - if (!next_interval) - next_interval = check_interval * HZ; - if (!next_interval) + *n = check_interval * HZ; + if (!*n) return; setup_timer(t, mcheck_timer, smp_processor_id()); - t->expires = round_jiffies(jiffies + next_interval); + t->expires = round_jiffies(jiffies + *n); add_timer(t); } @@ -907,7 +907,6 @@ static void mce_cpu_restart(void *data) /* Reinit MCEs after user configuration changes */ static void mce_restart(void) { - next_interval = check_interval * HZ; on_each_cpu(mce_cpu_restart, NULL, 1); } @@ -1110,7 +1109,8 @@ static int __cpuinit mce_cpu_callback(struct notifier_block *nfb, break; case CPU_DOWN_FAILED: case CPU_DOWN_FAILED_FROZEN: - t->expires = round_jiffies(jiffies + next_interval); + t->expires = round_jiffies(jiffies + + __get_cpu_var(next_interval)); add_timer_on(t, cpu); smp_call_function_single(cpu, mce_reenable_cpu, &action, 1); break; -- cgit v1.2.3-70-g09d2 From 5679af4c1625a1534a4321e1ecc3c48a1cf65eb8 Mon Sep 17 00:00:00 2001 From: Andi Kleen Date: Tue, 7 Apr 2009 17:06:55 +0200 Subject: x86, mce: fix boot logging logic The earlier patch to change the poller to a separate function subtly broke the boot logging logic. This could lead to machine checks getting logged at boot even when disabled or defaulting to off on some systems. Fix that. [ Impact: bug fix - avoid spurious MCE in log ] Signed-off-by: Andi Kleen Reviewed-by: Hidetoshi Seto Signed-off-by: H. Peter Anvin --- arch/x86/include/asm/mce.h | 1 + arch/x86/kernel/cpu/mcheck/mce_64.c | 9 +++++---- 2 files changed, 6 insertions(+), 4 deletions(-) (limited to 'arch/x86/kernel/cpu') diff --git a/arch/x86/include/asm/mce.h b/arch/x86/include/asm/mce.h index 563933e06a3..4f8c199584e 100644 --- a/arch/x86/include/asm/mce.h +++ b/arch/x86/include/asm/mce.h @@ -137,6 +137,7 @@ DECLARE_PER_CPU(mce_banks_t, mce_poll_banks); enum mcp_flags { MCP_TIMESTAMP = (1 << 0), /* log time stamp */ MCP_UC = (1 << 1), /* log uncorrected errors */ + MCP_DONTLOG = (1 << 2), /* only clear, don't log */ }; extern void machine_check_poll(enum mcp_flags flags, mce_banks_t *b); diff --git a/arch/x86/kernel/cpu/mcheck/mce_64.c b/arch/x86/kernel/cpu/mcheck/mce_64.c index 82614f1b923..6fb0b359d2a 100644 --- a/arch/x86/kernel/cpu/mcheck/mce_64.c +++ b/arch/x86/kernel/cpu/mcheck/mce_64.c @@ -239,9 +239,10 @@ void machine_check_poll(enum mcp_flags flags, mce_banks_t *b) * Don't get the IP here because it's unlikely to * have anything to do with the actual error location. */ - - mce_log(&m); - add_taint(TAINT_MACHINE_CHECK); + if (!(flags & MCP_DONTLOG)) { + mce_log(&m); + add_taint(TAINT_MACHINE_CHECK); + } /* * Clear state for this bank. @@ -585,7 +586,7 @@ static void mce_init(void *dummy) * Log the machine checks left over from the previous reset. */ bitmap_fill(all_banks, MAX_NR_BANKS); - machine_check_poll(MCP_UC, &all_banks); + machine_check_poll(MCP_UC|(!mce_bootlog ? MCP_DONTLOG : 0), &all_banks); set_in_cr4(X86_CR4_MCE); -- cgit v1.2.3-70-g09d2 From f9a196b8dceba3c1e5fe885b81e45043ad7c60fc Mon Sep 17 00:00:00 2001 From: Thomas Gleixner Date: Fri, 1 May 2009 20:59:25 +0200 Subject: x86: initialize io_bitmap_base on 32bit commit db949bba3c7cf2e664ac12e237c6d4c914f0c69d (x86-32: use non-lazy io bitmap context switching) broke ioperm for 32bit because it removed the lazy initialization of io_bitmap_base and did not set it to the real bitmap offset. [ Impact: fix non-working sys_ioperm() on 32-bit kernels ] Signed-off-by: Thomas Gleixner --- arch/x86/kernel/cpu/common.c | 2 ++ 1 file changed, 2 insertions(+) (limited to 'arch/x86/kernel/cpu') diff --git a/arch/x86/kernel/cpu/common.c b/arch/x86/kernel/cpu/common.c index c4f667896c2..c1caefc82e6 100644 --- a/arch/x86/kernel/cpu/common.c +++ b/arch/x86/kernel/cpu/common.c @@ -1203,6 +1203,8 @@ void __cpuinit cpu_init(void) load_TR_desc(); load_LDT(&init_mm.context); + t->x86_tss.io_bitmap_base = offsetof(struct tss_struct, io_bitmap); + #ifdef CONFIG_DOUBLEFAULT /* Set up doublefault TSS pointer in the GDT */ __set_tss_desc(cpu, GDT_ENTRY_DOUBLEFAULT_TSS, &doublefault_tss); -- cgit v1.2.3-70-g09d2 From 35d11680a9d82c93eb92f08f9702b72877427b4a Mon Sep 17 00:00:00 2001 From: Andreas Herrmann Date: Mon, 4 May 2009 20:28:59 +0200 Subject: x86: show number of core_siblings instead of thread_siblings in /proc/cpuinfo Commit 7ad728f98162cb1af06a85b2a5fc422dddd4fb78 (cpumask: x86: convert cpu_sibling_map/cpu_core_map to cpumask_var_t) changed the output of /proc/cpuinfo for siblings: Example on an AMD Phenom: physical id : 0 siblings : 1 core id : 3 cpu cores : 4 Before that commit it was: physical id : 0 siblings : 4 core id : 3 cpu cores : 4 Instead of cpu_core_mask it now uses cpu_sibling_mask to count siblings. This is due to the following hunk of above commit: | --- a/arch/x86/kernel/cpu/proc.c | +++ b/arch/x86/kernel/cpu/proc.c | @@ -14,7 +14,7 @@ static void show_cpuinfo_core(struct seq_file *m, struct cpuinf | if (c->x86_max_cores * smp_num_siblings > 1) { | seq_printf(m, "physical id\t: %d\n", c->phys_proc_id); | seq_printf(m, "siblings\t: %d\n", | - cpus_weight(per_cpu(cpu_core_map, cpu))); | + cpumask_weight(cpu_sibling_mask(cpu))); | seq_printf(m, "core id\t\t: %d\n", c->cpu_core_id); | seq_printf(m, "cpu cores\t: %d\n", c->booted_cores); | seq_printf(m, "apicid\t\t: %d\n", c->apicid); This was a mistake, because the impact line shows that this side-effect was not anticipated: Impact: reduce per-cpu size for CONFIG_CPUMASK_OFFSTACK=y So revert the respective hunk to restore the old behavior. [ Impact: fix sibling-info regression in /proc/cpuinfo ] Signed-off-by: Andreas Herrmann Cc: Rusty Russell LKML-Reference: <20090504182859.GA29045@alberich.amd.com> Signed-off-by: Ingo Molnar --- arch/x86/kernel/cpu/proc.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'arch/x86/kernel/cpu') diff --git a/arch/x86/kernel/cpu/proc.c b/arch/x86/kernel/cpu/proc.c index f93047fed79..d5e30397246 100644 --- a/arch/x86/kernel/cpu/proc.c +++ b/arch/x86/kernel/cpu/proc.c @@ -14,7 +14,7 @@ static void show_cpuinfo_core(struct seq_file *m, struct cpuinfo_x86 *c, if (c->x86_max_cores * smp_num_siblings > 1) { seq_printf(m, "physical id\t: %d\n", c->phys_proc_id); seq_printf(m, "siblings\t: %d\n", - cpumask_weight(cpu_sibling_mask(cpu))); + cpumask_weight(cpu_core_mask(cpu))); seq_printf(m, "core id\t\t: %d\n", c->cpu_core_id); seq_printf(m, "cpu cores\t: %d\n", c->booted_cores); seq_printf(m, "apicid\t\t: %d\n", c->apicid); -- cgit v1.2.3-70-g09d2 From e5299926d7459d9fa7c7f856983147817aedb10e Mon Sep 17 00:00:00 2001 From: Hidetoshi Seto Date: Fri, 8 May 2009 17:28:40 +0900 Subject: x86: MCE: make cmci_discover_lock irq-safe Lockdep reports the warning below when Li tries to offline one cpu: [ 110.835487] ================================= [ 110.835616] [ INFO: inconsistent lock state ] [ 110.835688] 2.6.30-rc4-00336-g8c9ed89 #52 [ 110.835757] --------------------------------- [ 110.835828] inconsistent {HARDIRQ-ON-W} -> {IN-HARDIRQ-W} usage. [ 110.835908] swapper/0 [HC1[1]:SC0[0]:HE0:SE1] takes: [ 110.835982] (cmci_discover_lock){?.+...}, at: [] cmci_clear+0x30/0x9b cmci_clear() can be called via smp_call_function_single(). It is better to disable interrupt while holding cmci_discover_lock, to turn it into an irq-safe lock - we can deadlock otherwise. [ Impact: fix possible deadlock in the MCE code ] Reported-by: Shaohua Li Signed-off-by: Hidetoshi Seto Cc: Andi Kleen Cc: Andrew Morton LKML-Reference: <4A03ED38.8000700@jp.fujitsu.com> Signed-off-by: Ingo Molnar Reported-by: Shaohua Li --- arch/x86/kernel/cpu/mcheck/mce_intel_64.c | 10 ++++++---- 1 file changed, 6 insertions(+), 4 deletions(-) (limited to 'arch/x86/kernel/cpu') diff --git a/arch/x86/kernel/cpu/mcheck/mce_intel_64.c b/arch/x86/kernel/cpu/mcheck/mce_intel_64.c index d6b72df89d6..cef3ee30744 100644 --- a/arch/x86/kernel/cpu/mcheck/mce_intel_64.c +++ b/arch/x86/kernel/cpu/mcheck/mce_intel_64.c @@ -151,10 +151,11 @@ static void print_update(char *type, int *hdr, int num) static void cmci_discover(int banks, int boot) { unsigned long *owned = (void *)&__get_cpu_var(mce_banks_owned); + unsigned long flags; int hdr = 0; int i; - spin_lock(&cmci_discover_lock); + spin_lock_irqsave(&cmci_discover_lock, flags); for (i = 0; i < banks; i++) { u64 val; @@ -184,7 +185,7 @@ static void cmci_discover(int banks, int boot) WARN_ON(!test_bit(i, __get_cpu_var(mce_poll_banks))); } } - spin_unlock(&cmci_discover_lock); + spin_unlock_irqrestore(&cmci_discover_lock, flags); if (hdr) printk(KERN_CONT "\n"); } @@ -211,13 +212,14 @@ void cmci_recheck(void) */ void cmci_clear(void) { + unsigned long flags; int i; int banks; u64 val; if (!cmci_supported(&banks)) return; - spin_lock(&cmci_discover_lock); + spin_lock_irqsave(&cmci_discover_lock, flags); for (i = 0; i < banks; i++) { if (!test_bit(i, __get_cpu_var(mce_banks_owned))) continue; @@ -227,7 +229,7 @@ void cmci_clear(void) wrmsrl(MSR_IA32_MC0_CTL2 + i, val); __clear_bit(i, __get_cpu_var(mce_banks_owned)); } - spin_unlock(&cmci_discover_lock); + spin_unlock_irqrestore(&cmci_discover_lock, flags); } /* -- cgit v1.2.3-70-g09d2