realtek: avoid wrong interrupt routing
authorMarkus Stockhausen <markus.stockhausen@gmx.de>
Wed, 7 Sep 2022 15:02:35 +0000 (17:02 +0200)
committerSander Vanheule <sander@svanheule.net>
Sun, 18 Sep 2022 18:38:56 +0000 (20:38 +0200)
commitbcb5d6b21ba574db1d02385b494eb01fe46bf8aa
treed3e9cc719796b6706d94bae064c0f1e6aaa64644
parentf0ea3df439c796dc6d4e5fee1cc6a15e7fed8085
realtek: avoid wrong interrupt routing

The interrupt controller depends on two control registers. GIMR enables
or disables interrupts and IRRx routes these to MIPS CPU interrupts 2-7.
Wiki currently states "A value of '0' (in IRRx) disconnects this input from
the output line, independent of the line's setting in GIMR."

Contrary to normal intuition this statement DOES NOT mean, that interrupts
can be disabled by IRRx alone. The sad truth was discovered by enabling
SMP for an Zyxel XGS1010 on the 930x target. It shows that driver and
interrupts behave as follows:

- Timer 0 interrupt 7 has active routing to CPU0 and no routing to CPU1
- Timer 1 interrupt 8 has no routing to CPU0 and active routing to CPU1
- Unmasking (enabling) interrupts writes 1 bits to all GIMR registers
- Masking (disabling) interrupts writes 0 bits to both GIMR registers

During operation we can encounter a situation like

- GIMR bit for a interrupt/CPU combination is set to enabed (=1)
- IRRx routing bits for a interrupt/CPU combination are set to disabed (=0)

This setting already allows the hardware to fire interrupts to the target
CPU/VPE if the other CPU/VPE is currently busy. Especially for CPU bound
timer interrupts this is lethal. If timer interrupt 7 arrives at CPU1 and
vice versa for interrupt 8 the restart trigger gets lost. The timer dies
and a msleep() operation in the kernel will halt endlessly.

Fix this by tracking the IRRx active routing setting in a new bitfield with
0="routing active" and 1="no routing". Enable interrupts in GIMR only
for a interrupt & CPU if routing is active. Thus we have

- GIMR = 0 / IRRx = 0 -> everything disabled
- GIMR = 1 / IRRx > 0 -> active and normal routing
- GIMR = 0 / IRRx > 0 -> masked (disabled) with normal routing
- GIMR = 1 / IRRx = 0 -> no longer possible

Signed-off-by: Markus Stockhausen <markus.stockhausen@gmx.de>
target/linux/realtek/patches-5.10/319-irqchip-irq-realtek-rtl-fix-VPE-affinity.patch [new file with mode: 0644]