Commit d595d423 authored by Paul Burton's avatar Paul Burton Committed by Ralf Baechle

MIPS: SMP: Allow boot_secondary SMP op to return errors

Allow the boot_secondary SMP op to return an error to __cpu_up(), which
will in turn return it to its caller.

This will allow SMP implementations to return errors quickly in cases
they they know have failed, rather than relying upon __cpu_up()
eventually timing out waiting for the cpu_running completion.
Signed-off-by: default avatarPaul Burton <paul.burton@imgtec.com>
Cc: linux-mips@linux-mips.org
Patchwork: https://patchwork.linux-mips.org/patch/17014/Signed-off-by: default avatarRalf Baechle <ralf@linux-mips.org>
parent 68923cdc
...@@ -205,7 +205,7 @@ int plat_post_relocation(long offset) ...@@ -205,7 +205,7 @@ int plat_post_relocation(long offset)
* Firmware CPU startup hook * Firmware CPU startup hook
* *
*/ */
static void octeon_boot_secondary(int cpu, struct task_struct *idle) static int octeon_boot_secondary(int cpu, struct task_struct *idle)
{ {
int count; int count;
...@@ -223,8 +223,12 @@ static void octeon_boot_secondary(int cpu, struct task_struct *idle) ...@@ -223,8 +223,12 @@ static void octeon_boot_secondary(int cpu, struct task_struct *idle)
udelay(1); udelay(1);
count--; count--;
} }
if (count == 0) if (count == 0) {
pr_err("Secondary boot timeout\n"); pr_err("Secondary boot timeout\n");
return -ETIMEDOUT;
}
return 0;
} }
/** /**
......
...@@ -26,7 +26,7 @@ struct plat_smp_ops { ...@@ -26,7 +26,7 @@ struct plat_smp_ops {
void (*send_ipi_mask)(const struct cpumask *mask, unsigned int action); void (*send_ipi_mask)(const struct cpumask *mask, unsigned int action);
void (*init_secondary)(void); void (*init_secondary)(void);
void (*smp_finish)(void); void (*smp_finish)(void);
void (*boot_secondary)(int cpu, struct task_struct *idle); int (*boot_secondary)(int cpu, struct task_struct *idle);
void (*smp_setup)(void); void (*smp_setup)(void);
void (*prepare_cpus)(unsigned int max_cpus); void (*prepare_cpus)(unsigned int max_cpus);
#ifdef CONFIG_HOTPLUG_CPU #ifdef CONFIG_HOTPLUG_CPU
......
...@@ -179,7 +179,7 @@ static void bmips_prepare_cpus(unsigned int max_cpus) ...@@ -179,7 +179,7 @@ static void bmips_prepare_cpus(unsigned int max_cpus)
/* /*
* Tell the hardware to boot CPUx - runs on CPU0 * Tell the hardware to boot CPUx - runs on CPU0
*/ */
static void bmips_boot_secondary(int cpu, struct task_struct *idle) static int bmips_boot_secondary(int cpu, struct task_struct *idle)
{ {
bmips_smp_boot_sp = __KSTK_TOS(idle); bmips_smp_boot_sp = __KSTK_TOS(idle);
bmips_smp_boot_gp = (unsigned long)task_thread_info(idle); bmips_smp_boot_gp = (unsigned long)task_thread_info(idle);
...@@ -231,6 +231,8 @@ static void bmips_boot_secondary(int cpu, struct task_struct *idle) ...@@ -231,6 +231,8 @@ static void bmips_boot_secondary(int cpu, struct task_struct *idle)
} }
cpumask_set_cpu(cpu, &bmips_booted_mask); cpumask_set_cpu(cpu, &bmips_booted_mask);
} }
return 0;
} }
/* /*
......
...@@ -78,7 +78,7 @@ static void cmp_smp_finish(void) ...@@ -78,7 +78,7 @@ static void cmp_smp_finish(void)
* __KSTK_TOS(idle) is apparently the stack pointer * __KSTK_TOS(idle) is apparently the stack pointer
* (unsigned long)idle->thread_info the gp * (unsigned long)idle->thread_info the gp
*/ */
static void cmp_boot_secondary(int cpu, struct task_struct *idle) static int cmp_boot_secondary(int cpu, struct task_struct *idle)
{ {
struct thread_info *gp = task_thread_info(idle); struct thread_info *gp = task_thread_info(idle);
unsigned long sp = __KSTK_TOS(idle); unsigned long sp = __KSTK_TOS(idle);
...@@ -95,6 +95,7 @@ static void cmp_boot_secondary(int cpu, struct task_struct *idle) ...@@ -95,6 +95,7 @@ static void cmp_boot_secondary(int cpu, struct task_struct *idle)
#endif #endif
amon_cpu_start(cpu, pc, sp, (unsigned long)gp, a0); amon_cpu_start(cpu, pc, sp, (unsigned long)gp, a0);
return 0;
} }
/* /*
......
...@@ -288,7 +288,7 @@ static void remote_vpe_boot(void *dummy) ...@@ -288,7 +288,7 @@ static void remote_vpe_boot(void *dummy)
mips_cps_boot_vpes(core_cfg, cpu_vpe_id(&current_cpu_data)); mips_cps_boot_vpes(core_cfg, cpu_vpe_id(&current_cpu_data));
} }
static void cps_boot_secondary(int cpu, struct task_struct *idle) static int cps_boot_secondary(int cpu, struct task_struct *idle)
{ {
unsigned core = cpu_core(&cpu_data[cpu]); unsigned core = cpu_core(&cpu_data[cpu]);
unsigned vpe_id = cpu_vpe_id(&cpu_data[cpu]); unsigned vpe_id = cpu_vpe_id(&cpu_data[cpu]);
...@@ -346,6 +346,7 @@ static void cps_boot_secondary(int cpu, struct task_struct *idle) ...@@ -346,6 +346,7 @@ static void cps_boot_secondary(int cpu, struct task_struct *idle)
mips_cps_boot_vpes(core_cfg, vpe_id); mips_cps_boot_vpes(core_cfg, vpe_id);
out: out:
preempt_enable(); preempt_enable();
return 0;
} }
static void cps_init_secondary(void) static void cps_init_secondary(void)
......
...@@ -152,7 +152,7 @@ static void vsmp_smp_finish(void) ...@@ -152,7 +152,7 @@ static void vsmp_smp_finish(void)
* (unsigned long)idle->thread_info the gp * (unsigned long)idle->thread_info the gp
* assumes a 1:1 mapping of TC => VPE * assumes a 1:1 mapping of TC => VPE
*/ */
static void vsmp_boot_secondary(int cpu, struct task_struct *idle) static int vsmp_boot_secondary(int cpu, struct task_struct *idle)
{ {
struct thread_info *gp = task_thread_info(idle); struct thread_info *gp = task_thread_info(idle);
dvpe(); dvpe();
...@@ -184,6 +184,8 @@ static void vsmp_boot_secondary(int cpu, struct task_struct *idle) ...@@ -184,6 +184,8 @@ static void vsmp_boot_secondary(int cpu, struct task_struct *idle)
clear_c0_mvpcontrol(MVPCONTROL_VPC); clear_c0_mvpcontrol(MVPCONTROL_VPC);
evpe(EVPE_ENABLE); evpe(EVPE_ENABLE);
return 0;
} }
/* /*
......
...@@ -39,8 +39,9 @@ static void up_smp_finish(void) ...@@ -39,8 +39,9 @@ static void up_smp_finish(void)
/* /*
* Firmware CPU startup hook * Firmware CPU startup hook
*/ */
static void up_boot_secondary(int cpu, struct task_struct *idle) static int up_boot_secondary(int cpu, struct task_struct *idle)
{ {
return 0;
} }
static void __init up_smp_setup(void) static void __init up_smp_setup(void)
......
...@@ -439,7 +439,11 @@ void smp_prepare_boot_cpu(void) ...@@ -439,7 +439,11 @@ void smp_prepare_boot_cpu(void)
int __cpu_up(unsigned int cpu, struct task_struct *tidle) int __cpu_up(unsigned int cpu, struct task_struct *tidle)
{ {
mp_ops->boot_secondary(cpu, tidle); int err;
err = mp_ops->boot_secondary(cpu, tidle);
if (err)
return err;
/* /*
* We must check for timeout here, as the CPU will not be marked * We must check for timeout here, as the CPU will not be marked
......
...@@ -400,7 +400,7 @@ static void __init loongson3_prepare_cpus(unsigned int max_cpus) ...@@ -400,7 +400,7 @@ static void __init loongson3_prepare_cpus(unsigned int max_cpus)
/* /*
* Setup the PC, SP, and GP of a secondary processor and start it runing! * Setup the PC, SP, and GP of a secondary processor and start it runing!
*/ */
static void loongson3_boot_secondary(int cpu, struct task_struct *idle) static int loongson3_boot_secondary(int cpu, struct task_struct *idle)
{ {
unsigned long startargs[4]; unsigned long startargs[4];
...@@ -423,6 +423,7 @@ static void loongson3_boot_secondary(int cpu, struct task_struct *idle) ...@@ -423,6 +423,7 @@ static void loongson3_boot_secondary(int cpu, struct task_struct *idle)
(void *)(ipi_mailbox_buf[cpu_logical_map(cpu)]+0x8)); (void *)(ipi_mailbox_buf[cpu_logical_map(cpu)]+0x8));
loongson3_ipi_write64(startargs[0], loongson3_ipi_write64(startargs[0],
(void *)(ipi_mailbox_buf[cpu_logical_map(cpu)]+0x0)); (void *)(ipi_mailbox_buf[cpu_logical_map(cpu)]+0x0));
return 0;
} }
#ifdef CONFIG_HOTPLUG_CPU #ifdef CONFIG_HOTPLUG_CPU
......
...@@ -147,7 +147,7 @@ unsigned long nlm_next_gp; ...@@ -147,7 +147,7 @@ unsigned long nlm_next_gp;
unsigned long nlm_next_sp; unsigned long nlm_next_sp;
static cpumask_t phys_cpu_present_mask; static cpumask_t phys_cpu_present_mask;
void nlm_boot_secondary(int logical_cpu, struct task_struct *idle) int nlm_boot_secondary(int logical_cpu, struct task_struct *idle)
{ {
uint64_t picbase; uint64_t picbase;
int hwtid; int hwtid;
...@@ -161,6 +161,8 @@ void nlm_boot_secondary(int logical_cpu, struct task_struct *idle) ...@@ -161,6 +161,8 @@ void nlm_boot_secondary(int logical_cpu, struct task_struct *idle)
/* barrier for sp/gp store above */ /* barrier for sp/gp store above */
__sync(); __sync();
nlm_pic_send_ipi(picbase, hwtid, 1, 1); /* NMI */ nlm_pic_send_ipi(picbase, hwtid, 1, 1); /* NMI */
return 0;
} }
void __init nlm_smp_setup(void) void __init nlm_smp_setup(void)
......
...@@ -100,11 +100,12 @@ static void paravirt_smp_finish(void) ...@@ -100,11 +100,12 @@ static void paravirt_smp_finish(void)
local_irq_enable(); local_irq_enable();
} }
static void paravirt_boot_secondary(int cpu, struct task_struct *idle) static int paravirt_boot_secondary(int cpu, struct task_struct *idle)
{ {
paravirt_smp_gp[cpu] = (unsigned long)task_thread_info(idle); paravirt_smp_gp[cpu] = (unsigned long)task_thread_info(idle);
smp_wmb(); smp_wmb();
paravirt_smp_sp[cpu] = __KSTK_TOS(idle); paravirt_smp_sp[cpu] = __KSTK_TOS(idle);
return 0;
} }
static irqreturn_t paravirt_reched_interrupt(int irq, void *dev_id) static irqreturn_t paravirt_reched_interrupt(int irq, void *dev_id)
......
...@@ -195,7 +195,7 @@ static void ip27_smp_finish(void) ...@@ -195,7 +195,7 @@ static void ip27_smp_finish(void)
* set sp to the kernel stack of the newly created idle process, gp to the proc * set sp to the kernel stack of the newly created idle process, gp to the proc
* struct so that current_thread_info() will work. * struct so that current_thread_info() will work.
*/ */
static void ip27_boot_secondary(int cpu, struct task_struct *idle) static int ip27_boot_secondary(int cpu, struct task_struct *idle)
{ {
unsigned long gp = (unsigned long)task_thread_info(idle); unsigned long gp = (unsigned long)task_thread_info(idle);
unsigned long sp = __KSTK_TOS(idle); unsigned long sp = __KSTK_TOS(idle);
...@@ -203,6 +203,7 @@ static void ip27_boot_secondary(int cpu, struct task_struct *idle) ...@@ -203,6 +203,7 @@ static void ip27_boot_secondary(int cpu, struct task_struct *idle)
LAUNCH_SLAVE(cputonasid(cpu), cputoslice(cpu), LAUNCH_SLAVE(cputonasid(cpu), cputoslice(cpu),
(launch_proc_t)MAPPED_KERN_RW_TO_K0(smp_bootstrap), (launch_proc_t)MAPPED_KERN_RW_TO_K0(smp_bootstrap),
0, (void *) sp, (void *) gp); 0, (void *) sp, (void *) gp);
return 0;
} }
static void __init ip27_smp_setup(void) static void __init ip27_smp_setup(void)
......
...@@ -117,7 +117,7 @@ static void bcm1480_smp_finish(void) ...@@ -117,7 +117,7 @@ static void bcm1480_smp_finish(void)
* Setup the PC, SP, and GP of a secondary processor and start it * Setup the PC, SP, and GP of a secondary processor and start it
* running! * running!
*/ */
static void bcm1480_boot_secondary(int cpu, struct task_struct *idle) static int bcm1480_boot_secondary(int cpu, struct task_struct *idle)
{ {
int retval; int retval;
...@@ -126,6 +126,7 @@ static void bcm1480_boot_secondary(int cpu, struct task_struct *idle) ...@@ -126,6 +126,7 @@ static void bcm1480_boot_secondary(int cpu, struct task_struct *idle)
(unsigned long)task_thread_info(idle), 0); (unsigned long)task_thread_info(idle), 0);
if (retval != 0) if (retval != 0)
printk("cfe_start_cpu(%i) returned %i\n" , cpu, retval); printk("cfe_start_cpu(%i) returned %i\n" , cpu, retval);
return retval;
} }
/* /*
......
...@@ -106,7 +106,7 @@ static void sb1250_smp_finish(void) ...@@ -106,7 +106,7 @@ static void sb1250_smp_finish(void)
* Setup the PC, SP, and GP of a secondary processor and start it * Setup the PC, SP, and GP of a secondary processor and start it
* running! * running!
*/ */
static void sb1250_boot_secondary(int cpu, struct task_struct *idle) static int sb1250_boot_secondary(int cpu, struct task_struct *idle)
{ {
int retval; int retval;
...@@ -115,6 +115,7 @@ static void sb1250_boot_secondary(int cpu, struct task_struct *idle) ...@@ -115,6 +115,7 @@ static void sb1250_boot_secondary(int cpu, struct task_struct *idle)
(unsigned long)task_thread_info(idle), 0); (unsigned long)task_thread_info(idle), 0);
if (retval != 0) if (retval != 0)
printk("cfe_start_cpu(%i) returned %i\n" , cpu, retval); printk("cfe_start_cpu(%i) returned %i\n" , cpu, retval);
return retval;
} }
/* /*
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment