From mboxrd@z Thu Jan 1 00:00:00 1970 Received: from smtp.kernel.org (aws-us-west-2-korg-mail-alma10-1.taild15c8.ts.net [100.103.45.18]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id 9E6473AFAF4; Sun, 28 Jun 2026 14:54:47 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=100.103.45.18 ARC-Seal:i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1782658489; cv=none; b=LTcgpIiBtSll9iF9WnofDJn1K2JIECWyvlKTT8ogcC+imibMytW0nZVKg+SlzFv052xWVeCvBcxAbEdJZCf1sN0iDKL31w7UCoZ0nXmsJhDpBdCC/9h/tRziYmNMpwbc8Klo+u7TRVPyA9kCe57LGM54TdOHx1UnTRVaNLBbbRg= ARC-Message-Signature:i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1782658489; c=relaxed/simple; bh=HAhnRV20uR40ErH+QZ3Ql3RUxO3TME4yavNCD9jFXLA=; h=From:To:Cc:Subject:Date:Message-ID:In-Reply-To:References: MIME-Version; b=LJwW0sR1t4h2SlaTbeftPo2sJI67+hxU7fGk+qTXcs+p1cQrv78NwAAysaQ1KhzPHH/GsPngH4whJ2JZiJh4kNGZuUv4Sft0HZMmezwLZp0hGaS3rdKI3ynPhgaCBRtJAKg0C/0yq/5cxj5wO95B69yhUZbz+aRwsS2B3CPcEgs= ARC-Authentication-Results:i=1; smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=kernel.org header.i=@kernel.org header.b=FGDasNpB; arc=none smtp.client-ip=100.103.45.18 Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=kernel.org header.i=@kernel.org header.b="FGDasNpB" Received: by smtp.kernel.org (Postfix) with ESMTPSA id 67DFF1F00A3A; Sun, 28 Jun 2026 14:54:43 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=kernel.org; s=k20260515; t=1782658487; bh=VdXGSK9Hvwvp1qJCdS/hMb1N5+O8JKk6jdOeJFV41l0=; h=From:To:Cc:Subject:Date:In-Reply-To:References; b=FGDasNpBq2KwV9ETb3R0gpLiMQ+Mte0em+0bLdzNkEbEaysfL8s9m+p38vG8iJCxh 6Dt2C/KDQnMxbLVkg+4iIJEy3MPQh7B8p/SH0HPstNQlQ61y7aLyZGUd4T3z0IQXQU j9q12SCI30UKt9SEn4SlPV0sJQpRpDIgdYfctCymbV1LxI2cYvl68Srg2Nxlx2rILR 3F77WzFspp0phWU0CEdKd34o/9x+Yt8kLfa7z/RWy9NF+WVUQdfw8DThg7w8ll+3Tj w/zrrwaf/2SVu/0p3r6GEn+r2GK3stON3+XDQojZozqP6bFbMM9CQ9t1870LgkQc9P Rdl9AqmjvVr6Q== From: Danilo Krummrich To: dakr@kernel.org, aliceryhl@google.com, daniel.almeida@collabora.com, acourbot@nvidia.com, ecourtney@nvidia.com, ojeda@kernel.org, boqun@kernel.org, gary@garyguo.net, bjorn3_gh@protonmail.com, lossin@kernel.org, a.hindborg@kernel.org, tmgross@umich.edu, deborah.brouwer@collabora.com, boris.brezillon@collabora.com, lyude@redhat.com Cc: driver-core@lists.linux.dev, linux-kernel@vger.kernel.org, nova-gpu@lists.linux.dev, dri-devel@lists.freedesktop.org, rust-for-linux@vger.kernel.org Subject: [PATCH v5 08/19] rust: drm/gem: remove DeviceContext from shmem::Object Date: Sun, 28 Jun 2026 16:53:28 +0200 Message-ID: <20260628145406.2107056-9-dakr@kernel.org> X-Mailer: git-send-email 2.54.0 In-Reply-To: <20260628145406.2107056-1-dakr@kernel.org> References: <20260628145406.2107056-1-dakr@kernel.org> Precedence: bulk X-Mailing-List: nova-gpu@lists.linux.dev List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 Content-Transfer-Encoding: 8bit Now that AlwaysRefCounted is restricted to the Normal GEM Object context, there is no use for instantiating Object with a non-Normal context. Remove the DeviceContext generic parameter from shmem::Object and all associated types (VMap, VMapRef, VMapOwned, DmaResvGuard, SGTableMap), simplifying the API. Signed-off-by: Danilo Krummrich --- rust/kernel/drm/gem/shmem.rs | 121 +++++++++++++++-------------------- 1 file changed, 51 insertions(+), 70 deletions(-) diff --git a/rust/kernel/drm/gem/shmem.rs b/rust/kernel/drm/gem/shmem.rs index cf8410e0f228..e0ef47352e88 100644 --- a/rust/kernel/drm/gem/shmem.rs +++ b/rust/kernel/drm/gem/shmem.rs @@ -20,9 +20,7 @@ driver, gem, private::Sealed, - Device, - DeviceContext, - Normal, // + Device, // }, error::{ from_err_ptr, @@ -48,7 +46,6 @@ }; use core::{ ffi::c_void, - marker::PhantomData, mem::{ ManuallyDrop, MaybeUninit, // @@ -99,22 +96,20 @@ fn default() -> Self { /// /// - `obj` contains a valid initialized `struct drm_gem_shmem_object` for the lifetime of this /// object. -/// - Any type invariants of `C` apply to the parent DRM device for this GEM object. #[repr(C)] #[pin_data] -pub struct Object { +pub struct Object { #[pin] obj: Opaque, /// Parent object that owns this object's DMA reservation object. parent_resv_obj: Option>>, /// Devres object for unmapping any SGTable on driver-unbind. - sgt_res: ManuallyDrop>>>, + sgt_res: ManuallyDrop>>>, #[pin] /// Lock for protecting initialization of `sgt_res`. sgt_lock: Mutex<()>, #[pin] inner: T, - _ctx: PhantomData, } super::impl_aref_for_gem_obj! { @@ -124,12 +119,12 @@ impl for Object } // SAFETY: All GEM objects are thread-safe. -unsafe impl Send for Object {} +unsafe impl Send for Object {} // SAFETY: All GEM objects are thread-safe. -unsafe impl Sync for Object {} +unsafe impl Sync for Object {} -impl Object { +impl Object { /// `drm_gem_object_funcs` vtable suitable for GEM shmem objects. const VTABLE: bindings::drm_gem_object_funcs = bindings::drm_gem_object_funcs { free: Some(Self::free_callback), @@ -157,7 +152,7 @@ fn as_raw_shmem(&self) -> *mut bindings::drm_gem_shmem_object { } /// Returns the `Device` that owns this GEM object. - pub fn dev(&self) -> &Device { + pub fn dev(&self) -> &Device { // SAFETY: `dev` will have been initialized in `Self::new()` by `drm_gem_shmem_init()`. unsafe { Device::from_raw((*self.as_raw()).dev) } } @@ -171,8 +166,8 @@ extern "C" fn free_callback(obj: *mut bindings::drm_gem_object) { // SAFETY: // - We verified above that `obj` is valid, which makes `this` valid - // - This function is set in AllocOps, so we know that `this` is contained within a - // `Object` + // - This function is set in AllocOps, so we know that `this` is contained within an + // `Object` let this = unsafe { container_of!(Opaque::cast_from(base), Self, obj) }.cast_mut(); // We need to drop `sgt_res` first, since doing so requires that the GEM object is still @@ -193,7 +188,7 @@ extern "C" fn free_callback(obj: *mut bindings::drm_gem_object) { } /// Attempt to create a vmap from the gem object, and confirm the size of said vmap. - fn make_vmap<'a, R, const SIZE: usize>(&'a self) -> Result> + fn make_vmap<'a, R, const SIZE: usize>(&'a self) -> Result> where R: Deref + From<&'a Self>, { @@ -255,7 +250,7 @@ unsafe fn raw_vunmap(&self, mut map: bindings::iosys_map) { /// Creates and returns a virtual kernel memory mapping for this object. #[inline] - pub fn vmap(&self) -> Result> { + pub fn vmap(&self) -> Result> { self.make_vmap() } @@ -298,9 +293,7 @@ pub fn sg_table<'a>( Ok(sgt_res.access(dev)?) } -} -impl Object { /// Create a new shmem-backed DRM object of the given size. /// /// Additional config options can be specified using `config`. @@ -317,7 +310,6 @@ pub fn new( sgt_res: ManuallyDrop::new(SetOnce::new()), sgt_lock <- new_mutex!(()), inner <- T::new(dev, size, args), - _ctx: PhantomData, }), GFP_KERNEL, )?; @@ -351,12 +343,12 @@ pub fn new( /// Creates and returns an owned reference to a virtual kernel memory mapping for this object. #[inline] - pub fn owned_vmap(&self) -> Result> { + pub fn owned_vmap(&self) -> Result> { self.make_vmap() } } -impl Deref for Object { +impl Deref for Object { type Target = T; fn deref(&self) -> &Self::Target { @@ -364,15 +356,15 @@ fn deref(&self) -> &Self::Target { } } -impl DerefMut for Object { +impl DerefMut for Object { fn deref_mut(&mut self) -> &mut Self::Target { &mut self.inner } } -impl Sealed for Object {} +impl Sealed for Object {} -impl gem::IntoGEMObject for Object { +impl gem::IntoGEMObject for Object { fn as_raw(&self) -> *mut bindings::drm_gem_object { // SAFETY: // - Our immutable reference is proof that this is safe to dereference. @@ -391,7 +383,7 @@ unsafe fn from_raw<'a>(obj: *mut bindings::drm_gem_object) -> &'a Self { } } -impl driver::AllocImpl for Object { +impl driver::AllocImpl for Object { type Driver = T::Driver; const ALLOC_OPS: driver::AllocOps = driver::AllocOps { @@ -410,14 +402,11 @@ impl driver::AllocImpl for Object { /// When this is dropped, the `dma_resv` lock is dropped as well. /// // TODO: This should be replace with a WwMutex equivalent once we have such bindings in the kernel. -struct DmaResvGuard<'a, T: DriverObject, C: DeviceContext = Normal>( - &'a Object, - NotThreadSafe, -); +struct DmaResvGuard<'a, T: DriverObject>(&'a Object, NotThreadSafe); -impl<'a, T: DriverObject, C: DeviceContext> DmaResvGuard<'a, T, C> { +impl<'a, T: DriverObject> DmaResvGuard<'a, T> { #[inline] - fn new(obj: &'a Object) -> Self { + fn new(obj: &'a Object) -> Self { // SAFETY: This lock is initialized throughout the lifetime of `object`. unsafe { bindings::dma_resv_lock(obj.raw_dma_resv(), ptr::null_mut()) }; @@ -425,7 +414,7 @@ fn new(obj: &'a Object) -> Self { } } -impl<'a, T: DriverObject, C: DeviceContext> Drop for DmaResvGuard<'a, T, C> { +impl<'a, T: DriverObject> Drop for DmaResvGuard<'a, T> { #[inline] fn drop(&mut self) { // SAFETY: We are releasing the lock grabbed during the creation of this object. @@ -439,40 +428,37 @@ fn drop(&mut self) { /// /// - The size of `owner` is >= SIZE. /// - The memory pointed to by `addr` remains valid at least until this object is dropped. -pub struct VMap +pub struct VMap where D: DriverObject, - C: DeviceContext, - R: Deref>, + R: Deref>, { addr: *mut c_void, owner: R, } /// An alias type for a reference to a shmem-based GEM object's VMap. -pub type VMapRef<'a, D, C, const SIZE: usize = 0> = VMap, C, SIZE>; +pub type VMapRef<'a, D, const SIZE: usize = 0> = VMap, SIZE>; /// An alias type for an owned reference to a shmem-based GEM object's VMap. -pub type VMapOwned = VMap>, C, SIZE>; +pub type VMapOwned = VMap>, SIZE>; -impl VMap +impl VMap where D: DriverObject, - C: DeviceContext, - R: Deref>, + R: Deref>, { /// Borrows a reference to the object that owns this virtual mapping. #[inline] - pub fn owner(&self) -> &Object { + pub fn owner(&self) -> &Object { &self.owner } } -impl Drop for VMap +impl Drop for VMap where D: DriverObject, - C: DeviceContext, - R: Deref>, + R: Deref>, { #[inline] fn drop(&mut self) { @@ -491,29 +477,26 @@ fn drop(&mut self) { // SAFETY: `addr` points to a valid memory address for as long as `owner` exists, meaning that so // long as `owner` is `Send` so is `VMap`. -unsafe impl Send for VMap +unsafe impl Send for VMap where D: DriverObject, - C: DeviceContext, - R: Deref> + Send, + R: Deref> + Send, { } // SAFETY: `addr` points to a valid memory address for as long as `owner` exists, meaning that so // long as `owner` is `Sync` so is `VMap`. -unsafe impl Sync for VMap +unsafe impl Sync for VMap where D: DriverObject, - C: DeviceContext, - R: Deref> + Sync, + R: Deref> + Sync, { } -impl Io for VMap +impl Io for VMap where D: DriverObject, - C: DeviceContext, - R: Deref>, + R: Deref>, { #[inline] fn addr(&self) -> usize { @@ -526,22 +509,20 @@ fn maxsize(&self) -> usize { } } -impl IoKnownSize for VMap +impl IoKnownSize for VMap where D: DriverObject, - C: DeviceContext, - R: Deref>, + R: Deref>, { const MIN_SIZE: usize = SIZE; } macro_rules! impl_vmap_io_capable { ($ty:ty) => { - impl IoCapable<$ty> for VMap + impl IoCapable<$ty> for VMap where D: DriverObject, - C: DeviceContext, - R: Deref>, + R: Deref>, { #[inline] unsafe fn io_read(&self, address: usize) -> $ty { @@ -584,11 +565,11 @@ unsafe fn io_write(&self, value: $ty, address: usize) { /// [`SGTable`]. /// /// [`SGTable`]: scatterlist::SGTable -pub struct SGTableMap { - obj: NonNull>, +pub struct SGTableMap { + obj: NonNull>, } -impl Deref for SGTableMap { +impl Deref for SGTableMap { type Target = scatterlist::SGTable; fn deref(&self) -> &Self::Target { @@ -599,7 +580,7 @@ fn deref(&self) -> &Self::Target { } } -impl Drop for SGTableMap { +impl Drop for SGTableMap { fn drop(&mut self) { // SAFETY: `obj` is always valid via our type invariants let obj = unsafe { self.obj.as_ref() }; @@ -610,8 +591,8 @@ fn drop(&mut self) { } } -impl SGTableMap { - fn new(obj: &Object) -> impl Init { +impl SGTableMap { + fn new(obj: &Object) -> impl Init { // INVARIANT: // - We call drm_gem_shmem_get_pages_sgt below and check whether or not it succeeds, // fulfilling the invariant of SGTableMap that the object's `sgt` field is initialized. @@ -625,10 +606,10 @@ fn new(obj: &Object) -> impl Init { // SAFETY: The NonNull in SGTableMap is guaranteed valid by our type invariants, and the GEM object // it points to is guaranteed to be thread-safe. -unsafe impl Send for SGTableMap {} +unsafe impl Send for SGTableMap {} // SAFETY: The NonNull in SGTableMap is guaranteed valid by our type invariants, and the GEM object // it points to is guaranteed to be thread-safe. -unsafe impl Sync for SGTableMap {} +unsafe impl Sync for SGTableMap {} #[kunit_tests(rust_drm_gem_shmem)] mod tests { @@ -705,7 +686,7 @@ fn create_drm_dev() -> Result<(faux::Registration, UnregisteredDevice Result { let (_dev, drm) = create_drm_dev()?; - let obj = Object::::new(&drm, PAGE_SIZE, ObjectConfig::default(), ())?; + let obj = Object::::new(&drm, PAGE_SIZE, ObjectConfig::default(), ())?; // Try creating a normal vmap obj.vmap::()?; @@ -729,7 +710,7 @@ fn compile_time_vmap_sizes() -> Result { fn vmap_io() -> Result { let (_dev, drm) = create_drm_dev()?; - let obj = Object::::new(&drm, PAGE_SIZE, ObjectConfig::default(), ())?; + let obj = Object::::new(&drm, PAGE_SIZE, ObjectConfig::default(), ())?; let vmap = obj.vmap::()?; @@ -761,7 +742,7 @@ fn fail_sg_table_on_wrong_dev() -> Result { let reg = faux::Registration::new(c"EvilKunit", None)?; let wrong_dev = reg.as_ref(); - let obj = Object::::new(&drm, PAGE_SIZE, ObjectConfig::default(), ())?; + let obj = Object::::new(&drm, PAGE_SIZE, ObjectConfig::default(), ())?; assert_eq!(obj.sg_table(wrong_dev.as_ref()).err().unwrap(), EINVAL); -- 2.54.0