Ben! On Tue, Dec 12 2023 at 10:35, Ben Wolsieffer wrote: > On Fri, Dec 08, 2023 at 09:43:21PM +0100, Thomas Gleixner wrote: >> On Mon, Dec 04 2023 at 15:33, Ben Wolsieffer wrote: >> > The STM32 doesn't support GPIO level interrupts in hardware, so the >> > driver tries to emulate them using edge interrupts, by retriggering the >> > interrupt if necessary based on the pin state after the handler >> > finishes. >> > >> > Currently, this functionality does not work because the irqchip uses >> > handle_edge_irq(), which doesn't run the irq_eoi() or irq_unmask() >> > callbacks after handling the interrupt. This patch fixes this by using >> > handle_level_irq() for level interrupts, which causes irq_unmask() to be >> > called to retrigger the interrupt. >> >> This does not make any sense at all. irq_unmask() does not retrigger >> anything. It sets the corresponding bit in the mask register, not more >> not less. > > I don't think this is correct. I was referring to > stm32_gpio_irq_unmask(), which calls stm32_gpio_irq_trigger(), which in > turn (for level interrupts) checks the GPIO pin state and retriggers the > interrupt if necessary. Ah. That makes a lot more sense. Sorry that I missed that driver detail. The changelog could mention explicitely where the retrigger comes from. >> Switching to handle_level_irq() makes the following difference >> vs. handle_edge_irq() when an interrupt is handled (ignoring the inner >> loop): >> >> + irq_mask(); >> irq_ack(); >> .... >> handle(); >> .... >> + irq_unmask(); > > Yes, the additional call to irq_unmask() is the key difference here, as > that callback performs the retriggering for level interrupts. Sorry to be pedantic here. irq_unmask() is a function in the interrupt core code which eventually ends up invoking the irqchip::irq_unmask(). >> When the interrupt is raised again after irq_ack() while the handler is >> running, i.e. a full toggle from active to inactive and back to active >> where the back to active transition causes the edge detector to trigger, >> then: > > I don't see how this is relevant. The bug occurs with level interrupts > in the case where there are no new transitions while the handler is > running. For example, with a high level interrupt, if the pin is still > high after the handler finishes, the interrupt should be immediately > triggered again. Ah. That's the problem you are trying to solve. Now we are getting closer to a proper description :) >> But in fact the regular exti driver could do the same and just handle >> the two NVIC interrupts which need demultiplexing separately and let >> everything else go through the hierarchy without bells and whistles. > > This sounds reasonable to me. It did seem strange to me that the exti > and exti_h drivers used such different approaches, although I wasn't > aware of the reasons behind them. I think this refactoring is out of > scope of this bug fix though. Sure. It just occured to me while looking at this stuff.. Care to resend with a proper explanation in the changelog? Thanks, tglx