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).
This commit is contained in:
Red Bear OS
2026-07-24 01:59:26 +09:00
parent 92bf05c20a
commit 374a95aca7
+23 -19
View File
@@ -244,26 +244,30 @@ pub fn handle_sci(context: &AcpiContext) -> Vec<PowerEvent> {
} }
} }
// General GPE dispatch (evgpe.c acpi_ev_gpe_detect): non-EC enabled+active // General GPE dispatch (evgpe.c acpi_ev_gpe_detect). It runs on acpid's
// GPEs get \_GPE._Lxx (level, tried first) or \_GPE._Exx (edge) evaluated. // main-loop thread, which also serves /scheme/acpi — a blocking _Lxx/_Exx
let ec_gpe = context.ec_device.read().clone().map(|(_, g)| g); // method would freeze the scheme and deadlock the boot. Opt-in via
for gpe in blocks.enabled_active_gpes() { // REDBEAR_ACPI_GPE_DISPATCH=1, default OFF (EC + PM1 stay always-on).
if Some(gpe) == ec_gpe { if std::env::var_os("REDBEAR_ACPI_GPE_DISPATCH").is_some() {
continue; 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). // Drain AML notifications (from _Qxx methods and any other Notify).