[PATCH 4/4] powerpc/mpic: FSL MPIC error interrupt support.

Kumar Gala galak at kernel.crashing.org
Thu Mar 29 01:35:13 EST 2012


On Mar 27, 2012, at 2:07 PM, Scott Wood wrote:

> On 03/27/2012 08:59 AM, Kumar Gala wrote:
>> 
>> On Mar 27, 2012, at 7:17 AM, Varun Sethi wrote:
>> 
>>> All SOC device error interrupts are muxed and delivered to the core as a single
>>> MPIC error interrupt. Currently all the device drivers requiring access to device
>>> errors have to register for the MPIC error interrupt as a shared interrupt.
>>> 
>>> With this patch we add interrupt demuxing capability in the mpic driver, allowing
>>> device drivers to register for their individual error interrupts. This is achieved
>>> by handling error interrupts in a cascaded fashion.
>>> 
>>> MPIC error interrupt is handled by the "error_int_handler", which subsequently demuxes
>>> it using the EISR and delivers it to the respective drivers. 
>>> 
>>> The error interrupt capability is dependent on the MPIC EIMR register, which was
>>> introduced in FSL MPIC version 4.1 (P4080 rev2). So, error interrupt demuxing capability
>>> is dependent on the MPIC version and can be used for versions >= 4.1.
>>> 
>>> Signed-off-by: Varun Sethi <Varun.Sethi at freescale.com>
>>> ---
>> 
>> This isn't quite right.  Doing the 'request_irq' on behalf of the driver isn't treating the error interrupts as a real cascade, in addition to how you are hooking things up.
> 
> Define "real cascade".  If you mean the chained handler stuff that's how
> Varun initially did it and I asked him to change it, because it gets a
> lot trickier to get things right, and I didn't see what it was buying us.
> 
> The request_irq() isn't on behalf of the individual drivers, it's
> requesting the cascade itself (not a shared interrupt).

I missed the bit related to err_int_config_done, need to re-look at it.  Was thinking request_irq() was getting called for every error interrupt.

>> I think you need to add proper irq_domain_ops, etc.  Thus when we map the virq the proper thing can happen
> 
> What proper thing is not happening?
> 
> Maybe it would be cleaner from an interrupt number management
> perspective to keep things more separate, but do you have a functional
> issue in mind?
> 
>> I'd also suggest maybe thinking about pulling this code into an mpic_fsl.c
>> 
>>> arch/powerpc/include/asm/mpic.h |   18 +++++
>>> arch/powerpc/sysdev/mpic.c      |  155 ++++++++++++++++++++++++++++++++++++++-
>>> 2 files changed, 171 insertions(+), 2 deletions(-)
>>> 
>>> diff --git a/arch/powerpc/include/asm/mpic.h b/arch/powerpc/include/asm/mpic.h
>>> index 3929b4b..db51015 100644
>>> --- a/arch/powerpc/include/asm/mpic.h
>>> +++ b/arch/powerpc/include/asm/mpic.h
>>> @@ -114,12 +114,21 @@
>>> #define MPIC_FSL_BRR1			0x00000
>>> #define 	MPIC_FSL_BRR1_VER			0x0000ffff
>>> 
>>> +/*
>>> + * Error interrupt registers
>>> + */
>>> +
>>> +#define MPIC_ERR_INT_BASE	0x3900
>>> +#define MPIC_ERR_INT_EISR	0x0000
>>> +#define MPIC_ERR_INT_EIMR	0x0010
>>> +
>>> #define MPIC_MAX_IRQ_SOURCES	2048
>>> #define MPIC_MAX_CPUS		32
>>> #define MPIC_MAX_ISU		32
>>> 
>>> #define MPIC_MAX_TIMER    8
>>> #define MPIC_MAX_IPI      4
>>> +#define MPIC_MAX_ERR      32
>> 
>> Should probably be 64
> 
> This patch supports MPIC 4.1 and EISR0.  When support is added for EISR1
> (didn't realize this was coming until your comment prompted me to
> check...), this should be updated, but this change alone would not make
> it work.

Would prefer we handle this now rather than later (T4240 is going to need EISR1 support).

>>> +static void mpic_mask_err(struct irq_data *d)
>>> +{
>>> +	u32 eimr;
>>> +	struct mpic *mpic = mpic_from_irq_data(d);
>>> +	unsigned int src = virq_to_hw(d->irq) - mpic->err_int_vecs[0];
>>> +	unsigned int err_reg_offset = MPIC_INFO(ERR_INT_EIMR);
>>> +
>>> +	eimr = mpic_err_read(err_reg_offset);
>>> +	eimr |= (0x80000000 >> src);
>> 
>> This seems funny, add a comment about src # and bit # being opposite.
> 
> People in PPC-land should be used to this craziness by now. :-P

:), as I said a comment would be helpful.

>> Maybe do:
>> 
>> 	eimr |= (1 << (31 - src));
> 
> I'm not sure it's really any clearer that way...
> 
>>> +static irqreturn_t error_int_handler(int irq, void *data)
>>> +{
>>> +	struct mpic *mpic = (struct mpic *) data;
>>> +	unsigned int eisr_offset = MPIC_INFO(ERR_INT_EISR);
>>> +	unsigned int eimr_offset = MPIC_INFO(ERR_INT_EIMR);
>>> +	u32 eisr, eimr;
>>> +	int errint;
>>> +	unsigned int cascade_irq;
>>> +
>>> +	eisr = mpic_err_read(eisr_offset);
>>> +	eimr = mpic_err_read(eimr_offset);
>>> +
>>> +	if (!(eisr & ~eimr))
>>> +		return IRQ_NONE;
>>> +
>>> +	while (eisr) {
>>> +		errint = __ffs(eisr);
>>> +		cascade_irq = irq_linear_revmap(mpic->irqhost,
>>> +				 mpic->err_int_vecs[31 - errint]);
>> 
>> Should 31, be replaced w/MPIC_MAX_ERR - 1 ?
> 
> No, the 31 here is due to the backwards bit numbering within the
> register.  It'd be better to say "errint = 31 - __ffs(eisr)" -- or
> perhaps "errint = __builtin_clz(eisr)".

gotcha

- k


More information about the Linuxppc-dev mailing list