summaryrefslogtreecommitdiff
path: root/drivers/acpi
diff options
context:
space:
mode:
authorLinus Torvalds <torvalds@linux-foundation.org>2026-02-09 20:28:45 -0800
committerLinus Torvalds <torvalds@linux-foundation.org>2026-02-09 20:28:45 -0800
commit45bf4bc87c46856c5cf4ac39a0c25c83ccbf3209 (patch)
tree902fa8ce3c2c714535bfcadb3e0465a18de5601c /drivers/acpi
parent9f722cb7304f63d8be7164c15ebc278f54d14357 (diff)
parent36c0de02575ce59dfd879eb4ef63d53a68bbf9ce (diff)
Merge tag 'arm64-upstream' of git://git.kernel.org/pub/scm/linux/kernel/git/arm64/linux
Pull arm64 updates from Will Deacon: "There's a little less than normal, probably due to LPC & Christmas/New Year meaning that a few series weren't quite ready or reviewed in time. It's still useful across the board, despite the only real feature being support for the LS64 feature enabling 64-byte atomic accesses to endpoints that support it. ACPI: - Add interrupt signalling support to the AGDI handler - Add Catalin and myself to the arm64 ACPI MAINTAINERS entry CPU features: - Drop Kconfig options for PAN and LSE (these are detected at runtime) - Add support for 64-byte single-copy atomic instructions (LS64/LS64V) - Reduce MTE overhead when executing in the kernel on Ampere CPUs - Ensure POR_EL0 value exposed via ptrace is up-to-date - Fix error handling on GCS allocation failure CPU frequency: - Add CPU hotplug support to the FIE setup in the AMU driver Entry code: - Minor optimisations and cleanups to the syscall entry path - Preparatory rework for moving to the generic syscall entry code Hardware errata: - Work around Spectre-BHB on TSV110 processors - Work around broken CMO propagation on some systems with the SI-L1 interconnect Miscellaneous: - Disable branch profiling for arch/arm64/ to avoid issues with noinstr - Minor fixes and cleanups (kexec + ubsan, WARN_ONCE() instead of WARN_ON(), reduction of boolean expression) - Fix custom __READ_ONCE() implementation for LTO builds when operating on non-atomic types Perf and PMUs: - Support for CMN-600AE - Be stricter about supported hardware in the CMN driver - Support for DSU-110 and DSU-120 - Support for the cycles event in the DSU driver (alongside the dedicated cycles counter) - Use IRQF_NO_THREAD instead of IRQF_ONESHOT in the cxlpmu driver - Use !bitmap_empty() as a faster alternative to bitmap_weight() - Fix SPE error handling when failing to resume profiling Selftests: - Add support for the FORCE_TARGETS option to the arm64 kselftests - Avoid nolibc-specific my_syscall() function - Add basic test for the LS64 HWCAP - Extend fp-pidbench to cover additional workload patterns" * tag 'arm64-upstream' of git://git.kernel.org/pub/scm/linux/kernel/git/arm64/linux: (43 commits) perf/arm-cmn: Reject unsupported hardware configurations perf: arm_spe: Properly set hw.state on failures arm64/gcs: Fix error handling in arch_set_shadow_stack_status() arm64: Fix non-atomic __READ_ONCE() with CONFIG_LTO=y arm64: poe: fix stale POR_EL0 values for ptrace kselftest/arm64: Raise default number of loops in fp-pidbench kselftest/arm64: Add a no-SVE loop after SVE in fp-pidbench perf/cxlpmu: Replace IRQF_ONESHOT with IRQF_NO_THREAD arm64: mte: Set TCMA1 whenever MTE is present in the kernel arm64/ptrace: Return early for ptrace_report_syscall_entry() error arm64/ptrace: Split report_syscall() arm64: Remove unused _TIF_WORK_MASK kselftest/arm64: Add missing file in .gitignore arm64: errata: Workaround for SI L1 downstream coherency issue kselftest/arm64: Add HWCAP test for FEAT_LS64 arm64: Add support for FEAT_{LS64, LS64_V} KVM: arm64: Enable FEAT_{LS64, LS64_V} in the supported guest arm64: Provide basic EL2 setup for FEAT_{LS64, LS64_V} usage at EL0/1 KVM: arm64: Handle DABT caused by LS64* instructions on unsupported memory KVM: arm64: Add documentation for KVM_EXIT_ARM_LDST64B ...
Diffstat (limited to 'drivers/acpi')
-rw-r--r--drivers/acpi/arm64/agdi.c101
1 files 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))