diff options
| author | Linus Torvalds <torvalds@linux-foundation.org> | 2026-02-09 20:28:45 -0800 |
|---|---|---|
| committer | Linus Torvalds <torvalds@linux-foundation.org> | 2026-02-09 20:28:45 -0800 |
| commit | 45bf4bc87c46856c5cf4ac39a0c25c83ccbf3209 (patch) | |
| tree | 902fa8ce3c2c714535bfcadb3e0465a18de5601c /drivers/acpi | |
| parent | 9f722cb7304f63d8be7164c15ebc278f54d14357 (diff) | |
| parent | 36c0de02575ce59dfd879eb4ef63d53a68bbf9ce (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.c | 101 |
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)) |
