diff options
author | Pekka Paalanen <pq@iki.fi> | 2008-05-12 15:21:02 -0400 |
---|---|---|
committer | Thomas Gleixner <tglx@linutronix.de> | 2008-05-24 05:26:52 -0400 |
commit | 7423d1115f18627666d475fccc7c62394406ff8c (patch) | |
tree | 0c53cab24435ee95c0f4b01e257060bc171c15b6 /arch | |
parent | 37b3619257d3190f47f233d7ed626d4b9916462c (diff) |
x86 mmiotrace: dynamically disable non-boot CPUs
From 8979ee55cb6a429c4edd72ebec2244b849f6a79a Mon Sep 17 00:00:00 2001
From: Pekka Paalanen <pq@iki.fi>
Date: Sat, 12 Apr 2008 00:18:57 +0300
Mmiotrace is not reliable with multiple CPUs and may
miss events. Drop to single CPU when mmiotrace is activated.
Signed-off-by: Pekka Paalanen <pq@iki.fi>
Signed-off-by: Ingo Molnar <mingo@elte.hu>
Diffstat (limited to 'arch')
-rw-r--r-- | arch/x86/mm/mmio-mod.c | 61 |
1 files changed, 61 insertions, 0 deletions
diff --git a/arch/x86/mm/mmio-mod.c b/arch/x86/mm/mmio-mod.c index 6d6cac84c045..1f77d8532037 100644 --- a/arch/x86/mm/mmio-mod.c +++ b/arch/x86/mm/mmio-mod.c | |||
@@ -32,6 +32,7 @@ | |||
32 | #include <asm/e820.h> /* for ISA_START_ADDRESS */ | 32 | #include <asm/e820.h> /* for ISA_START_ADDRESS */ |
33 | #include <asm/atomic.h> | 33 | #include <asm/atomic.h> |
34 | #include <linux/percpu.h> | 34 | #include <linux/percpu.h> |
35 | #include <linux/cpu.h> | ||
35 | 36 | ||
36 | #include "pf_in.h" | 37 | #include "pf_in.h" |
37 | 38 | ||
@@ -400,6 +401,64 @@ static void clear_trace_list(void) | |||
400 | } | 401 | } |
401 | } | 402 | } |
402 | 403 | ||
404 | #ifdef CONFIG_HOTPLUG_CPU | ||
405 | static cpumask_t downed_cpus; | ||
406 | |||
407 | static void enter_uniprocessor(void) | ||
408 | { | ||
409 | int cpu; | ||
410 | int err; | ||
411 | |||
412 | get_online_cpus(); | ||
413 | downed_cpus = cpu_online_map; | ||
414 | cpu_clear(first_cpu(cpu_online_map), downed_cpus); | ||
415 | if (num_online_cpus() > 1) | ||
416 | pr_notice(NAME "Disabling non-boot CPUs...\n"); | ||
417 | put_online_cpus(); | ||
418 | |||
419 | for_each_cpu_mask(cpu, downed_cpus) { | ||
420 | err = cpu_down(cpu); | ||
421 | if (!err) { | ||
422 | pr_info(NAME "CPU%d is down.\n", cpu); | ||
423 | } else { | ||
424 | pr_err(NAME "Error taking CPU%d down: %d\n", cpu, err); | ||
425 | } | ||
426 | } | ||
427 | if (num_online_cpus() > 1) | ||
428 | pr_warning(NAME "multiple CPUs still online, " | ||
429 | "may miss events.\n"); | ||
430 | } | ||
431 | |||
432 | static void leave_uniprocessor(void) | ||
433 | { | ||
434 | int cpu; | ||
435 | int err; | ||
436 | |||
437 | if (cpus_weight(downed_cpus) == 0) | ||
438 | return; | ||
439 | pr_notice(NAME "Re-enabling CPUs...\n"); | ||
440 | for_each_cpu_mask(cpu, downed_cpus) { | ||
441 | err = cpu_up(cpu); | ||
442 | if (!err) | ||
443 | pr_info(NAME "enabled CPU%d.\n", cpu); | ||
444 | else | ||
445 | pr_err(NAME "cannot re-enable CPU%d: %d\n", cpu, err); | ||
446 | } | ||
447 | } | ||
448 | |||
449 | #else /* !CONFIG_HOTPLUG_CPU */ | ||
450 | static void enter_uniprocessor(void) | ||
451 | { | ||
452 | if (num_online_cpus() > 1) | ||
453 | pr_warning(NAME "multiple CPUs are online, may miss events. " | ||
454 | "Suggest booting with maxcpus=1 kernel argument.\n"); | ||
455 | } | ||
456 | |||
457 | static void leave_uniprocessor(void) | ||
458 | { | ||
459 | } | ||
460 | #endif | ||
461 | |||
403 | #if 0 /* XXX: out of order */ | 462 | #if 0 /* XXX: out of order */ |
404 | static struct file_operations fops_marker = { | 463 | static struct file_operations fops_marker = { |
405 | .owner = THIS_MODULE, | 464 | .owner = THIS_MODULE, |
@@ -422,6 +481,7 @@ void enable_mmiotrace(void) | |||
422 | 481 | ||
423 | if (nommiotrace) | 482 | if (nommiotrace) |
424 | pr_info(NAME "MMIO tracing disabled.\n"); | 483 | pr_info(NAME "MMIO tracing disabled.\n"); |
484 | enter_uniprocessor(); | ||
425 | spin_lock_irq(&trace_lock); | 485 | spin_lock_irq(&trace_lock); |
426 | atomic_inc(&mmiotrace_enabled); | 486 | atomic_inc(&mmiotrace_enabled); |
427 | spin_unlock_irq(&trace_lock); | 487 | spin_unlock_irq(&trace_lock); |
@@ -442,6 +502,7 @@ void disable_mmiotrace(void) | |||
442 | spin_unlock_irq(&trace_lock); | 502 | spin_unlock_irq(&trace_lock); |
443 | 503 | ||
444 | clear_trace_list(); /* guarantees: no more kmmio callbacks */ | 504 | clear_trace_list(); /* guarantees: no more kmmio callbacks */ |
505 | leave_uniprocessor(); | ||
445 | if (marker_file) { | 506 | if (marker_file) { |
446 | debugfs_remove(marker_file); | 507 | debugfs_remove(marker_file); |
447 | marker_file = NULL; | 508 | marker_file = NULL; |