Skip to content

Commit db4cbfa

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 ed4a812 commit db4cbfa

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
@@ -648,6 +648,8 @@ impl File {
648648

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

651+
vm.bo_deferred_cleanup();
652+
651653
Ok(0)
652654
}
653655

@@ -710,6 +712,8 @@ impl File {
710712

711713
vm.unmap_range(range.start, range.range())?;
712714

715+
vm.bo_deferred_cleanup();
716+
713717
Ok(0)
714718
}
715719

drivers/gpu/drm/asahi/mmu.rs

Lines changed: 16 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,7 @@ use core::sync::atomic::{fence, AtomicU32, AtomicU64, AtomicU8, Ordering};
1818

1919
use kernel::{
2020
addr::PhysicalAddr,
21+
bindings::drm_gpuvm_flags_DRM_GPUVM_IMMEDIATE_MODE,
2122
c_str, device,
2223
drm::{self, gem::shmem, gpuvm, mm},
2324
error::Result,
@@ -296,7 +297,7 @@ impl gpuvm::DriverGpuVm for VmInner {
296297
mem::sync();
297298
}
298299

299-
if op.unmap_and_unlink_va().is_none() {
300+
if op.unmap_and_unlink_va_defer().is_none() {
300301
dev_err!(self.dev.as_ref(), "step_unmap: could not unlink gpuva");
301302
}
302303
Ok(())
@@ -350,7 +351,7 @@ impl gpuvm::DriverGpuVm for VmInner {
350351
mem::sync();
351352
}
352353

353-
if op.unmap().unmap_and_unlink_va().is_none() {
354+
if op.unmap().unmap_and_unlink_va_defer().is_none() {
354355
dev_err!(self.dev.as_ref(), "step_unmap: could not unlink gpuva");
355356
}
356357

@@ -975,6 +976,8 @@ impl Vm {
975976
dummy_obj: dummy_obj.gem.clone(),
976977
inner: gpuvm::GpuVm::new(
977978
c_str!("Asahi::GpuVm"),
979+
// TODO: should we using DRM_GPUVM_RESV_PROTECTED as well?
980+
drm_gpuvm_flags_DRM_GPUVM_IMMEDIATE_MODE,
978981
dev,
979982
dummy_obj.gem.clone(),
980983
gpuvm_range,
@@ -1013,7 +1016,7 @@ impl Vm {
10131016
let size = object_range.range();
10141017
let sgt = gem.owned_sg_table()?;
10151018
let mut inner = self.inner.exec_lock(Some(gem), false)?;
1016-
let vm_bo = inner.obtain_bo()?;
1019+
let vm_bo = self.inner.obtain_bo(gem)?;
10171020

10181021
let mut vm_bo_guard = vm_bo.inner().sgt.lock();
10191022
if vm_bo_guard.is_none() {
@@ -1061,7 +1064,7 @@ impl Vm {
10611064
let sgt = gem.owned_sg_table()?;
10621065
let mut inner = self.inner.exec_lock(Some(&gem), false)?;
10631066

1064-
let vm_bo = inner.obtain_bo()?;
1067+
let vm_bo = self.inner.obtain_bo(&gem)?;
10651068

10661069
let mut vm_bo_guard = vm_bo.inner().sgt.lock();
10671070
if vm_bo_guard.is_none() {
@@ -1119,7 +1122,7 @@ impl Vm {
11191122
// Preallocate the page tables, to fail early if we ENOMEM
11201123
inner.page_table.alloc_pages(addr..(addr + size))?;
11211124

1122-
let vm_bo = inner.obtain_bo()?;
1125+
let vm_bo = self.inner.obtain_bo(gem)?;
11231126

11241127
let mut vm_bo_guard = vm_bo.inner().sgt.lock();
11251128
if vm_bo_guard.is_none() {
@@ -1235,11 +1238,11 @@ impl Vm {
12351238
// Removing whole mappings only does unmaps, so no preallocated VAs
12361239
let mut ctx = Default::default();
12371240

1238-
let mut inner = self.inner.exec_lock(Some(gem), false)?;
1241+
let inner = self.inner.exec_lock(Some(gem), false)?;
12391242

1240-
if let Some(bo) = inner.find_bo() {
1243+
if let Some(bo) = self.inner.find_bo(gem) {
12411244
mod_dev_dbg!(inner.dev, "MMU: bo_unmap\n");
1242-
inner.bo_unmap(&mut ctx, &bo)?;
1245+
self.inner.bo_unmap(&mut ctx, &bo)?;
12431246
mod_dev_dbg!(inner.dev, "MMU: bo_unmap done\n");
12441247
// We need to drop the exec_lock first, then the GpuVmBo since that will take the lock itself.
12451248
core::mem::drop(inner);
@@ -1258,6 +1261,11 @@ impl Vm {
12581261
pub(crate) fn is_extobj(&self, gem: &drm::gem::OpaqueObject<driver::AsahiDriver>) -> bool {
12591262
self.inner.is_extobj(gem)
12601263
}
1264+
1265+
/// Check whether an object is external to this GpuVm
1266+
pub(crate) fn bo_deferred_cleanup(&self) {
1267+
self.inner.bo_deferred_cleanup()
1268+
}
12611269
}
12621270

12631271
impl Drop for VmInner {

0 commit comments

Comments
 (0)