Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit f9fd3488 authored by Sam Ravnborg's avatar Sam Ravnborg Committed by David S. Miller
Browse files

sparc32: refactor smp boot



Introduce a common smp_callin() function to call
from trampoline_32.S.
Add platform specific functions to handle the
platform details.

This is in preparation for a patch that will
unify the smp boot stuff for all architectures.
sparc32 was significantly different to warrant
this patch in preparation.

Signed-off-by: default avatarSam Ravnborg <sam@ravnborg.org>
Acked-by: default avatarDavid S. Miller <davem@davemloft.net>
Cc: "Srivatsa S. Bhat" <srivatsa.bhat@linux.vnet.ibm.com>
Acked-by: default avatarSrivatsa S. Bhat <srivatsa.bhat@linux.vnet.ibm.com>
Signed-off-by: default avatarDavid S. Miller <davem@davemloft.net>
parent 76968ad2
Loading
Loading
Loading
Loading
+12 −0
Original line number Diff line number Diff line
@@ -48,6 +48,10 @@ extern void sun4m_init_IRQ(void);
extern void sun4m_unmask_profile_irq(void);
extern void sun4m_clear_profile_irq(int cpu);

/* sun4m_smp.c */
void sun4m_cpu_pre_starting(void *arg);
void sun4m_cpu_pre_online(void *arg);

/* sun4d_irq.c */
extern spinlock_t sun4d_imsk_lock;

@@ -60,6 +64,14 @@ extern int show_sun4d_interrupts(struct seq_file *, void *);
extern void sun4d_distribute_irqs(void);
extern void sun4d_free_irq(unsigned int irq, void *dev_id);

/* sun4d_smp.c */
void sun4d_cpu_pre_starting(void *arg);
void sun4d_cpu_pre_online(void *arg);

/* leon_smp.c */
void leon_cpu_pre_starting(void *arg);
void leon_cpu_pre_online(void *arg);

/* head_32.S */
extern unsigned int t_nmi[];
extern unsigned int linux_trap_ipi15_sun4d[];
+9 −24
Original line number Diff line number Diff line
@@ -69,31 +69,19 @@ static inline unsigned long do_swap(volatile unsigned long *ptr,
	return val;
}

void __cpuinit leon_callin(void)
void __cpuinit leon_cpu_pre_starting(void *arg)
{
	int cpuid = hard_smp_processor_id();

	local_ops->cache_all();
	local_ops->tlb_all();
	leon_configure_cache_smp();
}

	notify_cpu_starting(cpuid);

	/* Get our local ticker going. */
	register_percpu_ce(cpuid);

	calibrate_delay();
	smp_store_cpu_info(cpuid);

	local_ops->cache_all();
	local_ops->tlb_all();
void __cpuinit leon_cpu_pre_online(void *arg)
{
	int cpuid = hard_smp_processor_id();

	/*
	 * Unblock the master CPU _only_ when the scheduler state
	 * of all secondary CPUs will be up-to-date, so after
	 * the SMP initialization the master will be just allowed
	 * to call the scheduler code.
	 * Allow master to continue.
	/* Allow master to continue. The master will then give us the
	 * go-ahead by setting the smp_commenced_mask and will wait without
	 * timeouts until our setup is completed fully (signified by
	 * our bit being set in the cpu_online_mask).
	 */
	do_swap(&cpu_callin_map[cpuid], 1);

@@ -110,9 +98,6 @@ void __cpuinit leon_callin(void)

	while (!cpumask_test_cpu(cpuid, &smp_commenced_mask))
		mb();

	local_irq_enable();
	set_cpu_online(cpuid, true);
}

/*
+86 −0
Original line number Diff line number Diff line
@@ -20,6 +20,7 @@
#include <linux/seq_file.h>
#include <linux/cache.h>
#include <linux/delay.h>
#include <linux/cpu.h>

#include <asm/ptrace.h>
#include <linux/atomic.h>
@@ -32,8 +33,10 @@
#include <asm/cacheflush.h>
#include <asm/tlbflush.h>
#include <asm/cpudata.h>
#include <asm/timer.h>
#include <asm/leon.h>

#include "kernel.h"
#include "irq.h"

volatile unsigned long cpu_callin_map[NR_CPUS] __cpuinitdata = {0,};
@@ -294,6 +297,89 @@ int __cpuinit __cpu_up(unsigned int cpu, struct task_struct *tidle)
	return ret;
}

void __cpuinit arch_cpu_pre_starting(void *arg)
{
	local_ops->cache_all();
	local_ops->tlb_all();

	switch(sparc_cpu_model) {
	case sun4m:
		sun4m_cpu_pre_starting(arg);
		break;
	case sun4d:
		sun4d_cpu_pre_starting(arg);
		break;
	case sparc_leon:
		leon_cpu_pre_starting(arg);
		break;
	default:
		BUG();
	}
}

void __cpuinit arch_cpu_pre_online(void *arg)
{
	unsigned int cpuid = hard_smp_processor_id();

	register_percpu_ce(cpuid);

	calibrate_delay();
	smp_store_cpu_info(cpuid);

	local_ops->cache_all();
	local_ops->tlb_all();

	switch(sparc_cpu_model) {
	case sun4m:
		sun4m_cpu_pre_online(arg);
		break;
	case sun4d:
		sun4d_cpu_pre_online(arg);
		break;
	case sparc_leon:
		leon_cpu_pre_online(arg);
		break;
	default:
		BUG();
	}
}

void __cpuinit sparc_start_secondary(void *arg)
{
	unsigned int cpu;

	/*
	 * SMP booting is extremely fragile in some architectures. So run
	 * the cpu initialization code first before anything else.
	 */
	arch_cpu_pre_starting(arg);

	preempt_disable();
	cpu = smp_processor_id();

	/* Invoke the CPU_STARTING notifier callbacks */
	notify_cpu_starting(cpu);

	arch_cpu_pre_online(arg);

	/* Set the CPU in the cpu_online_mask */
	set_cpu_online(cpu, true);

	/* Enable local interrupts now */
	local_irq_enable();

	wmb();
	cpu_idle();

	/* We should never reach here! */
	BUG();
}

