diff --git a/drivers/gpu/drm/asahi/g17/runtime/render/submit.rs b/drivers/gpu/drm/asahi/g17/runtime/render/submit.rs index d35c2cdd66420..8133761ee6cbf 100644 --- a/drivers/gpu/drm/asahi/g17/runtime/render/submit.rs +++ b/drivers/gpu/drm/asahi/g17/runtime/render/submit.rs @@ -318,8 +318,11 @@ impl Backend { self.shared.queue_events(); self.admission_open()?; let started = super::super::now_ns(); + // Backing frees only as other owners' pairs and pools are released, which takes far + // longer than one poll under concurrent clients: wait as long as a compute queue + // waits for capacity (and a render channel for its retirement). let remaining = self - .wait_deadline(clock, super::super::WORK_RING_WAIT_NS)? + .wait_deadline(clock, crate::g17::preparation::QUEUE_WAIT_NS)? .saturating_sub(started); if remaining == 0 { return Err(EBUSY); diff --git a/tools/asahi/g17-capacity-backoff-tests.py b/tools/asahi/g17-capacity-backoff-tests.py index 9510927abd674..cf679a53d2dc5 100755 --- a/tools/asahi/g17-capacity-backoff-tests.py +++ b/tools/asahi/g17-capacity-backoff-tests.py @@ -34,7 +34,7 @@ def fixture(source): parts = [const(source, 'CAPACITY_PAUSE_MIN_NS'), const(source, 'CAPACITY_PAUSE_MAX_NS'), '#[derive(Default)]\n' + item(source, 'struct WaitClock'), item(source, 'impl WaitClock'), 'impl Backend {\n' + item(source, 'fn wait_render_capacity(') + '\n}'] - code = '\n'.join(parts).replace('super::super::', 'rt::') + code = '\n'.join(parts).replace('super::super::', 'rt::').replace('crate::g17::preparation::', 'rt::') return r''' #![allow(dead_code)] use std::sync::atomic::{AtomicU64, AtomicUsize, Ordering}; @@ -47,7 +47,7 @@ def fixture(source): const STORM:usize=0; const QUIET:usize=1; const RELEASE:usize=2; const RELEASE_AT:u64=5_000_000; fn recovery_wait_ns()->u64 {10_000_000_000} -mod rt {pub fn now_ns()->u64 {crate::NOW.load(crate::Ordering::SeqCst)} pub const WORK_RING_WAIT_NS:u64=2_000_000_000;} +mod rt {pub fn now_ns()->u64 {crate::NOW.load(crate::Ordering::SeqCst)} pub const WORK_RING_WAIT_NS:u64=2_000_000_000; pub const QUEUE_WAIT_NS:u64=30_000_000_000;} struct Delta(i64); impl Delta {fn from_nanos(n:i64)->Self {Delta(n)}} fn fsleep(d:Delta) {assert!(d.0>0); NOW.fetch_add(d.0 as u64,Ordering::SeqCst);} @@ -78,7 +78,8 @@ def fixture(source): NOW.store(0,Ordering::SeqCst); GEN.store(0,Ordering::SeqCst); ATTEMPTS.store(0,Ordering::SeqCst); MODE.store(mode,Ordering::SeqCst); let b=Backend{shared:Shared{renders:Renders}}; let (mut observed,mut clock)=(None,WaitClock::default()); - let deadline=rt::WORK_RING_WAIT_NS; + // The wait's own bound: QUEUE_WAIT_NS from its start, at most the recovery wait. + let deadline=rt::QUEUE_WAIT_NS.min(recovery_wait_ns()); let result=loop { // One refused placement attempt of the caller's loop. NOW.fetch_add(200,Ordering::SeqCst); @@ -90,18 +91,19 @@ def fixture(source): (result,rt::now_ns(),ATTEMPTS.load(Ordering::SeqCst)) } fn main() { + let bound=rt::QUEUE_WAIT_NS.min(recovery_wait_ns()); let (r,t,n)=run(STORM); - assert_eq!(r,Err(EBUSY)); assert!(t>=2_000_000_000 && t<2_003_000_000,"storm ends at {t}"); assert!(n<=3_200,"storm attempts {n}"); + assert_eq!(r,Err(EBUSY)); assert!(t>=bound && t=2_000_000_000 && t<2_011_000_000); assert!(n<=420,"quiet attempts {n}"); + assert_eq!(r,Err(EBUSY)); assert!(t>=bound && tResult {let b=Backend{shared:Shared{renders:Renders}}; b.wait_render_capacity(&mut None,&mut WaitClock::default(),false)} '''