patch-2_6_7-vs1_9_1_12
[linux-2.6.git] / arch / sparc64 / kernel / smp.c
index 88fe647..64b8732 100644 (file)
@@ -547,15 +547,18 @@ retry:
 static void smp_cross_call_masked(unsigned long *func, u32 ctx, u64 data1, u64 data2, cpumask_t mask)
 {
        u64 data0 = (((u64)ctx)<<32 | (((u64)func) & 0xffffffff));
+       int this_cpu = get_cpu();
 
        cpus_and(mask, mask, cpu_online_map);
-       cpu_clear(smp_processor_id(), mask);
+       cpu_clear(this_cpu, mask);
 
        if (tlb_type == spitfire)
                spitfire_xcall_deliver(data0, data1, data2, mask);
        else
                cheetah_xcall_deliver(data0, data1, data2, mask);
        /* NOTE: Caller runs local copy on master. */
+
+       put_cpu();
 }
 
 extern unsigned long xcall_sync_tick;
@@ -598,6 +601,9 @@ int smp_call_function(void (*func)(void *info), void *info,
        if (!cpus)
                return 0;
 
+       /* Can deadlock when called with interrupts disabled */
+       WARN_ON(irqs_disabled());
+
        data.func = func;
        data.info = info;
        atomic_set(&data.finished, 0);
@@ -682,11 +688,12 @@ static __inline__ void __local_flush_dcache_page(struct page *page)
 void smp_flush_dcache_page_impl(struct page *page, int cpu)
 {
        cpumask_t mask = cpumask_of_cpu(cpu);
+       int this_cpu = get_cpu();
 
 #ifdef CONFIG_DEBUG_DCFLUSH
        atomic_inc(&dcpage_flushes);
 #endif
-       if (cpu == smp_processor_id()) {
+       if (cpu == this_cpu) {
                __local_flush_dcache_page(page);
        } else if (cpu_online(cpu)) {
                u64 data0;
@@ -711,14 +718,17 @@ void smp_flush_dcache_page_impl(struct page *page, int cpu)
                atomic_inc(&dcpage_flushes_xcall);
 #endif
        }
+
+       put_cpu();
 }
 
 void flush_dcache_page_all(struct mm_struct *mm, struct page *page)
 {
        cpumask_t mask = cpu_online_map;
        u64 data0;
+       int this_cpu = get_cpu();
 
-       cpu_clear(smp_processor_id(), mask);
+       cpu_clear(this_cpu, mask);
 
 #ifdef CONFIG_DEBUG_DCFLUSH
        atomic_inc(&dcpage_flushes);
@@ -744,6 +754,8 @@ void flush_dcache_page_all(struct mm_struct *mm, struct page *page)
 #endif
  flush_self:
        __local_flush_dcache_page(page);
+
+       put_cpu();
 }
 
 void smp_receive_signal(int cpu)
@@ -839,7 +851,7 @@ void smp_flush_tlb_mm(struct mm_struct *mm)
 
        {
                u32 ctx = CTX_HWBITS(mm->context);
-               int cpu = smp_processor_id();
+               int cpu = get_cpu();
 
                if (atomic_read(&mm->mm_users) == 1) {
                        /* See smp_flush_tlb_page for info about this. */
@@ -853,6 +865,8 @@ void smp_flush_tlb_mm(struct mm_struct *mm)
 
        local_flush_and_out:
                __flush_tlb_mm(ctx, SECONDARY_CONTEXT);
+
+               put_cpu();
        }
 }
 
@@ -860,7 +874,7 @@ void smp_flush_tlb_range(struct mm_struct *mm, unsigned long start,
                         unsigned long end)
 {
        u32 ctx = CTX_HWBITS(mm->context);
-       int cpu = smp_processor_id();
+       int cpu = get_cpu();
 
        start &= PAGE_MASK;
        end    = PAGE_ALIGN(end);
@@ -877,6 +891,8 @@ void smp_flush_tlb_range(struct mm_struct *mm, unsigned long start,
  local_flush_and_out:
        __flush_tlb_range(ctx, start, SECONDARY_CONTEXT,
                          end, PAGE_SIZE, (end-start));
+
+       put_cpu();
 }
 
 void smp_flush_tlb_kernel_range(unsigned long start, unsigned long end)
@@ -895,7 +911,7 @@ void smp_flush_tlb_page(struct mm_struct *mm, unsigned long page)
 {
        {
                u32 ctx = CTX_HWBITS(mm->context);
-               int cpu = smp_processor_id();
+               int cpu = get_cpu();
 
                page &= PAGE_MASK;
                if (mm == current->active_mm &&
@@ -935,6 +951,8 @@ void smp_flush_tlb_page(struct mm_struct *mm, unsigned long page)
 
        local_flush_and_out:
                __flush_tlb_page(ctx, page, SECONDARY_CONTEXT);
+
+               put_cpu();
        }
 }
 
@@ -1108,11 +1126,6 @@ void __init smp_tick_init(void)
        boot_cpu_id = hard_smp_processor_id();
        current_tick_offset = timer_tick_offset;
 
-       if (boot_cpu_id >= NR_CPUS) {
-               prom_printf("Serious problem, boot cpu id >= NR_CPUS\n");
-               prom_halt();
-       }
-
        cpu_set(boot_cpu_id, cpu_online_map);
        prof_counter(boot_cpu_id) = prof_multiplier(boot_cpu_id) = 1;
 }
@@ -1254,6 +1267,11 @@ void __init smp_prepare_cpus(unsigned int max_cpus)
 
 void __devinit smp_prepare_boot_cpu(void)
 {
+       if (hard_smp_processor_id() >= NR_CPUS) {
+               prom_printf("Serious problem, boot cpu id >= NR_CPUS\n");
+               prom_halt();
+       }
+
        current_thread_info()->cpu = hard_smp_processor_id();
        cpu_set(smp_processor_id(), cpu_online_map);
        cpu_set(smp_processor_id(), phys_cpu_present_map);