void __cpuinit smp_callin(void)
{
	sparc_start_secondary(NULL);
}

void smp_bogo(struct seq_file *m)
{
	int i;
+9 −20
Original line number Diff line number Diff line
@@ -50,10 +50,9 @@ static inline void show_leds(int cpuid)
			      "i" (ASI_M_CTL));
}

void __cpuinit smp4d_callin(void)
void __cpuinit sun4d_cpu_pre_starting(void *arg)
{
	int cpuid = hard_smp_processor_id();
	unsigned long flags;

	/* Show we are alive */
	cpu_leds[cpuid] = 0x6;
@@ -61,26 +60,20 @@ void __cpuinit smp4d_callin(void)

	/* Enable level15 interrupt, disable level14 interrupt for now */
	cc_set_imsk((cc_get_imsk() & ~0x8000) | 0x4000);
}

	local_ops->cache_all();
	local_ops->tlb_all();
void __cpuinit sun4d_cpu_pre_online(void *arg)
{
	unsigned long flags;
	int cpuid;

	notify_cpu_starting(cpuid);
	/*
	 * Unblock the master CPU _only_ when the scheduler state
	cpuid = hard_smp_processor_id();

	/* Unblock the master CPU _only_ when the scheduler state
	 * of all secondary CPUs will be up-to-date, so after
	 * the SMP initialization the master will be just allowed
	 * to call the scheduler code.
	 */
	/* Get our local ticker going. */
	register_percpu_ce(cpuid);

	calibrate_delay();
	smp_store_cpu_info(cpuid);
	local_ops->cache_all();
	local_ops->tlb_all();

	/* Allow master to continue. */
	sun4d_swap((unsigned long *)&cpu_callin_map[cpuid], 1);
	local_ops->cache_all();
	local_ops->tlb_all();
@@ -106,16 +99,12 @@ void __cpuinit smp4d_callin(void)
	local_ops->cache_all();
	local_ops->tlb_all();

	local_irq_enable();	/* We don't allow PIL 14 yet */

	while (!cpumask_test_cpu(cpuid, &smp_commenced_mask))
		barrier();

	spin_lock_irqsave(&sun4d_imsk_lock, flags);
	cc_set_imsk(cc_get_imsk() & ~0x4000); /* Allow PIL 14 as well */
	spin_unlock_irqrestore(&sun4d_imsk_lock, flags);
	set_cpu_online(cpuid, true);

}

/*
+9 −24
Original line number Diff line number Diff line
@@ -34,30 +34,19 @@ swap_ulong(volatile unsigned long *ptr, unsigned long val)
	return val;
}

void __cpuinit smp4m_callin(void)
void __cpuinit sun4m_cpu_pre_starting(void *arg)
{
	int cpuid = hard_smp_processor_id();

	local_ops->cache_all();
	local_ops->tlb_all();

	notify_cpu_starting(cpuid);

	register_percpu_ce(cpuid);

	calibrate_delay();
	smp_store_cpu_info(cpuid);
}

	local_ops->cache_all();
	local_ops->tlb_all();
void __cpuinit sun4m_cpu_pre_online(void *arg)
{
	int cpuid = hard_smp_processor_id();

	/*
	 * Unblock the master CPU _only_ when the scheduler state
	 * of all secondary CPUs will be up-to-date, so after
	 * the SMP initialization the master will be just allowed
	 * to call the scheduler code.
	/* Allow master to continue. The master will then give us the
	 * go-ahead by setting the smp_commenced_mask and will wait without
	 * timeouts until our setup is completed fully (signified by
	 * our bit being set in the cpu_online_mask).
	 */
	/* Allow master to continue. */
	swap_ulong(&cpu_callin_map[cpuid], 1);

	/* XXX: What's up with all the flushes? */
@@ -75,10 +64,6 @@ void __cpuinit smp4m_callin(void)

	while (!cpumask_test_cpu(cpuid, &smp_commenced_mask))
		mb();

	local_irq_enable();

	set_cpu_online(cpuid, true);
}

/*
Loading