redbear-power: wire package thermal status into header
This commit is contained in:
@@ -121,7 +121,7 @@ pub struct App {
|
||||
pub load_available: bool,
|
||||
pub governor_available: bool,
|
||||
pub hwmon_available: bool,
|
||||
pub pkg_thermal: PackageThermal,
|
||||
pub package_thermal: Option<PackageThermal>,
|
||||
pub dbus_disconnected: bool,
|
||||
pub cpuid_info: CpuId,
|
||||
pub simd: String,
|
||||
@@ -423,7 +423,7 @@ impl App {
|
||||
load_available,
|
||||
governor_available,
|
||||
hwmon_available,
|
||||
pkg_thermal: PackageThermal::default(),
|
||||
package_thermal: None,
|
||||
dbus_disconnected: false,
|
||||
cpuid_info,
|
||||
simd,
|
||||
@@ -882,11 +882,15 @@ impl App {
|
||||
}
|
||||
// Re-read cpufreq state (catches external governor changes).
|
||||
self.cpufreq.refresh();
|
||||
if let Some(pkg) = read_package_thermal_status(self.cpus[0].id) {
|
||||
self.pkg_thermal = PackageThermal::from_msr(pkg);
|
||||
self.package_thermal = self
|
||||
.cpus
|
||||
.first()
|
||||
.and_then(|cpu| read_package_thermal_status(cpu.id))
|
||||
.map(PackageThermal::from_msr);
|
||||
if let Some(pkg) = self.package_thermal.as_ref() {
|
||||
// PROCHOT at the package level means the entire chip is
|
||||
// throttling. Surface that in the global header.
|
||||
let prochot_now = pkg & THERM_STATUS_PROCHOT != 0;
|
||||
let prochot_now = pkg.prochot;
|
||||
let prochot_was = matches!(self.throttle, ThrottleMode::ForcedMin);
|
||||
if prochot_now && !prochot_was {
|
||||
self.flash_toast("PROCHOT triggered \u{2014} throttling active");
|
||||
|
||||
@@ -23,17 +23,21 @@ use std::sync::Mutex;
|
||||
static MSR_FAILED: Mutex<Vec<bool>> = Mutex::new(Vec::new());
|
||||
|
||||
fn msr_failed_for(cpu: u32) -> bool {
|
||||
let cache = MSR_FAILED.lock().unwrap();
|
||||
cpu as usize >= cache.len() || cache[cpu as usize]
|
||||
if let Ok(cache) = MSR_FAILED.lock() {
|
||||
cpu as usize >= cache.len() || cache[cpu as usize]
|
||||
} else {
|
||||
false
|
||||
}
|
||||
}
|
||||
|
||||
fn mark_msr_failed(cpu: u32) {
|
||||
let mut cache = MSR_FAILED.lock().unwrap();
|
||||
let idx = cpu as usize;
|
||||
if idx >= cache.len() {
|
||||
cache.resize(idx + 1, false);
|
||||
if let Ok(mut cache) = MSR_FAILED.lock() {
|
||||
let idx = cpu as usize;
|
||||
if idx >= cache.len() {
|
||||
cache.resize(idx + 1, false);
|
||||
}
|
||||
cache[idx] = true;
|
||||
}
|
||||
cache[idx] = true;
|
||||
}
|
||||
|
||||
/// Clear the MSR failure cache. Call periodically (every ~30s) so that
|
||||
@@ -261,7 +265,6 @@ pub fn read_hwp_status(cpu: u32) -> Option<u64> {
|
||||
/// Decoded view of `IA32_PACKAGE_THERM_STATUS`. Built from the raw MSR
|
||||
/// value in `app.rs:refresh()`. Empty/default when the MSR is unreadable.
|
||||
#[derive(Clone, Copy, Debug, Default)]
|
||||
#[allow(dead_code)]
|
||||
pub struct PackageThermal {
|
||||
pub temp_c: Option<u32>,
|
||||
pub valid: bool,
|
||||
|
||||
@@ -166,12 +166,28 @@ pub fn render_toast<'a>(app: &'a App) -> Option<Paragraph<'a>> {
|
||||
pub fn render_header<'a>(app: &'a App, focused: bool) -> Paragraph<'a> {
|
||||
let theme = &app.theme;
|
||||
let pkg_temp = app
|
||||
.cpus
|
||||
.iter()
|
||||
.filter_map(|c| c.temp_c)
|
||||
.max()
|
||||
.package_thermal
|
||||
.and_then(|pkg| pkg.temp_c)
|
||||
.or_else(|| app.cpus.iter().filter_map(|c| c.temp_c).max())
|
||||
.map(|t| format!("{t}°C"))
|
||||
.unwrap_or_else(|| "n/a".into());
|
||||
let pkg_thermal = app.package_thermal.map(|pkg| {
|
||||
let label = pkg.short_label();
|
||||
let style = if pkg.valid
|
||||
&& (pkg.prochot
|
||||
|| pkg.power_limit_1
|
||||
|| pkg.power_limit_2
|
||||
|| pkg.critical
|
||||
|| pkg.hfi
|
||||
|| pkg.thermal_throttle_1
|
||||
|| pkg.thermal_throttle_2)
|
||||
{
|
||||
theme.value_hot
|
||||
} else {
|
||||
theme.value_off
|
||||
};
|
||||
(label, style)
|
||||
});
|
||||
let lines = vec![
|
||||
Line::from(vec![
|
||||
"Vendor: ".set_style(theme.label),
|
||||
@@ -214,6 +230,20 @@ pub fn render_header<'a>(app: &'a App, focused: bool) -> Paragraph<'a> {
|
||||
"P-state source: ".set_style(theme.label),
|
||||
app.pss_source.as_str().into(),
|
||||
]),
|
||||
Line::from(vec![
|
||||
"PkgTherm: ".set_style(theme.label),
|
||||
match pkg_thermal {
|
||||
Some((label, style)) => label.set_style(style),
|
||||
None => "n/a".set_style(theme.value_off),
|
||||
},
|
||||
" ".into(),
|
||||
"D-Bus: ".set_style(theme.label),
|
||||
if app.dbus_disconnected {
|
||||
"DISCONNECTED".set_style(theme.status_warn)
|
||||
} else {
|
||||
"ok".set_style(theme.value_ok)
|
||||
},
|
||||
]),
|
||||
Line::from(vec![
|
||||
"SIMD: ".set_style(theme.label),
|
||||
app.simd.as_str().set_style(theme.value),
|
||||
|
||||
Reference in New Issue
Block a user