Skip to content

Commit 69f7c5c

Browse files
committed
drm/asahi: Add support for initializing GpuObjects with init!()
Signed-off-by: Asahi Lina <[email protected]>
1 parent 8fb0d53 commit 69f7c5c

2 files changed

Lines changed: 77 additions & 0 deletions

File tree

drivers/gpu/drm/asahi/alloc.rs

Lines changed: 37 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -267,6 +267,43 @@ pub(crate) trait Allocator {
267267
)
268268
}
269269

270+
/// Allocate a new GpuStruct object. See [`GpuObject::new_init_prealloc`].
271+
#[inline(never)]
272+
fn new_init_prealloc<
273+
'a,
274+
T: GpuStruct,
275+
I: Init<T, kernel::error::Error>,
276+
R: PinInit<T::Raw<'a>, kernel::error::Error>,
277+
>(
278+
&mut self,
279+
inner_init: impl FnOnce(GpuWeakPointer<T>) -> I,
280+
raw_init: impl FnOnce(&'a T, GpuWeakPointer<T>) -> R,
281+
) -> Result<GpuObject<T, GenericAlloc<T, Self::Raw>>> {
282+
GpuObject::<T, GenericAlloc<T, Self::Raw>>::new_init_prealloc(
283+
self.alloc_object()?,
284+
inner_init,
285+
raw_init,
286+
)
287+
}
288+
289+
/// Allocate a new GpuStruct object. See [`GpuObject::new_init`].
290+
#[inline(never)]
291+
fn new_init<'a, T: GpuStruct, R: PinInit<T::Raw<'a>, F>, E, F>(
292+
&mut self,
293+
inner_init: impl Init<T, E>,
294+
raw_init: impl FnOnce(&'a T, GpuWeakPointer<T>) -> R,
295+
) -> Result<GpuObject<T, GenericAlloc<T, Self::Raw>>>
296+
where
297+
kernel::error::Error: core::convert::From<E>,
298+
kernel::error::Error: core::convert::From<F>,
299+
{
300+
GpuObject::<T, GenericAlloc<T, Self::Raw>>::new_init_prealloc(
301+
self.alloc_object()?,
302+
|_p| inner_init,
303+
raw_init,
304+
)
305+
}
306+
270307
/// Allocate a generic buffer of the given size and alignment, applying the debug features if
271308
/// enabled to tag it and detect overflows.
272309
fn alloc_generic<T>(

drivers/gpu/drm/asahi/object.rs

Lines changed: 40 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -380,6 +380,46 @@ impl<T: GpuStruct, U: Allocation<T>> GpuObject<T, U> {
380380
})
381381
}
382382

383+
/// Create a new GpuObject given an allocator and the boxed inner data (a type implementing
384+
/// GpuStruct).
385+
///
386+
/// The caller passes a closure that initializes the `T::Raw` type given a reference to the
387+
/// `GpuStruct` and a `MaybeUninit<T::Raw>`. This is intended to be used with the place!()
388+
/// macro to avoid constructing the whole `T::Raw` object on the stack.
389+
pub(crate) fn new_init_prealloc<'a, I: Init<T, E>, R: PinInit<T::Raw<'a>, F>, E, F>(
390+
alloc: U,
391+
inner_init: impl FnOnce(GpuWeakPointer<T>) -> I,
392+
raw_init: impl FnOnce(&'a T, GpuWeakPointer<T>) -> R,
393+
) -> Result<Self>
394+
where
395+
kernel::error::Error: core::convert::From<E>,
396+
kernel::error::Error: core::convert::From<F>,
397+
{
398+
if alloc.size() < mem::size_of::<T::Raw<'static>>() {
399+
return Err(ENOMEM);
400+
}
401+
let gpu_ptr =
402+
GpuWeakPointer::<T>(NonZeroU64::new(alloc.gpu_ptr()).ok_or(EINVAL)?, PhantomData);
403+
mod_dev_dbg!(
404+
alloc.device(),
405+
"Allocating {} @ {:#x}\n",
406+
core::any::type_name::<T>(),
407+
alloc.gpu_ptr()
408+
);
409+
let inner = inner_init(gpu_ptr);
410+
let p = alloc.ptr().ok_or(EINVAL)?.as_ptr() as *mut T::Raw<'_>;
411+
let ret = Self {
412+
raw: p as *mut u8 as *mut T::Raw<'static>,
413+
gpu_ptr,
414+
alloc,
415+
inner: Box::init(inner)?,
416+
};
417+
let q = &*ret.inner as *const T;
418+
// SAFETY: `p` is guaranteed to be valid per the Allocation invariant.
419+
unsafe { raw_init(&*q, gpu_ptr).__pinned_init(p) }?;
420+
Ok(ret)
421+
}
422+
383423
/// Returns the GPU VA of this object (as a raw [`NonZeroU64`])
384424
pub(crate) fn gpu_va(&self) -> NonZeroU64 {
385425
self.gpu_ptr.0

0 commit comments

Comments
 (0)