diff options
Diffstat (limited to 'arch/powerpc/sysdev/mpic.c')
| -rw-r--r-- | arch/powerpc/sysdev/mpic.c | 42 | 
1 files changed, 35 insertions, 7 deletions
diff --git a/arch/powerpc/sysdev/mpic.c b/arch/powerpc/sysdev/mpic.c index 3b2efd41abf..ee21b5e71ae 100644 --- a/arch/powerpc/sysdev/mpic.c +++ b/arch/powerpc/sysdev/mpic.c @@ -54,7 +54,7 @@ static DEFINE_RAW_SPINLOCK(mpic_lock);  #ifdef CONFIG_PPC32	/* XXX for now */  #ifdef CONFIG_IRQ_ALL_CPUS -#define distribute_irqs	(1) +#define distribute_irqs	(!(mpic->flags & MPIC_SINGLE_DEST_CPU))  #else  #define distribute_irqs	(0)  #endif @@ -1001,8 +1001,12 @@ static int mpic_host_map(struct irq_domain *h, unsigned int virq,  	if (hw == mpic->spurious_vec)  		return -EINVAL; -	if (mpic->protected && test_bit(hw, mpic->protected)) -		return -EINVAL; +	if (mpic->protected && test_bit(hw, mpic->protected)) { +		pr_warning("mpic: Mapping of source 0x%x failed, " +			   "source protected by firmware !\n",\ +			   (unsigned int)hw); +		return -EPERM; +	}  #ifdef CONFIG_SMP  	else if (hw >= mpic->ipi_vecs[0]) { @@ -1029,8 +1033,12 @@ static int mpic_host_map(struct irq_domain *h, unsigned int virq,  	if (mpic_map_error_int(mpic, virq, hw))  		return 0; -	if (hw >= mpic->num_sources) +	if (hw >= mpic->num_sources) { +		pr_warning("mpic: Mapping of source 0x%x failed, " +			   "source out of range !\n",\ +			   (unsigned int)hw);  		return -EINVAL; +	}  	mpic_msi_reserve_hwirq(mpic, hw); @@ -1182,6 +1190,7 @@ struct mpic * __init mpic_alloc(struct device_node *node,  	const char *vers;  	const u32 *psrc;  	u32 last_irq; +	u32 fsl_version = 0;  	/* Default MPIC search parameters */  	static const struct of_device_id __initconst mpic_device_id[] = { @@ -1314,7 +1323,7 @@ struct mpic * __init mpic_alloc(struct device_node *node,  	mpic_map(mpic, mpic->paddr, &mpic->tmregs, MPIC_INFO(TIMER_BASE), 0x1000);  	if (mpic->flags & MPIC_FSL) { -		u32 brr1, version; +		u32 brr1;  		int ret;  		/* @@ -1327,7 +1336,7 @@ struct mpic * __init mpic_alloc(struct device_node *node,  		brr1 = _mpic_read(mpic->reg_type, &mpic->thiscpuregs,  				MPIC_FSL_BRR1); -		version = brr1 & MPIC_FSL_BRR1_VER; +		fsl_version = brr1 & MPIC_FSL_BRR1_VER;  		/* Error interrupt mask register (EIMR) is required for  		 * handling individual device error interrupts. EIMR @@ -1342,11 +1351,30 @@ struct mpic * __init mpic_alloc(struct device_node *node,  		 * is the number of vectors which have been consumed by  		 * ipis and timer interrupts.  		 */ -		if (version >= 0x401) { +		if (fsl_version >= 0x401) {  			ret = mpic_setup_error_int(mpic, intvec_top - 12);  			if (ret)  				return NULL;  		} + +	} + +	/* +	 * EPR is only available starting with v4.0.  To support +	 * platforms that don't know the MPIC version at compile-time, +	 * such as qemu-e500, turn off coreint if this MPIC doesn't +	 * support it.  Note that we never enable it if it wasn't +	 * requested in the first place. +	 * +	 * This is done outside the MPIC_FSL check, so that we +	 * also disable coreint if the MPIC node doesn't have +	 * an "fsl,mpic" compatible at all.  This will be the case +	 * with device trees generated by older versions of QEMU. +	 * fsl_version will be zero if MPIC_FSL is not set. +	 */ +	if (fsl_version < 0x400 && (flags & MPIC_ENABLE_COREINT)) { +		WARN_ON(ppc_md.get_irq != mpic_get_coreint_irq); +		ppc_md.get_irq = mpic_get_irq;  	}  	/* Reset */  |