Skip to content

Commit 1583d9e

Browse files
committed
drm/asahi: Switch gpuvm to DRM_GPUVM_IMMEDIATE_MODE
DRM_GPUVM_IMMEDIATE_MODE supports deferred gpuva unlink and gpuvm bu release. Gpuva unlink of imported DMAbufs might drop the last reference of the gem object resulting in calling drm_prime_gem_destroy(). This calls ma_buf_unmap_attachment_unlocked() which expects to be able to lock dma_resv. This obviously deadlocks if called from a locked gpuvm. Signed-off-by: Janne Grunau <j@jannau.net>
1 parent 8bcfb1a commit 1583d9e

2 files changed

Lines changed: 20 additions & 8 deletions

File tree

drivers/gpu/drm/asahi/file.rs

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -674,6 +674,8 @@ impl File {
674674

675675
vm.bind_object(&bo, data.addr, data.range, data.offset, prot, single_page)?;
676676

677+
vm.bo_deferred_cleanup();
678+
677679
Ok(0)
678680
}
679681

@@ -736,6 +738,8 @@ impl File {
736738

737739
vm.unmap_range(range.start, range.range())?;
738740

741+
vm.bo_deferred_cleanup();
742+
739743
Ok(0)
740744
}
741745

drivers/gpu/drm/asahi/mmu.rs

Lines changed: 16 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -24,6 +24,7 @@ use core::sync::atomic::{
2424

2525
use kernel::{
2626
addr::PhysicalAddr,
27+
bindings::drm_gpuvm_flags_DRM_GPUVM_IMMEDIATE_MODE,
2728
c_str,
2829
device,
2930
drm::{
@@ -330,7 +331,7 @@ impl gpuvm::DriverGpuVm for VmInner {
330331
mem::sync();
331332
}
332333

333-
if op.unmap_and_unlink_va().is_none() {
334+
if op.unmap_and_unlink_va_defer().is_none() {
334335
dev_err!(self.dev.as_ref(), "step_unmap: could not unlink gpuva");
335336
}
336337
Ok(())
@@ -384,7 +385,7 @@ impl gpuvm::DriverGpuVm for VmInner {
384385
mem::sync();
385386
}
386387

387-
if op.unmap().unmap_and_unlink_va().is_none() {
388+
if op.unmap().unmap_and_unlink_va_defer().is_none() {
388389
dev_err!(self.dev.as_ref(), "step_unmap: could not unlink gpuva");
389390
}
390391

@@ -1009,6 +1010,8 @@ impl Vm {
10091010
dummy_obj: dummy_obj.gem.clone(),
10101011
inner: gpuvm::GpuVm::new(
10111012
c_str!("Asahi::GpuVm"),
1013+
// TODO: should we using DRM_GPUVM_RESV_PROTECTED as well?
1014+
drm_gpuvm_flags_DRM_GPUVM_IMMEDIATE_MODE,
10121015
dev,
10131016
dummy_obj.gem.clone(),
10141017
gpuvm_range,
@@ -1047,7 +1050,7 @@ impl Vm {
10471050
let size = object_range.range();
10481051
let sgt = gem.owned_sg_table()?;
10491052
let mut inner = self.inner.exec_lock(Some(gem), false)?;
1050-
let vm_bo = inner.obtain_bo()?;
1053+
let vm_bo = self.inner.obtain_bo(gem)?;
10511054

10521055
let mut vm_bo_guard = vm_bo.inner().sgt.lock();
10531056
if vm_bo_guard.is_none() {
@@ -1095,7 +1098,7 @@ impl Vm {
10951098
let sgt = gem.owned_sg_table()?;
10961099
let mut inner = self.inner.exec_lock(Some(&gem), false)?;
10971100

1098-
let vm_bo = inner.obtain_bo()?;
1101+
let vm_bo = self.inner.obtain_bo(&gem)?;
10991102

11001103
let mut vm_bo_guard = vm_bo.inner().sgt.lock();
11011104
if vm_bo_guard.is_none() {
@@ -1153,7 +1156,7 @@ impl Vm {
11531156
// Preallocate the page tables, to fail early if we ENOMEM
11541157
inner.page_table.alloc_pages(addr..(addr + size))?;
11551158

1156-
let vm_bo = inner.obtain_bo()?;
1159+
let vm_bo = self.inner.obtain_bo(gem)?;
11571160

11581161
let mut vm_bo_guard = vm_bo.inner().sgt.lock();
11591162
if vm_bo_guard.is_none() {
@@ -1269,11 +1272,11 @@ impl Vm {
12691272
// Removing whole mappings only does unmaps, so no preallocated VAs
12701273
let mut ctx = Default::default();
12711274

1272-
let mut inner = self.inner.exec_lock(Some(gem), false)?;
1275+
let inner = self.inner.exec_lock(Some(gem), false)?;
12731276

1274-
if let Some(bo) = inner.find_bo() {
1277+
if let Some(bo) = self.inner.find_bo(gem) {
12751278
mod_dev_dbg!(inner.dev, "MMU: bo_unmap\n");
1276-
inner.bo_unmap(&mut ctx, &bo)?;
1279+
self.inner.bo_unmap(&mut ctx, &bo)?;
12771280
mod_dev_dbg!(inner.dev, "MMU: bo_unmap done\n");
12781281
// We need to drop the exec_lock first, then the GpuVmBo since that will take the lock itself.
12791282
core::mem::drop(inner);
@@ -1292,6 +1295,11 @@ impl Vm {
12921295
pub(crate) fn is_extobj(&self, gem: &gem::Object) -> bool {
12931296
self.inner.is_extobj(gem)
12941297
}
1298+
1299+
/// Check whether an object is external to this GpuVm
1300+
pub(crate) fn bo_deferred_cleanup(&self) {
1301+
self.inner.bo_deferred_cleanup()
1302+
}
12951303
}
12961304

12971305
impl Drop for VmInner {

0 commit comments

Comments
 (0)