X-Git-Url: http://git.onelab.eu/?a=blobdiff_plain;ds=sidebyside;f=arch%2Fsparc64%2Fkernel%2Fsmp.c;h=64b873212243f7d6adfa8d62db5a15779c7602c9;hb=9213980e6a70d8473e0ffd4b39ab5b6caaba9ff5;hp=88fe647652f48700ef001925510304f1a7016e57;hpb=c449269f45c2cdf53af08c8d0af37472f66539d9;p=linux-2.6.git diff --git a/arch/sparc64/kernel/smp.c b/arch/sparc64/kernel/smp.c index 88fe64765..64b873212 100644 --- a/arch/sparc64/kernel/smp.c +++ b/arch/sparc64/kernel/smp.c @@ -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);