diff options
-rw-r--r-- | arch/sparc64/kernel/smp.c | 32 |
1 files changed, 15 insertions, 17 deletions
diff --git a/arch/sparc64/kernel/smp.c b/arch/sparc64/kernel/smp.c index 20f4e291c74a..6d458b35643c 100644 --- a/arch/sparc64/kernel/smp.c +++ b/arch/sparc64/kernel/smp.c | |||
@@ -611,7 +611,7 @@ retry: | |||
611 | static void hypervisor_xcall_deliver(u64 data0, u64 data1, u64 data2, const cpumask_t *mask) | 611 | static void hypervisor_xcall_deliver(u64 data0, u64 data1, u64 data2, const cpumask_t *mask) |
612 | { | 612 | { |
613 | int cnt, retries, this_cpu, prev_sent, i; | 613 | int cnt, retries, this_cpu, prev_sent, i; |
614 | unsigned long flags, status; | 614 | unsigned long status; |
615 | cpumask_t error_mask; | 615 | cpumask_t error_mask; |
616 | struct trap_per_cpu *tb; | 616 | struct trap_per_cpu *tb; |
617 | u16 *cpu_list; | 617 | u16 *cpu_list; |
@@ -620,18 +620,6 @@ static void hypervisor_xcall_deliver(u64 data0, u64 data1, u64 data2, const cpum | |||
620 | if (cpus_empty(*mask)) | 620 | if (cpus_empty(*mask)) |
621 | return; | 621 | return; |
622 | 622 | ||
623 | /* We have to do this whole thing with interrupts fully disabled. | ||
624 | * Otherwise if we send an xcall from interrupt context it will | ||
625 | * corrupt both our mondo block and cpu list state. | ||
626 | * | ||
627 | * One consequence of this is that we cannot use timeout mechanisms | ||
628 | * that depend upon interrupts being delivered locally. So, for | ||
629 | * example, we cannot sample jiffies and expect it to advance. | ||
630 | * | ||
631 | * Fortunately, udelay() uses %stick/%tick so we can use that. | ||
632 | */ | ||
633 | local_irq_save(flags); | ||
634 | |||
635 | this_cpu = smp_processor_id(); | 623 | this_cpu = smp_processor_id(); |
636 | tb = &trap_block[this_cpu]; | 624 | tb = &trap_block[this_cpu]; |
637 | 625 | ||
@@ -720,8 +708,6 @@ static void hypervisor_xcall_deliver(u64 data0, u64 data1, u64 data2, const cpum | |||
720 | } | 708 | } |
721 | } while (1); | 709 | } while (1); |
722 | 710 | ||
723 | local_irq_restore(flags); | ||
724 | |||
725 | if (unlikely(!cpus_empty(error_mask))) | 711 | if (unlikely(!cpus_empty(error_mask))) |
726 | goto fatal_mondo_cpu_error; | 712 | goto fatal_mondo_cpu_error; |
727 | 713 | ||
@@ -738,14 +724,12 @@ fatal_mondo_cpu_error: | |||
738 | return; | 724 | return; |
739 | 725 | ||
740 | fatal_mondo_timeout: | 726 | fatal_mondo_timeout: |
741 | local_irq_restore(flags); | ||
742 | printk(KERN_CRIT "CPU[%d]: SUN4V mondo timeout, no forward " | 727 | printk(KERN_CRIT "CPU[%d]: SUN4V mondo timeout, no forward " |
743 | " progress after %d retries.\n", | 728 | " progress after %d retries.\n", |
744 | this_cpu, retries); | 729 | this_cpu, retries); |
745 | goto dump_cpu_list_and_out; | 730 | goto dump_cpu_list_and_out; |
746 | 731 | ||
747 | fatal_mondo_error: | 732 | fatal_mondo_error: |
748 | local_irq_restore(flags); | ||
749 | printk(KERN_CRIT "CPU[%d]: Unexpected SUN4V mondo error %lu\n", | 733 | printk(KERN_CRIT "CPU[%d]: Unexpected SUN4V mondo error %lu\n", |
750 | this_cpu, status); | 734 | this_cpu, status); |
751 | printk(KERN_CRIT "CPU[%d]: Args were cnt(%d) cpulist_pa(%lx) " | 735 | printk(KERN_CRIT "CPU[%d]: Args were cnt(%d) cpulist_pa(%lx) " |
@@ -763,7 +747,21 @@ static void (*xcall_deliver_impl)(u64, u64, u64, const cpumask_t *); | |||
763 | 747 | ||
764 | static void xcall_deliver(u64 data0, u64 data1, u64 data2, const cpumask_t *mask) | 748 | static void xcall_deliver(u64 data0, u64 data1, u64 data2, const cpumask_t *mask) |
765 | { | 749 | { |
750 | unsigned long flags; | ||
751 | |||
752 | /* We have to do this whole thing with interrupts fully disabled. | ||
753 | * Otherwise if we send an xcall from interrupt context it will | ||
754 | * corrupt both our mondo block and cpu list state. | ||
755 | * | ||
756 | * One consequence of this is that we cannot use timeout mechanisms | ||
757 | * that depend upon interrupts being delivered locally. So, for | ||
758 | * example, we cannot sample jiffies and expect it to advance. | ||
759 | * | ||
760 | * Fortunately, udelay() uses %stick/%tick so we can use that. | ||
761 | */ | ||
762 | local_irq_save(flags); | ||
766 | xcall_deliver_impl(data0, data1, data2, mask); | 763 | xcall_deliver_impl(data0, data1, data2, mask); |
764 | local_irq_restore(flags); | ||
767 | } | 765 | } |
768 | 766 | ||
769 | /* Send cross call to all processors mentioned in MASK_P | 767 | /* Send cross call to all processors mentioned in MASK_P |