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: Paul Burton <paul.burton@imgtec.com> Cc: linux-mips@linux-mips.org Patchwork: https://patchwork.linux-mips.org/patch/17014/ Signed-off-by: Ralf Baechle <ralf@linux-mips.org>
This commit is contained in:
parent
68923cdc2e
commit
d595d423d0
@ -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)
|
|||||||
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 {
|
|||||||
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)
|
|||||||
/*
|
/*
|
||||||
* 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)
|
|||||||
}
|
}
|
||||||
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)
|
|||||||
* __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)
|
|||||||
#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)
|
|||||||
mips_cps_boot_vpes(core_cfg, cpu_vpe_id(¤t_cpu_data));
|
mips_cps_boot_vpes(core_cfg, cpu_vpe_id(¤t_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)
|
|||||||
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)
|
|||||||
* (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)
|
|||||||
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)
|
|||||||
/*
|
/*
|
||||||
* 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)
|
|||||||
|
|
||||||
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)
|
|||||||
/*
|
/*
|
||||||
* 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)
|
|||||||
(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;
|
|||||||
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)
|
|||||||
/* 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)
|
|||||||
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)
|
|||||||
* 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)
|
|||||||
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)
|
|||||||
* 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)
|
|||||||
(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)
|
|||||||
* 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)
|
|||||||
(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;
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
|
Loading…
Reference in New Issue
Block a user