public inbox for linux-kernel@vger.kernel.org
 help / color / mirror / Atom feed
From: Lyude Paul <lyude@redhat.com>
To: dri-devel@lists.freedesktop.org, rust-for-linux@vger.kernel.org
Cc: "Asahi Lina" <lina@asahilina.net>,
	"Danilo Krummrich" <dakr@kernel.org>,
	mcanal@igalia.com, airlied@redhat.com, zhiw@nvidia.com,
	cjia@nvidia.com, jhubbard@nvidia.com,
	"Miguel Ojeda" <ojeda@kernel.org>,
	"Alex Gaynor" <alex.gaynor@gmail.com>,
	"Wedson Almeida Filho" <wedsonaf@gmail.com>,
	"Boqun Feng" <boqun.feng@gmail.com>,
	"Gary Guo" <gary@garyguo.net>,
	"Björn Roy Baron" <bjorn3_gh@protonmail.com>,
	"Benno Lossin" <benno.lossin@proton.me>,
	"Andreas Hindborg" <a.hindborg@samsung.com>,
	"Alice Ryhl" <aliceryhl@google.com>,
	"Trevor Gross" <tmgross@umich.edu>,
	"Danilo Krummrich" <dakr@redhat.com>,
	"Mika Westerberg" <mika.westerberg@linux.intel.com>,
	linux-kernel@vger.kernel.org (open list)
Subject: [WIP RFC v2 04/35] rust: drm/kms: Introduce the main ModeConfigObject traits
Date: Mon, 30 Sep 2024 19:09:47 -0400	[thread overview]
Message-ID: <20240930233257.1189730-5-lyude@redhat.com> (raw)
In-Reply-To: <20240930233257.1189730-1-lyude@redhat.com>

The KMS API has a very consistent idea of a "mode config object", which
includes any object with a drm_mode_object struct embedded in it. These
objects have their own object IDs which DRM exposes to userspace, and we
introduce the ModeConfigObject trait to represent any object matching these
characteristics.

One slightly less consistent trait of these objects however: some mode
objects have a reference count, while others don't. Since rust requires
that we are able to define the lifetime of an object up-front, we introduce
two other super-traits of ModeConfigObject for this:

* StaticModeObject - this trait represents any mode object which does not
  have a reference count of its own. Such objects can be considered to
  share the lifetime of their parent KMS device
* RcModeObject - this trait represents any mode object which does have its
  own reference count. Objects implementing this trait get a free blanket
  implementation of AlwaysRefCounted, and as such can be used with the ARef
  container without us having to implement AlwaysRefCounted for each
  individual mode object.

This will be able to handle most lifetimes we'll need with one exception:
it's entirely possible a driver may want to hold a "owned" reference to a
static mode object. We allow for this by introducing the KmsRef container,
which grabs an owned refcount to the parent KMS device of a
StaticModeObject and holds a pointer to said object - essentially allowing
it to act identically to an owned refcount by preventing the device's
lifetime from ending until the KmsRef is dropped. I choose not to use
AlwaysRefCounted for this as holding a refcount to the device has its own
set of implications since if you forget to drop the KmsRef the device will
never be destroyed.

Signed-off-by: Lyude Paul <lyude@redhat.com>
---
 rust/bindings/bindings_helper.h |   1 +
 rust/kernel/drm/kms.rs          | 107 ++++++++++++++++++++++++++++++++
 2 files changed, 108 insertions(+)

diff --git a/rust/bindings/bindings_helper.h b/rust/bindings/bindings_helper.h
index 9803e0ecac7c1..ba1871b05b7fa 100644
--- a/rust/bindings/bindings_helper.h
+++ b/rust/bindings/bindings_helper.h
@@ -17,6 +17,7 @@
 #include <drm/drm_gem.h>
 #include <drm/drm_gem_framebuffer_helper.h>
 #include <drm/drm_gem_shmem_helper.h>
