Re: iio: ad7192: Pending IRQ on SDO/RDY causing retrigger of interrupt handler and missing every sample

From: Nuno Sá
Date: Tue Apr 18 2023 - 07:28:49 EST


On Fri, 2023-04-07 at 10:51 +0200, Fabrizio Lamarque wrote:
> On Wed, Apr 5, 2023 at 4:35 PM Lars-Peter Clausen <lars@xxxxxxxxxx> wrote:
> >
> > On 4/5/23 06:49, Nuno Sá wrote:
> > > [...]
> > > I just tested the patch, but, at least on the platform I'm working on
> > > (I.MX6), it does not
> > > solve the issue.
> > > Whereas the thread describes the very same issue I am experiencing, I
> > > am not sure
> > > IRQ_DISABLE_UNLAZY would have any impact. By reading CPU registers I see
> > > I was expecting to have. AFAIU, the lazy approach would be the responsible
> > > for
> > > this behavior because when you call disable_irq() it does not really mask
> > > the
> > > IRQ in HW. Just marks it as disabled and if another IRQ event comes set's
> > > it to
> > > PENDING and only then masks at HW level... If we "unlazy" the IRQ, we
> > > should
> > > mask the IRQ right away so I would expect not to have any pending IRQ...
> > >
> > > > the IRQ line disabled at the hardware level, but when the IRQ flag of
> > > > the processor
> > > > is set (and this happens even if the interrupt is masked in HW), the
> > > > interrupt is immediately
> > > > triggered anyway.
> > > > (I see GPIOx_IMR cleared, so interrupt is masked, but GPIOx_ISR set. As
> > > > soon
> > > > as
> > > > enable_irq() is called the interrupt is triggered. Just by clearing
> > > > GPIOx_ISR before
> > > > enable_irq() solves the issue. I might share a few debug printk).
> >
> > This sounds to me that the GPIO driver should implement an
> > `irq_enable()` callback where it clears the pending bits before
> > unmasking. This is consistent with what other GPIO IRQ drivers do.
> >
>
> Hello Lars,
>  thank you for your comments and for having a look at this.
>
> I am not really confident in dissecting how ARM interrupt management
> and NXP specific features. However, he "Delayed Interrupt" feature in
> kernel documentation (specific to ARM interrupt implementation),
> "prevents losing edge interrupts on hardware which does not store an
> edge interrupt event while the interrupt is disabled at the hardware
> level". This feature is always enabled for any ARM core.
> Indeed, NXP hardware _stores_ the GPIO edge interrupt when the IRQ is
> disabled. While not explicitly written in kernel docs, to my limited
> understanding enable_irq() should not clear the pending edge IRQ
> (eventually occurred when interrupt was disabled).
> I do not see anything that clearly does not conform to documentation
> in how IRQs are being managed.
>

So I'm still not convinced that's the right behavior. If we set
IRQ_DISABLE_UNLAZY, then I would expect that line to be masked/disabled as
soon as disable_irq() is called. Then, I would expect that no IRQ is saved
for a disabled/masked line or we should (I guess) at least be capable of
distinguish between "we want to get interrupts while processing one" or
"we really want to disable the line".

Anyways, I'm not really sure about this and it would be interesting to give
this a try in another platform.

> > the driver was written with the assumption that
> > irq_disable() will stop recording of IRQ events. If that does not hold
> > we might have to switch from irq_enable/irq_disable to
> > request_irq/free_irq, which will come with a slight overhead.
>
> request_irq/free_irq should clear the interrupt flags.
> However, since this change might have side effects on other ADI ADC
> drivers and trigger functionality, I'd be unable to provide a valid
> and verified patch (but I could test a proposed patch on my platform).
>
>

I would prefer the bindings approach. AFAIR, we should not really impose any
flags (possibly overwriting what was described in dts) when requesting the
IRQ. Hence, dropping 'irq_flags' would actually make sense. 

But this brings the question if anyone was relying on it and not properly
setting the flags in devicetree.


- Nuno Sá