base: Fix P48 pattern and add P54 thermal module
- P48: Fix AmlSerdeValue::Package pattern (struct variant, not tuple) - P54: Add missing thermal.rs module referenced by P44 ThermalState with zone discovery via ACPI _TMP evaluation
This commit is contained in:
@@ -78,7 +78,7 @@ index 00000000..8b4fd533
|
||||
+ if let Ok(fst_name) = AmlName::from_str(&format!("{aml_prefix}._FST")) {
|
||||
+ match ctx.aml_eval(fst_name, Vec::new()) {
|
||||
+ Ok(value) => {
|
||||
+ if let AmlSerdeValue::Package(elements) = value {
|
||||
+ if let AmlSerdeValue::Package { contents: elements } = value {
|
||||
+ if elements.len() >= 2 {
|
||||
+ fan.current_level = extract_u64(&elements[1]);
|
||||
+ }
|
||||
|
||||
@@ -0,0 +1,141 @@
|
||||
diff --git a/drivers/acpid/src/thermal.rs b/drivers/acpid/src/thermal.rs
|
||||
new file mode 100644
|
||||
index 00000000..4614e481
|
||||
--- /dev/null
|
||||
+++ b/drivers/acpid/src/thermal.rs
|
||||
@@ -0,0 +1,135 @@
|
||||
+use acpi::aml::namespace::AmlName;
|
||||
+use std::str::FromStr;
|
||||
+use std::sync::RwLock;
|
||||
+
|
||||
+use crate::acpi::{AcpiContext, AmlEvalError};
|
||||
+use amlserde::AmlSerdeValue;
|
||||
+
|
||||
+#[derive(Clone, Debug)]
|
||||
+pub struct ThermalZone {
|
||||
+ pub name: String,
|
||||
+ pub temperature_raw: Option<u64>,
|
||||
+}
|
||||
+
|
||||
+impl ThermalZone {
|
||||
+ fn from_zone_eval(ctx: &AcpiContext, zone_name: &str) -> Result<Self, ThermalError> {
|
||||
+ let aml_prefix = format!("\\_TZ_.{zone_name}");
|
||||
+
|
||||
+ let mut temp_raw = None;
|
||||
+
|
||||
+ if let Ok(tmp_name) = AmlName::from_str(&format!("{aml_prefix}._TMP")) {
|
||||
+ match ctx.aml_eval(tmp_name, Vec::new()) {
|
||||
+ Ok(value) => {
|
||||
+ if let AmlSerdeValue::Integer(t) = value {
|
||||
+ temp_raw = Some(t as u64);
|
||||
+ }
|
||||
+ }
|
||||
+ Err(e) => {
|
||||
+ log::debug!("Thermal zone {zone_name}: _TMP eval failed: {e:?}");
|
||||
+ }
|
||||
+ }
|
||||
+ }
|
||||
+
|
||||
+ Ok(Self {
|
||||
+ name: zone_name.to_owned(),
|
||||
+ temperature_raw: temp_raw,
|
||||
+ })
|
||||
+ }
|
||||
+
|
||||
+ pub fn temperature_celsius(&self) -> Option<f64> {
|
||||
+ self.temperature_raw.map(|t| (t as f64 - 273.15) / 10.0)
|
||||
+ }
|
||||
+
|
||||
+ pub fn to_text(&self) -> String {
|
||||
+ let mut s = String::new();
|
||||
+ s.push_str(&format!("name={}\n", self.name));
|
||||
+ if let Some(c) = self.temperature_celsius() {
|
||||
+ s.push_str(&format!("temperature={:.1}°C\n", c));
|
||||
+ } else {
|
||||
+ s.push_str("temperature=na\n");
|
||||
+ }
|
||||
+ s
|
||||
+ }
|
||||
+}
|
||||
+
|
||||
+#[derive(Debug)]
|
||||
+pub enum ThermalError {
|
||||
+ EvalError(AmlEvalError),
|
||||
+ NotFound,
|
||||
+}
|
||||
+
|
||||
+impl From<AmlEvalError> for ThermalError {
|
||||
+ fn from(value: AmlEvalError) -> Self {
|
||||
+ ThermalError::EvalError(value)
|
||||
+ }
|
||||
+}
|
||||
+
|
||||
+pub fn discover_thermal_zones(ctx: &AcpiContext) -> Vec<ThermalZone> {
|
||||
+ let mut zones = Vec::new();
|
||||
+
|
||||
+ let zone_names = match ctx.thermal_zone_names() {
|
||||
+ Ok(names) => names,
|
||||
+ Err(e) => {
|
||||
+ log::debug!("Thermal zone discovery failed: {e:?}");
|
||||
+ return zones;
|
||||
+ }
|
||||
+ };
|
||||
+
|
||||
+ for zone_name in zone_names {
|
||||
+ match ThermalZone::from_zone_eval(ctx, &zone_name) {
|
||||
+ Ok(zone) => {
|
||||
+ if zone.temperature_raw.is_some() {
|
||||
+ log::info!(
|
||||
+ "Thermal zone discovered: {} = {:.1}°C",
|
||||
+ zone.name,
|
||||
+ zone.temperature_celsius().unwrap_or(0.0)
|
||||
+ );
|
||||
+ }
|
||||
+ zones.push(zone);
|
||||
+ }
|
||||
+ Err(e) => {
|
||||
+ log::warn!("Thermal zone {zone_name}: discovery failed: {e:?}");
|
||||
+ }
|
||||
+ }
|
||||
+ }
|
||||
+
|
||||
+ zones
|
||||
+}
|
||||
+
|
||||
+pub struct ThermalState {
|
||||
+ zones: RwLock<Vec<ThermalZone>>,
|
||||
+}
|
||||
+
|
||||
+impl ThermalState {
|
||||
+ pub fn new() -> Self {
|
||||
+ Self {
|
||||
+ zones: RwLock::new(Vec::new()),
|
||||
+ }
|
||||
+ }
|
||||
+
|
||||
+ pub fn refresh(&self, ctx: &AcpiContext) {
|
||||
+ let discovered = discover_thermal_zones(ctx);
|
||||
+ if let Ok(mut zones) = self.zones.write() {
|
||||
+ *zones = discovered;
|
||||
+ }
|
||||
+ }
|
||||
+
|
||||
+ pub fn zones(&self) -> Vec<ThermalZone> {
|
||||
+ self.zones.read().map(|g| g.clone()).unwrap_or_default()
|
||||
+ }
|
||||
+
|
||||
+ pub fn zone_by_name(&self, name: &str) -> Option<ThermalZone> {
|
||||
+ self.zones
|
||||
+ .read()
|
||||
+ .ok()?
|
||||
+ .iter()
|
||||
+ .find(|z| z.name == name)
|
||||
+ .cloned()
|
||||
+ }
|
||||
+}
|
||||
+
|
||||
+impl Default for ThermalState {
|
||||
+ fn default() -> Self {
|
||||
+ Self::new()
|
||||
+ }
|
||||
+}
|
||||
@@ -0,0 +1 @@
|
||||
../../../local/patches/base/P54-acpid-thermal-module.patch
|
||||
@@ -89,6 +89,8 @@ patches = [
|
||||
"P42-inputd-graceful-fallback.patch",
|
||||
"P43-dhcpd-requires-hard-dep.patch",
|
||||
"P44-acpid-thermal-zones.patch",
|
||||
# P54: Add missing thermal.rs module for P44
|
||||
"P54-acpid-thermal-module.patch",
|
||||
# P45: Migrate e1000d and ixgbed to MSI-X via pci_allocate_interrupt_vector
|
||||
"P45-net-msix-adoption.patch",
|
||||
# P46: Migrate ahcid and ac97d to MSI-X via pci_allocate_interrupt_vector
|
||||
|
||||
Reference in New Issue
Block a user