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.se...@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
_______________________________________________
Linuxppc-dev mailing list
Linuxppc-dev@lists.ozlabs.org
https://lists.ozlabs.org/listinfo/linuxppc-dev

Reply via email to