summaryrefslogtreecommitdiff
path: root/rust/kernel/drm/gem
diff options
context:
space:
mode:
authorLyude Paul <lyude@redhat.com>2025-05-14 01:09:57 +0300
committerDanilo Krummrich <dakr@kernel.org>2025-05-14 01:37:16 +0300
commit38cb08c3fcd3f3b1d0225dcec8ae50fab5751549 (patch)
tree2392983925ccb991cfe914db6da173b417fba6a1 /rust/kernel/drm/gem
parentb36ff40b4abd0f468564cfe9805f0d8e850cafe9 (diff)
downloadlinux-38cb08c3fcd3f3b1d0225dcec8ae50fab5751549.tar.xz
rust: drm: gem: Implement AlwaysRefCounted for all gem objects automatically
Currently we are requiring AlwaysRefCounted in most trait bounds for gem objects, and implementing it by hand for our only current type of gem object. However, all gem objects use the same functions for reference counting - and all gem objects support reference counting. We're planning on adding support for shmem gem objects, let's move this around a bit by instead making IntoGEMObject require AlwaysRefCounted as a trait bound, and then provide a blanket AlwaysRefCounted implementation for any object that implements IntoGEMObject so all gem object types can use the same AlwaysRefCounted implementation. This also makes things less verbose by making the AlwaysRefCounted trait bound implicit for any IntoGEMObject bound. Signed-off-by: Lyude Paul <lyude@redhat.com> Reviewed-by: Daniel Almeida <daniel.almeida@collabora.com> Link: https://lore.kernel.org/r/20250513221046.903358-5-lyude@redhat.com Signed-off-by: Danilo Krummrich <dakr@kernel.org>
Diffstat (limited to 'rust/kernel/drm/gem')
-rw-r--r--rust/kernel/drm/gem/mod.rs47
1 files changed, 24 insertions, 23 deletions
diff --git a/rust/kernel/drm/gem/mod.rs b/rust/kernel/drm/gem/mod.rs
index e11cf7837bf5..d8765e61c6c2 100644
--- a/rust/kernel/drm/gem/mod.rs
+++ b/rust/kernel/drm/gem/mod.rs
@@ -10,7 +10,7 @@ use crate::{
drm::driver::{AllocImpl, AllocOps},
error::{to_result, Result},
prelude::*,
- types::{ARef, Opaque},
+ types::{ARef, AlwaysRefCounted, Opaque},
};
use core::{mem, ops::Deref, ptr::NonNull};
@@ -36,7 +36,7 @@ pub trait BaseDriverObject<T: BaseObject>: Sync + Send + Sized {
}
/// Trait that represents a GEM object subtype
-pub trait IntoGEMObject: Sized + super::private::Sealed {
+pub trait IntoGEMObject: Sized + super::private::Sealed + AlwaysRefCounted {
/// Owning driver for this type
type Driver: drm::Driver;
@@ -54,6 +54,26 @@ pub trait IntoGEMObject: Sized + super::private::Sealed {
unsafe fn as_ref<'a>(self_ptr: *mut bindings::drm_gem_object) -> &'a Self;
}
+// SAFETY: All gem objects are refcounted.
+unsafe impl<T: IntoGEMObject> AlwaysRefCounted for T {
+ fn inc_ref(&self) {
+ // SAFETY: The existence of a shared reference guarantees that the refcount is non-zero.
+ unsafe { bindings::drm_gem_object_get(self.as_raw()) };
+ }
+
+ unsafe fn dec_ref(obj: NonNull<Self>) {
+ // SAFETY: We either hold the only refcount on `obj`, or one of many - meaning that no one
+ // else could possibly hold a mutable reference to `obj` and thus this immutable reference
+ // is safe.
+ let obj = unsafe { obj.as_ref() }.as_raw();
+
+ // SAFETY:
+ // - The safety requirements guarantee that the refcount is non-zero.
+ // - We hold no references to `obj` now, making it safe for us to potentially deallocate it.
+ unsafe { bindings::drm_gem_object_put(obj) };
+ }
+}
+
/// Trait which must be implemented by drivers using base GEM objects.
pub trait DriverObject: BaseDriverObject<Object<Self>> {
/// Parent `Driver` for this object.
@@ -112,10 +132,7 @@ impl<T: DriverObject> IntoGEMObject for Object<T> {
}
/// Base operations shared by all GEM object classes
-pub trait BaseObject
-where
- Self: crate::types::AlwaysRefCounted + IntoGEMObject,
-{
+pub trait BaseObject: IntoGEMObject {
/// Returns the size of the object in bytes.
fn size(&self) -> usize {
// SAFETY: `self.as_raw()` is guaranteed to be a pointer to a valid `struct drm_gem_object`.
@@ -172,7 +189,7 @@ where
}
}
-impl<T> BaseObject for T where Self: crate::types::AlwaysRefCounted + IntoGEMObject {}
+impl<T: IntoGEMObject> BaseObject for T {}
/// A base GEM object.
///
@@ -266,22 +283,6 @@ impl<T: DriverObject> Object<T> {
}
}
-// SAFETY: Instances of `Object<T>` are always reference-counted.
-unsafe impl<T: DriverObject> crate::types::AlwaysRefCounted for Object<T> {
- fn inc_ref(&self) {
- // SAFETY: The existence of a shared reference guarantees that the refcount is non-zero.
- unsafe { bindings::drm_gem_object_get(self.as_raw()) };
- }
-
- unsafe fn dec_ref(obj: NonNull<Self>) {
- // SAFETY: `obj` is a valid pointer to an `Object<T>`.
- let obj = unsafe { obj.as_ref() };
-
- // SAFETY: The safety requirements guarantee that the refcount is non-zero.
- unsafe { bindings::drm_gem_object_put(obj.as_raw()) }
- }
-}
-
impl<T: DriverObject> super::private::Sealed for Object<T> {}
impl<T: DriverObject> Deref for Object<T> {