diff --git a/drivers/gpu/drm/asahi/workqueue.rs b/drivers/gpu/drm/asahi/workqueue.rs index 6281ef684e251..c42d467b9a61e 100644 --- a/drivers/gpu/drm/asahi/workqueue.rs +++ b/drivers/gpu/drm/asahi/workqueue.rs @@ -243,6 +243,7 @@ struct WorkQueueInner { size: u32, wptr: u32, pending: KVec>>, + last_completed_work: Option>>, last_token: Option, pending_jobs: usize, last_submitted: Option, @@ -740,6 +741,7 @@ impl WorkQueue::ver { size, wptr: 0, pending: KVec::new(), + last_completed_work: None, last_token: None, event: None, priority, @@ -933,6 +935,8 @@ impl WorkQueue for WorkQueue::ver { let last_wptr = inner.pending[completed_commands - 1].inner.wptr(); let pipe_type = inner.pipe_type; + let mut last_cmd = inner.last_completed_work.take(); + for mut cmd in inner.pending.drain(..completed_commands) { mod_pr_debug!( "WorkQueue({:?}): Queueing command @ {:?} for cleanup\n", @@ -940,9 +944,13 @@ impl WorkQueue for WorkQueue::ver { cmd.inner.gpu_va() ); cmd.as_mut().inner_mut().complete(); - workqueue::system_dfl().enqueue(cmd); + if let Some(last_cmd) = last_cmd.replace(cmd) { + workqueue::system_dfl().enqueue(last_cmd); + } } + inner.last_completed_work = last_cmd; + mod_pr_debug!( "WorkQueue({:?}): Completed {} commands, left pending {}, ls {:#x?}, lc {:#x?}\n", inner.pipe_type, @@ -1039,3 +1047,12 @@ impl WorkQueue for WorkQueue::ver { } } } + +#[versions(AGX)] +impl Drop for WorkQueueInner::ver { + fn drop(&mut self) { + if let Some(last_cmd) = self.last_completed_work.take() { + workqueue::system_dfl().enqueue(last_cmd); + } + } +}