From e97e3e31d898833b2396310056cbf82e23956b36 Mon Sep 17 00:00:00 2001 From: Hanjun Guo Date: Fri, 19 Dec 2025 22:49:06 +0800 Subject: [PATCH 1/2] MAINTAINERS: Update the maintainers for ARM64 ACPI ARM64 ACPI patches go via ARM64 tree, but the listed maintainers for ARM64 ACPI don't include Catalin and Will, and there is no F: line under the ARM64 architecture entry, so emails will not route to Catalin and Will in an automatic way. Adding Catalin and Will to the maintainers entry for ARM64 ACPI to fix the problem, it will make life easy for merging ARM64 ACPI patches. Adding new maintainer entries for ARM64 ACPI doesn't mean the review work will balance to the new maintainer, patches still need to be acked by currently listed folks (Lorenzo, Hanjun, Sudeep) before merging them. Link: https://lore.kernel.org/linux-acpi/aS2ZTfS9YVO98Exe@willie-the-truck/ Signed-off-by: Hanjun Guo Acked-by: Lorenzo Pieralisi Signed-off-by: Will Deacon --- MAINTAINERS | 2 ++ 1 file changed, 2 insertions(+) diff --git a/MAINTAINERS b/MAINTAINERS index 5b11839cba9d..6050d94a50ec 100644 --- a/MAINTAINERS +++ b/MAINTAINERS @@ -335,6 +335,8 @@ ACPI FOR ARM64 (ACPI/arm64) M: Lorenzo Pieralisi M: Hanjun Guo M: Sudeep Holla +M: Catalin Marinas +M: Will Deacon L: linux-acpi@vger.kernel.org L: linux-arm-kernel@lists.infradead.org (moderated for non-subscribers) S: Maintained From f7d5e9e70302c06c04599919770f3e0cb339342e Mon Sep 17 00:00:00 2001 From: Kazuhiro Abe Date: Thu, 8 Jan 2026 16:56:09 +0900 Subject: [PATCH 2/2] ACPI: AGDI: Add interrupt signaling mode support AGDI has two types of signaling modes: SDEI and interrupt. Currently, the AGDI driver only supports SDEI. Therefore, add support for interrupt signaling mode. The interrupt vector is retrieved from the AGDI table, and call panic function when an interrupt occurs. Acked-by: Hanjun Guo Reviewed-by: Ilkka Koskinen Signed-off-by: Kazuhiro Abe Signed-off-by: Will Deacon --- drivers/acpi/arm64/agdi.c | 101 ++++++++++++++++++++++++++++++++++---- 1 file changed, 92 insertions(+), 9 deletions(-) diff --git a/drivers/acpi/arm64/agdi.c b/drivers/acpi/arm64/agdi.c index e0df3daa4abf..feb4b2cb4618 100644 --- a/drivers/acpi/arm64/agdi.c +++ b/drivers/acpi/arm64/agdi.c @@ -16,7 +16,11 @@ #include "init.h" struct agdi_data { + unsigned char flags; /* AGDI Signaling Mode */ int sdei_event; + unsigned int gsiv; + bool use_nmi; + int irq; }; static int agdi_sdei_handler(u32 sdei_event, struct pt_regs *regs, void *arg) @@ -48,6 +52,57 @@ static int agdi_sdei_probe(struct platform_device *pdev, return 0; } +static irqreturn_t agdi_interrupt_handler_nmi(int irq, void *dev_id) +{ + nmi_panic(NULL, "Arm Generic Diagnostic Dump and Reset NMI Interrupt event issued\n"); + return IRQ_HANDLED; +} + +static irqreturn_t agdi_interrupt_handler_irq(int irq, void *dev_id) +{ + panic("Arm Generic Diagnostic Dump and Reset Interrupt event issued\n"); + return IRQ_HANDLED; +} + +static int agdi_interrupt_probe(struct platform_device *pdev, + struct agdi_data *adata) +{ + unsigned long irq_flags; + int ret; + int irq; + + irq = acpi_register_gsi(NULL, adata->gsiv, ACPI_EDGE_SENSITIVE, ACPI_ACTIVE_HIGH); + if (irq < 0) { + dev_err(&pdev->dev, "cannot register GSI#%d (%d)\n", adata->gsiv, irq); + return irq; + } + + irq_flags = IRQF_PERCPU | IRQF_NOBALANCING | IRQF_NO_AUTOEN | + IRQF_NO_THREAD; + /* try NMI first */ + ret = request_nmi(irq, &agdi_interrupt_handler_nmi, irq_flags, + "agdi_interrupt_nmi", NULL); + if (!ret) { + enable_nmi(irq); + adata->irq = irq; + adata->use_nmi = true; + return 0; + } + + /* Then try normal interrupt */ + ret = request_irq(irq, &agdi_interrupt_handler_irq, + irq_flags, "agdi_interrupt_irq", NULL); + if (ret) { + dev_err(&pdev->dev, "cannot register IRQ %d\n", ret); + acpi_unregister_gsi(adata->gsiv); + return ret; + } + enable_irq(irq); + adata->irq = irq; + + return 0; +} + static int agdi_probe(struct platform_device *pdev) { struct agdi_data *adata = dev_get_platdata(&pdev->dev); @@ -55,12 +110,15 @@ static int agdi_probe(struct platform_device *pdev) if (!adata) return -EINVAL; - return agdi_sdei_probe(pdev, adata); + if (adata->flags & ACPI_AGDI_SIGNALING_MODE) + return agdi_interrupt_probe(pdev, adata); + else + return agdi_sdei_probe(pdev, adata); } -static void agdi_remove(struct platform_device *pdev) +static void agdi_sdei_remove(struct platform_device *pdev, + struct agdi_data *adata) { - struct agdi_data *adata = dev_get_platdata(&pdev->dev); int err, i; err = sdei_event_disable(adata->sdei_event); @@ -83,6 +141,30 @@ static void agdi_remove(struct platform_device *pdev) adata->sdei_event, ERR_PTR(err)); } +static void agdi_interrupt_remove(struct platform_device *pdev, + struct agdi_data *adata) +{ + if (adata->irq == -1) + return; + + if (adata->use_nmi) + free_nmi(adata->irq, NULL); + else + free_irq(adata->irq, NULL); + + acpi_unregister_gsi(adata->gsiv); +} + +static void agdi_remove(struct platform_device *pdev) +{ + struct agdi_data *adata = dev_get_platdata(&pdev->dev); + + if (adata->flags & ACPI_AGDI_SIGNALING_MODE) + agdi_interrupt_remove(pdev, adata); + else + agdi_sdei_remove(pdev, adata); +} + static struct platform_driver agdi_driver = { .driver = { .name = "agdi", @@ -94,7 +176,7 @@ static struct platform_driver agdi_driver = { void __init acpi_agdi_init(void) { struct acpi_table_agdi *agdi_table; - struct agdi_data pdata; + struct agdi_data pdata = { 0 }; struct platform_device *pdev; acpi_status status; @@ -103,12 +185,13 @@ void __init acpi_agdi_init(void) if (ACPI_FAILURE(status)) return; - if (agdi_table->flags & ACPI_AGDI_SIGNALING_MODE) { - pr_warn("Interrupt signaling is not supported"); - goto err_put_table; - } + if (agdi_table->flags & ACPI_AGDI_SIGNALING_MODE) + pdata.gsiv = agdi_table->gsiv; + else + pdata.sdei_event = agdi_table->sdei_event; - pdata.sdei_event = agdi_table->sdei_event; + pdata.irq = -1; + pdata.flags = agdi_table->flags; pdev = platform_device_register_data(NULL, "agdi", 0, &pdata, sizeof(pdata)); if (IS_ERR(pdev))