diff options
| author | Jessica Liu <liu.xuemei1@zte.com.cn> | 2026-03-10 14:17:31 +0800 |
|---|---|---|
| committer | Greg Kroah-Hartman <gregkh@linuxfoundation.org> | 2026-03-19 16:15:08 +0100 |
| commit | aef8051764ec04fdd9cd7bb4a88988179568f8d3 (patch) | |
| tree | ded1bc384cdfdd85a20187b534bf6254fd666b13 /drivers | |
| parent | ebbec32643b597604761843f3e34a94fff8b3c22 (diff) | |
irqchip/riscv-aplic: Register syscore operations only once
[ Upstream commit b330fbfd34d7624bec62b99ad88dba2614326a19 ]
Since commit 95a8ddde3660 ("irqchip/riscv-aplic: Preserve APLIC
states across suspend/resume"), when multiple NUMA nodes exist
and AIA is not configured as "none", aplic_probe() is called
multiple times. This leads to register_syscore(&aplic_syscore)
being invoked repeatedly, causing the following Oops:
list_add double add: new=ffffffffb91461f0, prev=ffffffffb91461f0, next=ffffffffb915c408.
[<ffffffffb7b5c8ca>] __list_add_valid_or_report+0x60/0xc0
[<ffffffffb7cc3236>] register_syscore+0x3e/0x70
[<ffffffffb7b8d61c>] aplic_probe+0xc6/0x112
Fix this by registering syscore operations only once, using a static
variable aplic_syscore_registered to track registration.
[ tglx: Trim backtrace properly ]
Fixes: 95a8ddde3660 ("irqchip/riscv-aplic: Preserve APLIC states across suspend/resume")
Signed-off-by: Jessica Liu <liu.xuemei1@zte.com.cn>
Signed-off-by: Thomas Gleixner <tglx@kernel.org>
Link: https://patch.msgid.link/20260310141731145xMwLsyvXl9Gw-m6A4VRYj@zte.com.cn
Signed-off-by: Sasha Levin <sashal@kernel.org>
Diffstat (limited to 'drivers')
| -rw-r--r-- | drivers/irqchip/irq-riscv-aplic-main.c | 12 |
1 files changed, 11 insertions, 1 deletions
diff --git a/drivers/irqchip/irq-riscv-aplic-main.c b/drivers/irqchip/irq-riscv-aplic-main.c index 8775f188ea4f..9f53979b6962 100644 --- a/drivers/irqchip/irq-riscv-aplic-main.c +++ b/drivers/irqchip/irq-riscv-aplic-main.c @@ -116,6 +116,16 @@ static struct syscore aplic_syscore = { .ops = &aplic_syscore_ops, }; +static bool aplic_syscore_registered __ro_after_init; + +static void aplic_syscore_init(void) +{ + if (!aplic_syscore_registered) { + register_syscore(&aplic_syscore); + aplic_syscore_registered = true; + } +} + static int aplic_pm_notifier(struct notifier_block *nb, unsigned long action, void *data) { struct aplic_priv *priv = container_of(nb, struct aplic_priv, genpd_nb); @@ -379,7 +389,7 @@ static int aplic_probe(struct platform_device *pdev) return rc; } - register_syscore(&aplic_syscore); + aplic_syscore_init(); #ifdef CONFIG_ACPI if (!acpi_disabled) |
