diff options
Diffstat (limited to 'arch/sparc/kernel/leon_smp.c')
| -rw-r--r-- | arch/sparc/kernel/leon_smp.c | 122 | 
1 files changed, 37 insertions, 85 deletions
diff --git a/arch/sparc/kernel/leon_smp.c b/arch/sparc/kernel/leon_smp.c index 160cac9c403..a469090faf9 100644 --- a/arch/sparc/kernel/leon_smp.c +++ b/arch/sparc/kernel/leon_smp.c @@ -24,6 +24,7 @@  #include <linux/delay.h>  #include <linux/gfp.h>  #include <linux/cpu.h> +#include <linux/clockchips.h>  #include <asm/cacheflush.h>  #include <asm/tlbflush.h> @@ -43,6 +44,7 @@  #include <asm/asi.h>  #include <asm/leon.h>  #include <asm/leon_amba.h> +#include <asm/timer.h>  #include "kernel.h" @@ -69,26 +71,24 @@ static inline unsigned long do_swap(volatile unsigned long *ptr,  	return val;  } -static void smp_setup_percpu_timer(void); -  void __cpuinit leon_callin(void)  { -	int cpuid = hard_smpleon_processor_id(); +	int cpuid = hard_smp_processor_id(); -	local_flush_cache_all(); -	local_flush_tlb_all(); +	local_ops->cache_all(); +	local_ops->tlb_all();  	leon_configure_cache_smp();  	notify_cpu_starting(cpuid);  	/* Get our local ticker going. */ -	smp_setup_percpu_timer(); +	register_percpu_ce(cpuid);  	calibrate_delay();  	smp_store_cpu_info(cpuid); -	local_flush_cache_all(); -	local_flush_tlb_all(); +	local_ops->cache_all(); +	local_ops->tlb_all();  	/*  	 * Unblock the master CPU _only_ when the scheduler state @@ -99,8 +99,8 @@ void __cpuinit leon_callin(void)  	 */  	do_swap(&cpu_callin_map[cpuid], 1); -	local_flush_cache_all(); -	local_flush_tlb_all(); +	local_ops->cache_all(); +	local_ops->tlb_all();  	/* Fix idle thread fields. */  	__asm__ __volatile__("ld [%0], %%g6\n\t" : : "r"(¤t_set[cpuid]) @@ -143,8 +143,8 @@ void __init leon_configure_cache_smp(void)  		}  	} -	local_flush_cache_all(); -	local_flush_tlb_all(); +	local_ops->cache_all(); +	local_ops->tlb_all();  }  void leon_smp_setbroadcast(unsigned int mask) @@ -199,21 +199,15 @@ void __init leon_boot_cpus(void)  	leon_smp_setbroadcast(1 << LEON3_IRQ_TICKER);  	leon_configure_cache_smp(); -	smp_setup_percpu_timer(); -	local_flush_cache_all(); +	local_ops->cache_all();  } -int __cpuinit leon_boot_one_cpu(int i) +int __cpuinit leon_boot_one_cpu(int i, struct task_struct *idle)  { - -	struct task_struct *p;  	int timeout; -	/* Cook up an idler for this guy. */ -	p = fork_idle(i); - -	current_set[i] = task_thread_info(p); +	current_set[i] = task_thread_info(idle);  	/* See trampoline.S:leon_smp_cpu_startup for details...  	 * Initialize the contexts table @@ -227,7 +221,7 @@ int __cpuinit leon_boot_one_cpu(int i)  	/* whirrr, whirrr, whirrrrrrrrr... */  	printk(KERN_INFO "Starting CPU %d : (irqmp: 0x%x)\n", (unsigned int)i,  	       (unsigned int)&leon3_irqctrl_regs->mpstatus); -	local_flush_cache_all(); +	local_ops->cache_all();  	/* Make sure all IRQs are of from the start for this new CPU */  	LEON_BYPASS_STORE_PA(&leon3_irqctrl_regs->mask[i], 0); @@ -252,7 +246,7 @@ int __cpuinit leon_boot_one_cpu(int i)  		leon_enable_irq_cpu(leon_ipi_irq, i);  	} -	local_flush_cache_all(); +	local_ops->cache_all();  	return 0;  } @@ -272,7 +266,7 @@ void __init leon_smp_done(void)  		}  	}  	*prev = first; -	local_flush_cache_all(); +	local_ops->cache_all();  	/* Free unneeded trap tables */  	if (!cpu_present(1)) { @@ -338,7 +332,7 @@ static void __init leon_ipi_init(void)  	local_irq_save(flags);  	trap_table = &sparc_ttable[SP_TRAP_IRQ1 + (leon_ipi_irq - 1)];  	trap_table->inst_three += smpleon_ipi - real_irq_entry; -	local_flush_cache_all(); +	local_ops->cache_all();  	local_irq_restore(flags);  	for_each_possible_cpu(cpu) { @@ -347,6 +341,13 @@ static void __init leon_ipi_init(void)  	}  } +static void leon_send_ipi(int cpu, int level) +{ +	unsigned long mask; +	mask = leon_get_irqmask(level); +	LEON3_BYPASS_STORE_PA(&leon3_irqctrl_regs->force[cpu], mask); +} +  static void leon_ipi_single(int cpu)  {  	struct leon_ipi_work *work = &per_cpu(leon_ipi_work, cpu); @@ -355,7 +356,7 @@ static void leon_ipi_single(int cpu)  	work->single = 1;  	/* Generate IRQ on the CPU */ -	set_cpu_int(cpu, leon_ipi_irq); +	leon_send_ipi(cpu, leon_ipi_irq);  }  static void leon_ipi_mask_one(int cpu) @@ -366,7 +367,7 @@ static void leon_ipi_mask_one(int cpu)  	work->msk = 1;  	/* Generate IRQ on the CPU */ -	set_cpu_int(cpu, leon_ipi_irq); +	leon_send_ipi(cpu, leon_ipi_irq);  }  static void leon_ipi_resched(int cpu) @@ -377,7 +378,7 @@ static void leon_ipi_resched(int cpu)  	work->resched = 1;  	/* Generate IRQ on the CPU (any IRQ will cause resched) */ -	set_cpu_int(cpu, leon_ipi_irq); +	leon_send_ipi(cpu, leon_ipi_irq);  }  void leonsmp_ipi_interrupt(void) @@ -449,7 +450,7 @@ static void leon_cross_call(smpfunc_t func, cpumask_t mask, unsigned long arg1,  				if (cpumask_test_cpu(i, &mask)) {  					ccall_info.processors_in[i] = 0;  					ccall_info.processors_out[i] = 0; -					set_cpu_int(i, LEON3_IRQ_CROSS_CALL); +					leon_send_ipi(i, LEON3_IRQ_CROSS_CALL);  				}  			} @@ -492,68 +493,19 @@ void leon_cross_call_irq(void)  	ccall_info.processors_out[i] = 1;  } -irqreturn_t leon_percpu_timer_interrupt(int irq, void *unused) -{ -	int cpu = smp_processor_id(); - -	leon_clear_profile_irq(cpu); - -	profile_tick(CPU_PROFILING); - -	if (!--prof_counter(cpu)) { -		int user = user_mode(get_irq_regs()); - -		update_process_times(user); - -		prof_counter(cpu) = prof_multiplier(cpu); -	} - -	return IRQ_HANDLED; -} - -static void __init smp_setup_percpu_timer(void) -{ -	int cpu = smp_processor_id(); - -	prof_counter(cpu) = prof_multiplier(cpu) = 1; -} - -void __init leon_blackbox_id(unsigned *addr) -{ -	int rd = *addr & 0x3e000000; -	int rs1 = rd >> 11; - -	/* patch places where ___b_hard_smp_processor_id appears */ -	addr[0] = 0x81444000 | rd;	/* rd %asr17, reg */ -	addr[1] = 0x8130201c | rd | rs1;	/* srl reg, 0x1c, reg */ -	addr[2] = 0x01000000;	/* nop */ -} - -void __init leon_blackbox_current(unsigned *addr) -{ -	int rd = *addr & 0x3e000000; -	int rs1 = rd >> 11; - -	/* patch LOAD_CURRENT macro where ___b_load_current appears */ -	addr[0] = 0x81444000 | rd;	/* rd %asr17, reg */ -	addr[2] = 0x8130201c | rd | rs1;	/* srl reg, 0x1c, reg */ -	addr[4] = 0x81282002 | rd | rs1;	/* sll reg, 0x2, reg */ - -} +static const struct sparc32_ipi_ops leon_ipi_ops = { +	.cross_call = leon_cross_call, +	.resched    = leon_ipi_resched, +	.single     = leon_ipi_single, +	.mask_one   = leon_ipi_mask_one, +};  void __init leon_init_smp(void)  {  	/* Patch ipi15 trap table */  	t_nmi[1] = t_nmi[1] + (linux_trap_ipi15_leon - linux_trap_ipi15_sun4m); -	BTFIXUPSET_BLACKBOX(hard_smp_processor_id, leon_blackbox_id); -	BTFIXUPSET_BLACKBOX(load_current, leon_blackbox_current); -	BTFIXUPSET_CALL(smp_cross_call, leon_cross_call, BTFIXUPCALL_NORM); -	BTFIXUPSET_CALL(__hard_smp_processor_id, __leon_processor_id, -			BTFIXUPCALL_NORM); -	BTFIXUPSET_CALL(smp_ipi_resched, leon_ipi_resched, BTFIXUPCALL_NORM); -	BTFIXUPSET_CALL(smp_ipi_single, leon_ipi_single, BTFIXUPCALL_NORM); -	BTFIXUPSET_CALL(smp_ipi_mask_one, leon_ipi_mask_one, BTFIXUPCALL_NORM); +	sparc32_ipi_ops = &leon_ipi_ops;  }  #endif /* CONFIG_SPARC_LEON */  |