+#include <drm/drm_mode_object.h>
 #include <drm/drm_ioctl.h>
 #include <kunit/test.h>
 #include <linux/blk-mq.h>
diff --git a/rust/kernel/drm/kms.rs b/rust/kernel/drm/kms.rs
index d3558a5eccc54..f1a8ba4b7e296 100644
--- a/rust/kernel/drm/kms.rs
+++ b/rust/kernel/drm/kms.rs
@@ -228,3 +228,110 @@ impl<T, K> KmsDriver for T
 where
     T: Driver<Kms = K>,
     K: Kms<Driver = T> {}
+
+/// A modesetting object in DRM.
+///
+/// This is any type of object where the underlying C object contains a [`struct drm_mode_object`].
+///
+/// [`struct drm_mode_object`]: srctree/include/drm/drm_mode_object.h
+pub trait ModeObject: Sealed + Send + Sync {
+    /// The parent driver for this [`ModeObject`].
+    type Driver: KmsDriver;
+
+    /// Return the [`Device`] for this [`ModeObject`].
+    fn drm_dev(&self) -> &Device<Self::Driver>;
+
+    /// Return a pointer to the [`struct drm_mode_object`] for this [`ModeObject`].
+    ///
+    /// [`struct drm_mode_object`]: (srctree/include/drm/drm_mode_object.h)
+    fn raw_mode_obj(&self) -> *mut bindings::drm_mode_object;
+}
+
+/// A trait for modesetting objects which don't come with their own reference-counting.
+///
+/// Some [`ModeObject`] types in DRM do not have a reference count. These types are considered
+/// "static" and share the lifetime of their parent [`Device`]. To retrieve an owned reference to
+/// such types, see [`KmsRef`].
+///
+/// # Safety
+///
+/// This trait must only be implemented for modesetting objects which do not have a refcount within
+/// their [`struct drm_mode_object`], otherwise [`KmsRef`] can't guarantee the object will stay
+/// alive.
+///
+/// [`struct drm_mode_object`]: (srctree/include/drm/drm_mode_object.h)
+pub unsafe trait StaticModeObject: ModeObject {}
+
+/// An owned reference to a [`StaticModeObject`].
+///
+/// Note that since [`StaticModeObject`] types share the lifetime of their parent [`Device`], the
+/// parent [`Device`] will stay alive as long as this type exists. Thus, users should be aware that
+/// storing a [`KmsRef`] within a [`ModeObject`] is a circular reference.
+///
+/// # Invariants
+///
+/// `self.0` points to a valid instance of `T` throughout the lifetime of this type.
+pub struct KmsRef<T: StaticModeObject>(NonNull<T>);
+
+// SAFETY: Owned references to DRM device are thread-safe.
+unsafe impl<T: StaticModeObject> Send for KmsRef<T> {}
+unsafe impl<T: StaticModeObject> Sync for KmsRef<T> {}
+
+impl<T: StaticModeObject> From<&T> for KmsRef<T> {
+    fn from(value: &T) -> Self {
+        // We will drop the reference we leak here in Drop
+        value.drm_dev().inc_ref();
+
+        Self(value.into())
+    }
+}
+
+impl<T: StaticModeObject> Drop for KmsRef<T> {
+    fn drop(&mut self) {
+        // SAFETY: We're reclaiming the reference we leaked in From<&T>
+        drop(unsafe { ARef::from_raw(self.drm_dev().into()) })
+    }
+}
+
+impl<T: StaticModeObject> Deref for KmsRef<T> {
+    type Target = T;
+
+    fn deref(&self) -> &Self::Target {
+        // SAFETY: We're guaranteed object will point to a valid object as long as we hold dev
+        unsafe { self.0.as_ref() }
+    }
+}
+
+impl<T: StaticModeObject> Clone for KmsRef<T> {
+    fn clone(&self) -> Self {
+        self.drm_dev().inc_ref();
+
+        Self(self.0)
+    }
+}
+
+/// A trait for [`ModeObject`] which is reference counted.
+///
+/// This trait is implemented by DRM for any [`ModeObject`] which has a reference count provided by
+/// [`struct drm_mode_object`]. It provides a common implementation of [`AlwaysRefCounted`], since
+/// all [`RcModeObject`] types use the same functions for refcounting.
+///
+/// # Safety
+///
+/// The [`ModeObject`] must initialize the refcount in its [`struct drm_mode_object`] field.
+///
+/// [`struct drm_mode_object`]: (srctree/include/drm/drm_mode_object.h)
+pub unsafe trait RcModeObject: ModeObject {}
+
+unsafe impl<T: RcModeObject> AlwaysRefCounted for T {
+    fn inc_ref(&self) {
+        // SAFETY: FFI call with no special requirements
+        unsafe { bindings::drm_mode_object_get(self.raw_mode_obj()) }
+    }
+
+    unsafe fn dec_ref(obj: ptr::NonNull<Self>) {
+        // SAFETY: We never expose modesetting objects in our interfaces to users before they're
+        // initialized
+        unsafe { bindings::drm_mode_object_put(obj.as_ref().raw_mode_obj()) }
+    }
+}
-- 
2.46.1


  parent reply	other threads:[~2024-09-30 23:37 UTC|newest]

