From 374a95aca7455fdbee0531bf2d546829e5c56569 Mon Sep 17 00:00:00 2001 From: Red Bear OS Date: Fri, 24 Jul 2026 01:59:26 +0900 Subject: [PATCH] acpid: gate general GPE _Lxx/_Exx dispatch behind REDBEAR_ACPI_GPE_DISPATCH The general GPE dispatch runs on acpid's single main-loop thread, which also serves /scheme/acpi. A blocking _Lxx/_Exx AML method (e.g. spinning on a PCI/EC condition that never becomes true) freezes the scheme and deadlocks every ACPI-reading daemon and therefore the whole boot. Linux avoids this with a dedicated kacpid thread. Until Red Bear has one, gate the general dispatch behind REDBEAR_ACPI_GPE_DISPATCH=1 (default OFF); EC + PM1 fixed events stay always-on (bounded and proven). --- drivers/acpid/src/power_events.rs | 42 +++++++++++++++++-------------- 1 file changed, 23 insertions(+), 19 deletions(-) diff --git a/drivers/acpid/src/power_events.rs b/drivers/acpid/src/power_events.rs index 08d8ea5361..6054f9ea0f 100644 --- a/drivers/acpid/src/power_events.rs +++ b/drivers/acpid/src/power_events.rs @@ -244,26 +244,30 @@ pub fn handle_sci(context: &AcpiContext) -> Vec { } } - // General GPE dispatch (evgpe.c acpi_ev_gpe_detect): non-EC enabled+active - // GPEs get \_GPE._Lxx (level, tried first) or \_GPE._Exx (edge) evaluated. - let ec_gpe = context.ec_device.read().clone().map(|(_, g)| g); - for gpe in blocks.enabled_active_gpes() { - if Some(gpe) == ec_gpe { - continue; + // General GPE dispatch (evgpe.c acpi_ev_gpe_detect). It runs on acpid's + // main-loop thread, which also serves /scheme/acpi — a blocking _Lxx/_Exx + // method would freeze the scheme and deadlock the boot. Opt-in via + // REDBEAR_ACPI_GPE_DISPATCH=1, default OFF (EC + PM1 stay always-on). + if std::env::var_os("REDBEAR_ACPI_GPE_DISPATCH").is_some() { + let ec_gpe = context.ec_device.read().clone().map(|(_, g)| g); + for gpe in blocks.enabled_active_gpes() { + if Some(gpe) == ec_gpe { + continue; + } + let level = format!("\\_GPE._L{gpe:02X}"); + let edge = format!("\\_GPE._E{gpe:02X}"); + let handled = context.evaluate_acpi_method(&level, "", &[]).is_ok() + || context.evaluate_acpi_method(&edge, "", &[]).is_ok(); + if handled { + log::info!("acpid: GPE {:#04x} dispatched to AML control method", gpe); + } else { + log::debug!( + "acpid: GPE {:#04x} active but no _L{gpe:02X}/_E{gpe:02X} method", + gpe + ); + } + blocks.clear_gpe(gpe); } - let level = format!("\\_GPE._L{gpe:02X}"); - let edge = format!("\\_GPE._E{gpe:02X}"); - let handled = context.evaluate_acpi_method(&level, "", &[]).is_ok() - || context.evaluate_acpi_method(&edge, "", &[]).is_ok(); - if handled { - log::info!("acpid: GPE {:#04x} dispatched to AML control method", gpe); - } else { - log::debug!( - "acpid: GPE {:#04x} active but no _L{gpe:02X}/_E{gpe:02X} method", - gpe - ); - } - blocks.clear_gpe(gpe); } // Drain AML notifications (from _Qxx methods and any other Notify).