Re: [tip: irq/core] x86: Select HARDIRQS_SW_RESEND on x86

Hans de Goede
2020-03-12T13:49:46Z

Hi,

On 3/12/20 2:31 PM, Linus Walleij wrote:
> On Wed, Mar 11, 2020 at 10:42 PM tip-bot2 for Hans de Goede
> <tip-bot2@linutronix.de> wrote:
>
>> select GENERIC_GETTIMEOFDAY
>> select GENERIC_VDSO_TIME_NS
>> select GUP_GET_PTE_LOW_HIGH if X86_PAE
>> + select HARDIRQS_SW_RESEND
>
> Just help me understand the semantics of this thing...
>
> According to the text in KConfig:
>
> # Tasklet based software resend for pending interrupts on enable_irq()
> config HARDIRQS_SW_RESEND
> bool
>
> According to
> commit a4633adcdbc15ac51afcd0e1395de58cee27cf92
>
> [PATCH] genirq: add genirq sw IRQ-retrigger
>
> Enable platforms that do not have a hardware-assisted
> hardirq-resend mechanism
> to resend them via a softirq-driven IRQ emulation mechanism.
>
> so when enable_irq() is called, if the IRQ is already asserted,
> it will be distributed in the form of a software irq?
>
> OK I give up I don't understand the semantics of this thing.
>
> Maybe it's because I think of a register where the IRQ line
> is just a level IRQ bit thing that stays high as long as the IRQ
> is not handled.
>
> So I suppose it is for any type of transient IRQ such as
> edge triggered that happened before the system came back
> online entirely and now the only remnant of it is a bit in
> the irchip status register?

The way I understand it is like this:

1. We have an edge triggered IRQ from a peripheral to a
GPIO controller

2. We have a level triggered IRQ from the GPIO controller to the
"root" IRQ controller.

3. With modern x86 suspend, we do not really put the entire
system in a firmware-controller suspend state, instead the CPU is
halted until any IRQ happens; and there is a power-management
micro-controller which shuts various things down while the CPU
is halted leading to similar power consumption as old S3 suspend.

The combination of these 3 means that we must ack the edge
triggered IRQ at the GPIO controller level even while suspended
(we briefly wake up for this) to make the level-triggered IRQ
coming from the GPIO controller low so that we can go back to sleep.

When this happens we record in the kernel IRQ tracking data for
the edge-triggered IRQ tied to the GPIO (there are no "remnants"
of it in any chuip registers), that the IRQ needs to be replayed
on resume. Some IRQ controllers allow writing a register to
retrigger the IRQ without the level on the external GPIO actually
changing.

Some IRQ controllers do not allow this, in this case we need to
emulate this retriggering in software, this is what the
HARDIRQS_SW_RESEND option is for, this handles this in a generic
way, so that we do not have to add emulation to every IRQ-chip
driver where the hardware lacks a "retrigger" register.

> I see that ARM and ARM64 simply just select this. What
> happens if you do that and why is x86 not selecting it in general?

Erm, "selecting it in general" (well at least on x86) is what
this patch is doing. But I guess you mean why is this not
selected on all architectures? If I've understood tglx correctly
the HARDIRQS_SW_RESEND option is incompatible with some irq-chip
drivers. I think it was incompatible with using nested threaded
handlers are some such...

tglx can probably explain this way better then I can :)

Regards,

Hans