intel: Phase 5 — runtime power management
- RPS interactive governor: fast ramp-up on activity, slow ramp-down on idle - Runtime PM with wakeref counting and RC6 transitions - Forcewake automatically taken on first wakeref, released on last - Frequency tracking with min/max/target per-GT state
This commit is contained in:
@@ -75,6 +75,12 @@ pub struct IntelGtManager {
|
||||
forcewake_active: bool,
|
||||
rc6_enabled: bool,
|
||||
gt_freq_initialized: bool,
|
||||
wakeref_count: u32,
|
||||
rps_idle_count: u32,
|
||||
last_busy_check: Option<Instant>,
|
||||
target_freq: u32,
|
||||
min_freq: u32,
|
||||
max_freq: u32,
|
||||
}
|
||||
|
||||
impl IntelGtManager {
|
||||
@@ -85,6 +91,12 @@ impl IntelGtManager {
|
||||
forcewake_active: false,
|
||||
rc6_enabled: false,
|
||||
gt_freq_initialized: false,
|
||||
wakeref_count: 0,
|
||||
rps_idle_count: 0,
|
||||
last_busy_check: None,
|
||||
target_freq: 0,
|
||||
min_freq: 0,
|
||||
max_freq: 0,
|
||||
}
|
||||
}
|
||||
|
||||
@@ -240,11 +252,13 @@ impl IntelGtManager {
|
||||
let (min_freq, max_freq) = self.read_gt_freq_limits()?;
|
||||
|
||||
if min_freq > 0 && max_freq > 0 {
|
||||
let target = max_freq;
|
||||
self.set_gt_frequency(target)?;
|
||||
self.min_freq = min_freq;
|
||||
self.max_freq = max_freq;
|
||||
self.target_freq = max_freq;
|
||||
self.set_gt_frequency(self.target_freq)?;
|
||||
info!(
|
||||
"redox-drm-intel: GT frequency set to {} MHz (min {}, max {})",
|
||||
target * 50, min_freq * 50, max_freq * 50
|
||||
self.target_freq * 50, min_freq * 50, max_freq * 50
|
||||
);
|
||||
} else {
|
||||
warn!("redox-drm-intel: GT frequency limits invalid ({}/{})", min_freq, max_freq);
|
||||
@@ -269,6 +283,81 @@ impl IntelGtManager {
|
||||
Ok(())
|
||||
}
|
||||
|
||||
pub fn rps_update(&mut self) -> Result<()> {
|
||||
if !self.gt_freq_initialized || self.max_freq == 0 {
|
||||
return Ok(());
|
||||
}
|
||||
|
||||
let now = Instant::now();
|
||||
let idle_duration = self.last_busy_check.map(|t| now.duration_since(t));
|
||||
|
||||
let busy = self.wakeref_count > 0 || self.forcewake_active;
|
||||
if busy {
|
||||
self.rps_idle_count = 0;
|
||||
let step = (self.max_freq - self.min_freq).max(1) / 8;
|
||||
let up = self.target_freq.saturating_add(step).min(self.max_freq);
|
||||
if up != self.target_freq {
|
||||
self.target_freq = up;
|
||||
self.set_gt_frequency(self.target_freq)?;
|
||||
debug!("redox-drm-intel: RPS ↑ {} MHz (wakeref={})",
|
||||
self.target_freq * 50, self.wakeref_count);
|
||||
}
|
||||
} else if let Some(dur) = idle_duration {
|
||||
if dur.as_millis() >= 100 {
|
||||
self.rps_idle_count += 1;
|
||||
if self.rps_idle_count >= 3 {
|
||||
let step = (self.max_freq - self.min_freq).max(1) / 4;
|
||||
let down = self.target_freq.saturating_sub(step).max(self.min_freq);
|
||||
if down != self.target_freq {
|
||||
self.target_freq = down;
|
||||
self.set_gt_frequency(self.target_freq)?;
|
||||
debug!("redox-drm-intel: RPS ↓ {} MHz (idle {} ticks)",
|
||||
self.target_freq * 50, self.rps_idle_count);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
self.last_busy_check = Some(now);
|
||||
Ok(())
|
||||
}
|
||||
|
||||
pub fn runtime_get(&mut self) -> Result<()> {
|
||||
if self.wakeref_count == 0 {
|
||||
self.take_forcewake()?;
|
||||
if self.rc6_enabled {
|
||||
self.disable_rc6()?;
|
||||
}
|
||||
}
|
||||
self.wakeref_count = self.wakeref_count.saturating_add(1);
|
||||
Ok(())
|
||||
}
|
||||
|
||||
pub fn runtime_put(&mut self) -> Result<()> {
|
||||
if self.wakeref_count == 0 {
|
||||
return Ok(());
|
||||
}
|
||||
self.wakeref_count = self.wakeref_count.saturating_sub(1);
|
||||
if self.wakeref_count == 0 {
|
||||
self.rps_update()?;
|
||||
if self.forcewake_active {
|
||||
self.release_forcewake()?;
|
||||
}
|
||||
if !self.rc6_enabled {
|
||||
self.enable_rc6()?;
|
||||
}
|
||||
}
|
||||
Ok(())
|
||||
}
|
||||
|
||||
pub fn wakeref_count(&self) -> u32 {
|
||||
self.wakeref_count
|
||||
}
|
||||
|
||||
pub fn rps_target_freq_mhz(&self) -> u32 {
|
||||
self.target_freq * 50
|
||||
}
|
||||
|
||||
fn init_cache_config(&mut self) -> Result<()> {
|
||||
debug!("redox-drm-intel: configuring L3 cache");
|
||||
|
||||
|
||||
Reference in New Issue
Block a user