mirror of
https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
synced 2026-08-31 11:41:29 -04:00
drm/tyr: add a kernel buffer object
Introduce a buffer object type (KernelBo) for internal driver allocations that are managed by the kernel rather than userspace. KernelBo wraps a GEM shmem object and automatically handles GPU virtual address space mapping during creation and unmapping on drop. This provides a safe and convenient way for the driver to both allocate and clean up internal buffers for kernel-managed resources. Co-developed-by: Boris Brezillon <boris.brezillon@collabora.com> Signed-off-by: Boris Brezillon <boris.brezillon@collabora.com> Signed-off-by: Deborah Brouwer <deborah.brouwer@collabora.com> Link: https://patch.msgid.link/20260728-fw-boot-b4-v10-5-9187aefa3f2f@collabora.com Signed-off-by: Alice Ryhl <aliceryhl@google.com>
This commit is contained in:
committed by
Alice Ryhl
parent
f2dc32d5a1
commit
e38e457b59
@@ -4,18 +4,29 @@
|
||||
//! This module provides buffer object (BO) management functionality using
|
||||
//! DRM's GEM subsystem with shmem backing.
|
||||
|
||||
use core::ops::Range;
|
||||
|
||||
use kernel::{
|
||||
drm::gem::{
|
||||
self,
|
||||
shmem, //
|
||||
},
|
||||
prelude::*,
|
||||
sync::aref::ARef, //
|
||||
sync::{
|
||||
aref::ARef,
|
||||
Arc, //
|
||||
}, //
|
||||
};
|
||||
|
||||
use crate::driver::{
|
||||
TyrDrmDevice,
|
||||
TyrDrmDriver, //
|
||||
use crate::{
|
||||
driver::{
|
||||
TyrDrmDevice,
|
||||
TyrDrmDriver, //
|
||||
},
|
||||
vm::{
|
||||
Vm,
|
||||
VmMapFlags, //
|
||||
},
|
||||
};
|
||||
|
||||
/// Tyr's DriverObject type for GEM objects.
|
||||
@@ -56,3 +67,97 @@ pub(crate) fn new_dummy_object(ddev: &TyrDrmDevice) -> Result<ARef<Bo>> {
|
||||
|
||||
Ok(bo)
|
||||
}
|
||||
|
||||
/// Specifies how to choose a GPU virtual address for a [`KernelBo`].
|
||||
/// An automatic VA allocation strategy will be added in the future.
|
||||
pub(crate) enum KernelBoVaAlloc {
|
||||
/// Explicit VA address specified by the caller.
|
||||
#[expect(dead_code)]
|
||||
Explicit(u64),
|
||||
}
|
||||
|
||||
/// A kernel-owned buffer object with automatic GPU virtual address mapping.
|
||||
///
|
||||
/// This structure represents a buffer object that is created and managed entirely
|
||||
/// by the kernel driver, as opposed to userspace-created GEM objects. It combines
|
||||
/// a GEM object with automatic GPU virtual address (VA) space mapping and cleanup.
|
||||
///
|
||||
/// When dropped, the buffer is automatically unmapped from the GPU VA space.
|
||||
pub(crate) struct KernelBo<'drm> {
|
||||
/// The underlying GEM buffer object.
|
||||
bo: ARef<Bo>,
|
||||
/// The GPU VM this buffer is mapped into.
|
||||
vm: Arc<Vm<'drm>>,
|
||||
/// The GPU VA range occupied by this buffer.
|
||||
va_range: Range<u64>,
|
||||
}
|
||||
|
||||
impl<'drm> KernelBo<'drm> {
|
||||
/// Creates a new kernel-owned buffer object and maps it into GPU VA space.
|
||||
///
|
||||
/// This function allocates a new shmem-backed GEM object and immediately maps
|
||||
/// it into the specified GPU virtual memory space. The mapping is automatically
|
||||
/// cleaned up when the [`KernelBo`] is dropped.
|
||||
#[expect(dead_code)]
|
||||
pub(crate) fn new(
|
||||
ddev: &TyrDrmDevice,
|
||||
vm: Arc<Vm<'drm>>,
|
||||
size: u64,
|
||||
va_alloc: KernelBoVaAlloc,
|
||||
flags: VmMapFlags,
|
||||
) -> Result<Self> {
|
||||
if size == 0 {
|
||||
dev_err!(vm.dev(), "Cannot create KernelBo with size 0");
|
||||
return Err(EINVAL);
|
||||
}
|
||||
|
||||
let KernelBoVaAlloc::Explicit(va) = va_alloc;
|
||||
|
||||
let bo_size = usize::try_from(size).map_err(|_| EOVERFLOW)?;
|
||||
let va_end = va.checked_add(size).ok_or(EINVAL)?;
|
||||
|
||||
let bo = Bo::new(
|
||||
ddev,
|
||||
bo_size,
|
||||
shmem::ObjectConfig {
|
||||
map_wc: true,
|
||||
parent_resv_obj: None,
|
||||
},
|
||||
BoCreateArgs { flags: 0 },
|
||||
)?;
|
||||
|
||||
vm.map_bo_range(&bo, 0, size, va, flags)?;
|
||||
|
||||
Ok(KernelBo {
|
||||
bo,
|
||||
vm,
|
||||
va_range: va..va_end,
|
||||
})
|
||||
}
|
||||
|
||||
#[expect(dead_code)]
|
||||
pub(crate) fn bo(&self) -> &Bo {
|
||||
&self.bo
|
||||
}
|
||||
}
|
||||
|
||||
impl Drop for KernelBo<'_> {
|
||||
fn drop(&mut self) {
|
||||
let va = self.va_range.start;
|
||||
let size = self.va_range.end - self.va_range.start;
|
||||
|
||||
if let Err(e) = self.vm.unmap_range(va, size) {
|
||||
// If unmap_range fails, it is still safe to drop the
|
||||
// KernelBo and its ARef to the GEM buffer object because
|
||||
// GPUVM also holds a reference to the GEM buffer object.
|
||||
// The physical pages won't be freed or reallocated.
|
||||
dev_err!(
|
||||
self.vm.dev(),
|
||||
"Failed to unmap KernelBo range {:#x}..{:#x}: {:?}",
|
||||
self.va_range.start,
|
||||
self.va_range.end,
|
||||
e
|
||||
);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user