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:
@@ -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
|
||||
// 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).
|
||||
|
||||
Reference in New Issue
Block a user