diff --git a/arch/arc/include/asm/smp.h b/arch/arc/include/asm/smp.h index 0cff3a5481360ba440e221719378828eae9ed538..c4fb211dcd25bef135c78ea0683e71d9259a8c20 100644 --- a/arch/arc/include/asm/smp.h +++ b/arch/arc/include/asm/smp.h @@ -31,6 +31,7 @@ extern void arch_send_call_function_ipi_mask(const struct cpumask *mask); */ extern void __init smp_init_cpus(void); extern void __init first_lines_of_secondary(void); +extern const char *arc_platform_smp_cpuinfo(void); /* * API expected BY platform smp code (FROM arch smp code) @@ -41,29 +42,22 @@ extern void __init first_lines_of_secondary(void); extern int smp_ipi_irq_setup(int cpu, int irq); /* - * APIs expected FROM platform smp code - * - * arc_platform_smp_cpuinfo: - * returns a string containing info for /proc/cpuinfo - * - * arc_platform_smp_wait_to_boot: - * Called from early bootup code for non-Master CPUs to "park" them + * struct plat_smp_ops - SMP callbacks provided by platform to ARC SMP * - * arc_platform_smp_wakeup_cpu: - * Called from __cpu_up (Master CPU) to kick start another one - * - * arc_platform_ipi_send: - * Takes @cpumask to which IPI(s) would be sent. - * The actual msg-id/buffer is manager in arch-common code - * - * arc_platform_ipi_clear: - * Takes @cpu which got IPI at @irq to do any IPI clearing + * @info: SoC SMP specific info for /proc/cpuinfo etc + * @cpu_kick: For Master to kickstart a cpu (optionally at a PC) + * @ipi_send: To send IPI to a @cpumask + * @ips_clear: To clear IPI received by @cpu at @irq */ -extern const char *arc_platform_smp_cpuinfo(void); -extern void arc_platform_smp_wait_to_boot(int cpu); -extern void arc_platform_smp_wakeup_cpu(int cpu, unsigned long pc); -extern void arc_platform_ipi_send(const struct cpumask *callmap); -extern void arc_platform_ipi_clear(int cpu, int irq); +struct plat_smp_ops { + const char *info; + void (*cpu_kick)(int cpu, unsigned long pc); + void (*ipi_send)(void *callmap); + void (*ipi_clear)(int cpu, int irq); +}; + +/* TBD: stop exporting it for direct population by platform */ +extern struct plat_smp_ops plat_smp_ops; #endif /* CONFIG_SMP */ diff --git a/arch/arc/kernel/smp.c b/arch/arc/kernel/smp.c index 8ee010fdbc1834f7864053f03591fc137ef13f84..3af3e06dcf028cc75b3998560ea58da37fb0bb85 100644 --- a/arch/arc/kernel/smp.c +++ b/arch/arc/kernel/smp.c @@ -37,6 +37,8 @@ arch_spinlock_t smp_atomic_ops_lock = __ARCH_SPIN_LOCK_UNLOCKED; arch_spinlock_t smp_bitops_lock = __ARCH_SPIN_LOCK_UNLOCKED; +struct plat_smp_ops plat_smp_ops; + /* XXX: per cpu ? Only needed once in early seconday boot */ struct task_struct *secondary_idle_tsk; @@ -105,6 +107,11 @@ void __attribute__((weak)) arc_platform_smp_wait_to_boot(int cpu) " b 1b \n"); } +const char *arc_platform_smp_cpuinfo(void) +{ + return plat_smp_ops.info; +} + /* * The very first "C" code executed by secondary * Called from asm stub in head.S @@ -156,7 +163,8 @@ int __cpuinit __cpu_up(unsigned int cpu, struct task_struct *idle) pr_info("Idle Task [%d] %p", cpu, idle); pr_info("Trying to bring up CPU%u ...\n", cpu); - arc_platform_smp_wakeup_cpu(cpu, + if (plat_smp_ops.cpu_kick) + plat_smp_ops.cpu_kick(cpu, (unsigned long)first_lines_of_secondary); /* wait for 1 sec after kicking the secondary */ @@ -225,7 +233,8 @@ static void ipi_send_msg(const struct cpumask *callmap, enum ipi_msg_type msg) } /* Call the platform specific cross-CPU call function */ - arc_platform_ipi_send(callmap); + if (plat_smp_ops.ipi_send) + plat_smp_ops.ipi_send((void *)callmap); local_irq_restore(flags); } @@ -299,7 +308,8 @@ irqreturn_t do_IPI(int irq, void *dev_id) struct ipi_data *ipi = &per_cpu(ipi_data, cpu); unsigned long ops; - arc_platform_ipi_clear(cpu, irq); + if (plat_smp_ops.ipi_clear) + plat_smp_ops.ipi_clear(cpu, irq); /* * XXX: is this loop really needed