Loading MAINTAINERS +2 −0 Original line number Diff line number Diff line Loading @@ -335,6 +335,8 @@ ACPI FOR ARM64 (ACPI/arm64) M: Lorenzo Pieralisi <lpieralisi@kernel.org> M: Hanjun Guo <guohanjun@huawei.com> M: Sudeep Holla <sudeep.holla@arm.com> M: Catalin Marinas <catalin.marinas@arm.com> M: Will Deacon <will@kernel.org> L: linux-acpi@vger.kernel.org L: linux-arm-kernel@lists.infradead.org (moderated for non-subscribers) S: Maintained Loading drivers/acpi/arm64/agdi.c +92 −9 Original line number Diff line number Diff line Loading @@ -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) Loading Loading @@ -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); Loading @@ -55,12 +110,15 @@ static int agdi_probe(struct platform_device *pdev) if (!adata) return -EINVAL; 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); Loading @@ -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", Loading @@ -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; Loading @@ -103,13 +185,14 @@ 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.irq = -1; pdata.flags = agdi_table->flags; pdev = platform_device_register_data(NULL, "agdi", 0, &pdata, sizeof(pdata)); if (IS_ERR(pdev)) goto err_put_table; Loading Loading
MAINTAINERS +2 −0 Original line number Diff line number Diff line Loading @@ -335,6 +335,8 @@ ACPI FOR ARM64 (ACPI/arm64) M: Lorenzo Pieralisi <lpieralisi@kernel.org> M: Hanjun Guo <guohanjun@huawei.com> M: Sudeep Holla <sudeep.holla@arm.com> M: Catalin Marinas <catalin.marinas@arm.com> M: Will Deacon <will@kernel.org> L: linux-acpi@vger.kernel.org L: linux-arm-kernel@lists.infradead.org (moderated for non-subscribers) S: Maintained Loading
drivers/acpi/arm64/agdi.c +92 −9 Original line number Diff line number Diff line Loading @@ -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) Loading Loading @@ -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); Loading @@ -55,12 +110,15 @@ static int agdi_probe(struct platform_device *pdev) if (!adata) return -EINVAL; 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); Loading @@ -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", Loading @@ -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; Loading @@ -103,13 +185,14 @@ 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.irq = -1; pdata.flags = agdi_table->flags; pdev = platform_device_register_data(NULL, "agdi", 0, &pdata, sizeof(pdata)); if (IS_ERR(pdev)) goto err_put_table; Loading