diff options
-rw-r--r-- | rust/kernel/drm/gem/mod.rs | 47 |
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> { |