diff options
Diffstat (limited to 'arch/powerpc/platforms/pseries/smp.c')
| -rw-r--r-- | arch/powerpc/platforms/pseries/smp.c | 33 | 
1 files changed, 31 insertions, 2 deletions
diff --git a/arch/powerpc/platforms/pseries/smp.c b/arch/powerpc/platforms/pseries/smp.c index 80cd0be71e0..12bc8c3663a 100644 --- a/arch/powerpc/platforms/pseries/smp.c +++ b/arch/powerpc/platforms/pseries/smp.c @@ -42,6 +42,7 @@  #include <asm/vdso_datapage.h>  #include <asm/cputhreads.h>  #include <asm/xics.h> +#include <asm/dbell.h>  #include "plpar_wrappers.h"  #include "pseries.h" @@ -54,6 +55,11 @@   */  static cpumask_var_t of_spin_mask; +/* + * If we multiplex IPI mechanisms, store the appropriate XICS IPI mechanism here + */ +static void  (*xics_cause_ipi)(int cpu, unsigned long data); +  /* Query where a cpu is now.  Return codes #defined in plpar_wrappers.h */  int smp_query_cpu_stopped(unsigned int pcpu)  { @@ -137,6 +143,8 @@ static void smp_xics_setup_cpu(int cpu)  {  	if (cpu != boot_cpuid)  		xics_setup_cpu(); +	if (cpu_has_feature(CPU_FTR_DBELL)) +		doorbell_setup_this_cpu();  	if (firmware_has_feature(FW_FEATURE_SPLPAR))  		vpa_init(cpu); @@ -195,6 +203,27 @@ static int smp_pSeries_cpu_bootable(unsigned int nr)  	return 1;  } +/* Only used on systems that support multiple IPI mechanisms */ +static void pSeries_cause_ipi_mux(int cpu, unsigned long data) +{ +	if (cpumask_test_cpu(cpu, cpu_sibling_mask(smp_processor_id()))) +		doorbell_cause_ipi(cpu, data); +	else +		xics_cause_ipi(cpu, data); +} + +static __init int pSeries_smp_probe(void) +{ +	int ret = xics_smp_probe(); + +	if (cpu_has_feature(CPU_FTR_DBELL)) { +		xics_cause_ipi = smp_ops->cause_ipi; +		smp_ops->cause_ipi = pSeries_cause_ipi_mux; +	} + +	return ret; +} +  static struct smp_ops_t pSeries_mpic_smp_ops = {  	.message_pass	= smp_mpic_message_pass,  	.probe		= smp_mpic_probe, @@ -204,8 +233,8 @@ static struct smp_ops_t pSeries_mpic_smp_ops = {  static struct smp_ops_t pSeries_xics_smp_ops = {  	.message_pass	= NULL,	/* Use smp_muxed_ipi_message_pass */ -	.cause_ipi	= NULL,	/* Filled at runtime by xics_smp_probe() */ -	.probe		= xics_smp_probe, +	.cause_ipi	= NULL,	/* Filled at runtime by pSeries_smp_probe() */ +	.probe		= pSeries_smp_probe,  	.kick_cpu	= smp_pSeries_kick_cpu,  	.setup_cpu	= smp_xics_setup_cpu,  	.cpu_bootable	= smp_pSeries_cpu_bootable,  |