Thread overview: 109+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
     [not found] <20240930233257.1189730-1-lyude@redhat.com>
2024-09-30 23:09 ` [WIP RFC v2 01/35] WIP: rust/drm: Add fourcc bindings Lyude Paul
2024-10-01  9:25   ` Jani Nikula
2024-10-01 15:18     ` Miguel Ojeda
2024-10-03  8:33   ` Louis Chauvet
2024-10-03 20:16     ` Lyude Paul
2024-11-26 17:40   ` Daniel Almeida
2024-11-27 21:11     ` Lyude Paul
2025-01-14 18:54       ` Daniel Almeida
2024-09-30 23:09 ` [WIP RFC v2 02/35] WIP: rust: drm: Add traits for registering KMS devices Lyude Paul
2024-11-26 18:18   ` Daniel Almeida
2024-11-27 21:21     ` Lyude Paul
2024-12-05 14:03       ` Daniel Almeida
2024-12-03 22:41     ` Lyude Paul
2024-12-05 13:43       ` Daniel Almeida
2024-12-06 15:23   ` Alice Ryhl
2024-12-09 23:20     ` Lyude Paul
2024-09-30 23:09 ` [WIP RFC v2 03/35] rust: drm/kms/fbdev: Add FbdevShmem Lyude Paul
2024-11-26 19:58   ` Daniel Almeida
2024-09-30 23:09 ` Lyude Paul [this message]
2024-11-26 20:34   ` [WIP RFC v2 04/35] rust: drm/kms: Introduce the main ModeConfigObject traits Daniel Almeida
2024-09-30 23:09 ` [WIP RFC v2 05/35] rust: drm/kms: Add bindings for drm_connector Lyude Paul
2024-11-26 21:25   ` Daniel Almeida
2024-12-04 21:16     ` Lyude Paul
2024-12-04 21:18       ` Lyude Paul
2024-12-10 23:41     ` Lyude Paul
2024-12-11  8:43       ` Simona Vetter
2024-12-12  0:34         ` Lyude Paul
2024-12-12 10:03           ` Simona Vetter
2024-09-30 23:09 ` [WIP RFC v2 06/35] rust: drm/kms: Add drm_plane bindings Lyude Paul
2024-10-03  8:30   ` Louis Chauvet
2024-10-03 20:06     ` Lyude Paul
2024-11-27 14:05   ` Daniel Almeida
2024-12-12 21:28     ` Lyude Paul
2024-09-30 23:09 ` [WIP RFC v2 07/35] WIP: rust: drm/kms: Add drm_crtc bindings Lyude Paul
2024-11-27 14:36   ` Daniel Almeida
2024-12-12 22:25     ` Lyude Paul
2024-09-30 23:09 ` [WIP RFC v2 08/35] rust: drm/kms: Add bindings for drm_encoder Lyude Paul
2024-09-30 23:09 ` [WIP RFC v2 09/35] WIP: rust: drm/kms: Add Connector.attach_encoder() Lyude Paul
2024-11-27 14:43   ` Daniel Almeida
2024-09-30 23:09 ` [WIP RFC v2 10/35] rust: drm/kms: Add DriverConnector::get_mode callback Lyude Paul
2024-11-27 15:03   ` Daniel Almeida
2024-12-12 22:37     ` Lyude Paul
2024-09-30 23:09 ` [WIP RFC v2 11/35] rust: drm/kms: Add ConnectorGuard::add_modes_noedid() Lyude Paul
2024-11-27 15:06   ` Daniel Almeida
2024-09-30 23:09 ` [WIP RFC v2 12/35] rust: drm/kms: Add ConnectorGuard::set_preferred_mode Lyude Paul
2024-11-27 15:11   ` Daniel Almeida
2024-09-30 23:09 ` [WIP RFC v2 13/35] WIP: rust: drm/kms: Add OpaqueConnector and OpaqueConnectorState Lyude Paul
2024-11-27 15:51   ` Daniel Almeida
2024-12-05 23:25     ` Lyude Paul
2024-09-30 23:09 ` [WIP RFC v2 14/35] WIP: rust: drm/kms: Add OpaqueCrtc and OpaqueCrtcState Lyude Paul
2024-11-27 16:00   ` Daniel Almeida
2024-12-12 23:01     ` Lyude Paul
2024-09-30 23:09 ` [WIP RFC v2 15/35] WIP: rust: drm/kms: Add OpaquePlane and OpaquePlaneState Lyude Paul
2024-11-27 17:03   ` Daniel Almeida
2024-09-30 23:09 ` [WIP RFC v2 16/35] rust: drm/kms: Add RawConnector and RawConnectorState Lyude Paul
2024-11-27 19:26   ` Daniel Almeida
2024-09-30 23:10 ` [WIP RFC v2 17/35] rust: drm/kms: Add RawCrtc and RawCrtcState Lyude Paul
2024-11-27 19:29   ` Daniel Almeida
2024-09-30 23:10 ` [WIP RFC v2 18/35] rust: drm/kms: Add RawPlane and RawPlaneState Lyude Paul
2024-11-27 19:30   ` Daniel Almeida
2024-09-30 23:10 ` [WIP RFC v2 19/35] WIP: rust: drm/kms: Add OpaqueEncoder Lyude Paul
2024-11-27 19:35   ` Daniel Almeida
2024-09-30 23:10 ` [WIP RFC v2 20/35] WIP: rust: drm/kms: Add drm_atomic_state bindings Lyude Paul
2024-11-27 20:54   ` Daniel Almeida
2024-12-12 23:37     ` Lyude Paul
2024-09-30 23:10 ` [WIP RFC v2 21/35] rust: drm/kms: Introduce DriverCrtc::atomic_check() Lyude Paul
2024-11-28 13:37   ` Daniel Almeida
2025-01-13 23:43     ` Lyude Paul
2024-09-30 23:10 ` [WIP RFC v2 22/35] rust: drm/kms: Add DriverPlane::atomic_update() Lyude Paul
2024-11-28 13:38   ` Daniel Almeida
2025-01-13 23:47     ` Lyude Paul
2024-11-28 13:51   ` Daniel Almeida
2025-01-13 23:53     ` Lyude Paul
2024-09-30 23:10 ` [WIP RFC v2 23/35] rust: drm/kms: Add DriverPlane::atomic_check() Lyude Paul
2024-11-28 13:49   ` Daniel Almeida
2025-01-13 23:51     ` Lyude Paul
2024-09-30 23:10 ` [WIP RFC v2 24/35] rust: drm/kms: Add RawCrtcState::active() Lyude Paul
2024-11-28 13:54   ` Daniel Almeida
2024-09-30 23:10 ` [WIP RFC v2 25/35] rust: drm/kms: Add RawPlaneState::crtc() Lyude Paul
2024-11-28 13:58   ` Daniel Almeida
2024-09-30 23:10 ` [WIP RFC v2 26/35] WIP: rust: drm/kms: Add RawPlaneState::atomic_helper_check() Lyude Paul
2024-11-28 14:04   ` Daniel Almeida
2025-01-13 23:57     ` Lyude Paul
2025-01-14 14:07       ` Simona Vetter
2024-09-30 23:10 ` [WIP RFC v2 27/35] rust: drm/kms: Add drm_framebuffer bindings Lyude Paul
2024-11-28 14:26   ` Daniel Almeida
2024-09-30 23:10 ` [WIP RFC v2 28/35] rust: drm/kms: Add RawPlane::framebuffer() Lyude Paul
2024-11-28 14:29   ` Daniel Almeida
2025-01-14  0:03     ` Lyude Paul
2025-01-14 14:09       ` Simona Vetter
2024-09-30 23:10 ` [WIP RFC v2 29/35] rust: drm/kms: Add DriverCrtc::atomic_begin() and atomic_flush() Lyude Paul
2024-11-28 14:31   ` Daniel Almeida
2024-09-30 23:10 ` [WIP RFC v2 30/35] rust: drm/kms: Add DriverCrtc::atomic_enable() and atomic_disable() Lyude Paul
2024-11-28 14:33   ` Daniel Almeida
2024-09-30 23:10 ` [WIP RFC v2 31/35] rust: drm: Add Device::event_lock() Lyude Paul
2024-11-28 14:35   ` Daniel Almeida
2024-09-30 23:10 ` [WIP RFC v2 32/35] rust: drm/kms: Add Device::num_crtcs() Lyude Paul
2024-11-28 14:38   ` Daniel Almeida
2025-01-14  0:05     ` Lyude Paul
2024-09-30 23:10 ` [WIP RFC v2 33/35] WIP: rust: drm/kms: Add VblankSupport Lyude Paul
2024-12-05 15:29   ` Daniel Almeida
2025-01-14  0:43     ` Lyude Paul
2025-01-14 14:24       ` Simona Vetter
2025-01-14 15:04         ` Miguel Ojeda
2025-01-14 15:38           ` Simona Vetter
2024-09-30 23:10 ` [WIP RFC v2 34/35] WIP: rust: drm/kms: Add Kms::atomic_commit_tail Lyude Paul
2024-12-05 16:09   ` Daniel Almeida
2024-09-30 23:10 ` [WIP RFC v2 35/35] WIP: drm: Introduce RVKMS! Lyude Paul
2024-12-05 16:36   ` Daniel Almeida

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=20240930233257.1189730-5-lyude@redhat.com \
    --to=lyude@redhat.com \
    --cc=a.hindborg@samsung.com \
    --cc=airlied@redhat.com \
    --cc=alex.gaynor@gmail.com \
    --cc=aliceryhl@google.com \
    --cc=benno.lossin@proton.me \
    --cc=bjorn3_gh@protonmail.com \
    --cc=boqun.feng@gmail.com \
    --cc=cjia@nvidia.com \
    --cc=dakr@kernel.org \
    --cc=dakr@redhat.com \
    --cc=dri-devel@lists.freedesktop.org \
    --cc=gary@garyguo.net \
    --cc=jhubbard@nvidia.com \
    --cc=lina@asahilina.net \
    --cc=linux-kernel@vger.kernel.org \
    --cc=mcanal@igalia.com \
    --cc=mika.westerberg@linux.intel.com \
    --cc=ojeda@kernel.org \
    --cc=rust-for-linux@vger.kernel.org \
    --cc=tmgross@umich.edu \
    --cc=wedsonaf@gmail.com \
    --cc=zhiw@nvidia.com \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox