From 48397c64193e544ec949ca4071ca24654cc98aa5 Mon Sep 17 00:00:00 2001 From: Admin Pupkin Date: Mon, 1 Jun 2026 21:29:43 +0300 Subject: [PATCH] =?UTF-8?q?intel:=20Phase=205=20=E2=80=94=20runtime=20powe?= =?UTF-8?q?r=20management?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - 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 --- .../redox-drm/source/src/drivers/intel/gt.rs | 95 ++++++++++++++++++- 1 file changed, 92 insertions(+), 3 deletions(-) diff --git a/local/recipes/gpu/redox-drm/source/src/drivers/intel/gt.rs b/local/recipes/gpu/redox-drm/source/src/drivers/intel/gt.rs index 5645217e3b..4463ceff9d 100644 --- a/local/recipes/gpu/redox-drm/source/src/drivers/intel/gt.rs +++ b/local/recipes/gpu/redox-drm/source/src/drivers/intel/gt.rs @@ -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, + 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");