Three mechanical fixups needed to build the forward-ported layer
against this tree, rather than the rvkms-slim/rust-stuck source
branches it came from:
- wire the KMS bindings/helpers/aref imports the port assumes into
bindings_helper.h and rust/helpers/drm/{atomic,drm,vblank}.c, and fix
the impl_aref_for_mode_object! macro path
- rename drm_atomic_state -> drm_atomic_commit, renamed upstream since
rvkms-slim was last synced
- pin KmsDriver's associated types to Driver=Self and tidy the
probe_kms stub so it type-checks against the current Driver trait
Signed-off-by: Mike Lothian <[email protected]>
Assisted-by: Claude:claude-sonnet-5 [Claude-Code]
---
rust/bindings/bindings_helper.h | 8 +++++++
rust/helpers/drm/atomic.c | 32 +++++++++++++++++++++++++
rust/helpers/drm/drm.c | 2 ++
rust/helpers/drm/vblank.c | 8 +++++++
rust/kernel/drm/kms.rs | 21 ++++++++---------
rust/kernel/drm/kms/atomic.rs | 41 +++++++++++++++++----------------
rust/kernel/drm/kms/crtc.rs | 16 ++++++-------
rust/kernel/drm/kms/plane.rs | 8 +++----
8 files changed, 93 insertions(+), 43 deletions(-)
create mode 100644 rust/helpers/drm/atomic.c
create mode 100644 rust/helpers/drm/vblank.c
diff --git a/rust/bindings/bindings_helper.h b/rust/bindings/bindings_helper.h
index a1ea23714bdd..e41d2716fb2e 100644
--- a/rust/bindings/bindings_helper.h
+++ b/rust/bindings/bindings_helper.h
@@ -36,6 +36,14 @@
#include <linux/gpu_buddy.h>
#include <drm/drm_atomic.h>
#include <drm/drm_atomic_helper.h>
+#include <drm/drm_connector.h>
+#include <drm/drm_crtc.h>
+#include <drm/drm_edid.h>
+#include <drm/drm_encoder.h>
+#include <drm/drm_framebuffer.h>
+#include <drm/drm_plane.h>
+#include <drm/drm_probe_helper.h>
+#include <drm/drm_vblank.h>
#include <drm/clients/drm_client_setup.h>
#include <drm/drm_device.h>
#include <drm/drm_drv.h>
diff --git a/rust/helpers/drm/atomic.c b/rust/helpers/drm/atomic.c
new file mode 100644
index 000000000000..ed5e49b73c81
--- /dev/null
+++ b/rust/helpers/drm/atomic.c
@@ -0,0 +1,32 @@
+// SPDX-License-Identifier: GPL-2.0
+
+#include <drm/drm_atomic.h>
+
+void rust_helper_drm_atomic_commit_get(struct drm_atomic_commit *state)
+{
+ drm_atomic_commit_get(state);
+}
+
+void rust_helper_drm_atomic_commit_put(struct drm_atomic_commit *state)
+{
+ drm_atomic_commit_put(state);
+}
+
+// Macros for generating one repetitive atomic state accessors (like
drm_atomic_get_new_plane_state)
+#define STATE_FUNC(type, tense)
\
+ struct drm_ ## type ## _state *rust_helper_drm_atomic_get_ ## tense ##
_ ## type ## _state( \
+ const struct drm_atomic_commit *state,
\
+ struct drm_ ## type *type
\
+ ) {
\
+ return drm_atomic_get_## tense ## _ ## type ## _state(state,
type); \
+ }
+#define STATE_FUNCS(type) \
+ STATE_FUNC(type, new); \
+ STATE_FUNC(type, old);
+
+STATE_FUNCS(plane);
+STATE_FUNCS(crtc);
+STATE_FUNCS(connector);
+
+#undef STATE_FUNCS
+#undef STATE_FUNC
diff --git a/rust/helpers/drm/drm.c b/rust/helpers/drm/drm.c
index b8700413a2b8..5d700d75c0c9 100644
--- a/rust/helpers/drm/drm.c
+++ b/rust/helpers/drm/drm.c
@@ -1,4 +1,6 @@
// SPDX-License-Identifier: GPL-2.0
+#include "atomic.c"
#include "gem.c"
#include "vma_manager.c"
+#include "vblank.c"
diff --git a/rust/helpers/drm/vblank.c b/rust/helpers/drm/vblank.c
new file mode 100644
index 000000000000..165db7ac5b4d
--- /dev/null
+++ b/rust/helpers/drm/vblank.c
@@ -0,0 +1,8 @@
+// SPDX-License-Identifier: GPL-2.0
+
+#include <drm/drm_vblank.h>
+
+struct drm_vblank_crtc *rust_helper_drm_crtc_vblank_crtc(struct drm_crtc *crtc)
+{
+ return drm_crtc_vblank_crtc(crtc);
+}
diff --git a/rust/kernel/drm/kms.rs b/rust/kernel/drm/kms.rs
index 11b09d2175db..a147276b3412 100644
--- a/rust/kernel/drm/kms.rs
+++ b/rust/kernel/drm/kms.rs
@@ -12,8 +12,7 @@
},
error::to_result,
prelude::*,
- sync::{Mutex, MutexGuard},
- types::*,
+ sync::{aref::ARef, Mutex, MutexGuard},
};
use bindings;
use core::{
@@ -69,10 +68,10 @@ pub trait KmsImpl {
///
/// This function may only be called once.
unsafe fn probe_kms(_drm: &Device<Self::Driver, Uninit>) ->
Result<ModeConfigInfo> {
- // TODO before submission: There is definitely a proper way of
doing this, but I don't
- // remember what it is.
- unimplemented!()
- //build_error!("This should never be reachable")
+ // This default is only reachable for the `PhantomData<T>`
(non-KMS) implementor, whose
+ // KMS setup is never invoked. KMS drivers override it via the
`KmsDriver` blanket impl
+ // below, so reaching this is a build-time bug.
+ build_error::build_error("probe_kms called on a device without KMS
support")
}
}
}
@@ -126,22 +125,22 @@ pub trait KmsDriver: Driver {
/// The driver's [`DriverConnector`](connector::DriverConnector)
implementation.
///
/// TODO: This will be unneeded once we support multiple `DriverConnector`
implementations.
- type Connector: connector::DriverConnector;
+ type Connector: connector::DriverConnector<Driver = Self>;
/// The driver's [`DriverPlane`](plane::DriverPlane) implementation.
///
/// TODO: This will be unneeded once we support multiple `DriverPlane`
implementations.
- type Plane: plane::DriverPlane;
+ type Plane: plane::DriverPlane<Driver = Self>;
/// The driver's [`DriverCrtc`](crtc::DriverCrtc) implementation.
///
/// TODO: This will be unneeded once we support multiple `DriverCrtc`
implementations.
- type Crtc: crtc::DriverCrtc;
+ type Crtc: crtc::DriverCrtc<Driver = Self>;
/// The driver's [`DriverEncoder`](encoder::DriverEncoder) implementation.
///
/// TODO: This will be unneeded once we support multiple `DriverEncoder`
implementations.
- type Encoder: encoder::DriverEncoder;
+ type Encoder: encoder::DriverEncoder<Driver = Self>;
/// Return a [`ModeConfigInfo`] structure for this [`device::Device`].
fn mode_config_info(dev: &Device<Self, Uninit>) -> Result<ModeConfigInfo>
@@ -486,7 +485,7 @@ macro_rules! impl_aref_for_mode_object {
(impl $( < $( $param:ident: $bound:ident ),+ > )? for $type:ty) => {
// SAFETY: drm_mode_object_get()/put() ensure the type is ref-counted
according to the
// safety contract
- unsafe impl $( < $( $param: $bound ),+ > )?
kernel::types::AlwaysRefCounted for $type {
+ unsafe impl $( < $( $param: $bound ),+ > )?
kernel::sync::aref::AlwaysRefCounted for $type {
#[inline]
fn inc_ref(&self) {
// SAFETY: We're guaranteed by the safety contract of
`ModeObject` that
diff --git a/rust/kernel/drm/kms/atomic.rs b/rust/kernel/drm/kms/atomic.rs
index cc14bff47abd..18dc136940f3 100644
--- a/rust/kernel/drm/kms/atomic.rs
+++ b/rust/kernel/drm/kms/atomic.rs
@@ -1,31 +1,32 @@
// SPDX-License-Identifier: GPL-2.0 OR MIT
-//! [`struct drm_atomic_state`] related bindings for rust.
+//! [`struct drm_atomic_commit`] related bindings for rust.
//!
-//! [`struct drm_atomic_state`]: srctree/include/drm/drm_atomic.h
+//! [`struct drm_atomic_commit`]: srctree/include/drm/drm_atomic.h
use super::{connector::*, crtc::*, plane::*, KmsDriver, ModeObject};
use crate::{
bindings,
drm::device::Device,
error::{from_err_ptr, to_result},
prelude::*,
+ sync::aref::{ARef, AlwaysRefCounted},
types::*,
};
use core::{cell::Cell, marker::*, mem::ManuallyDrop, ops::*, ptr::NonNull};
-/// The main wrapper around [`struct drm_atomic_state`].
+/// The main wrapper around [`struct drm_atomic_commit`].
///
/// This type is usually embedded within another interface such as an
[`AtomicStateMutator`].
///
/// # Invariants
///
-/// - The data layout of this type is identical to [`struct drm_atomic_state`].
+/// - The data layout of this type is identical to [`struct
drm_atomic_commit`].
/// - `state` is initialized for as long as this type is exposed to users.
///
-/// [`struct drm_atomic_state`]: srctree/include/drm/drm_atomic.h
+/// [`struct drm_atomic_commit`]: srctree/include/drm/drm_atomic.h
#[repr(transparent)]
pub struct AtomicState<T: KmsDriver> {
- pub(super) state: Opaque<bindings::drm_atomic_state>,
+ pub(super) state: Opaque<bindings::drm_atomic_commit>,
_p: PhantomData<T>,
}
@@ -34,18 +35,18 @@ impl<T: KmsDriver> AtomicState<T> {
///
/// # Safety
///
- /// `ptr` must point to a valid initialized instance of [`struct
drm_atomic_state`].
+ /// `ptr` must point to a valid initialized instance of [`struct
drm_atomic_commit`].
///
- /// [`struct drm_atomic_state`]: srctree/include/drm/drm_atomic.h
+ /// [`struct drm_atomic_commit`]: srctree/include/drm/drm_atomic.h
#[allow(dead_code)]
- pub(super) unsafe fn from_raw<'a>(ptr: *const bindings::drm_atomic_state)
-> &'a Self {
+ pub(super) unsafe fn from_raw<'a>(ptr: *const bindings::drm_atomic_commit)
-> &'a Self {
// SAFETY: Our data layout is identical
// INVARIANT: Our safety contract upholds the guarantee that `state`
is initialized for as
// long as this type is exposed to users.
unsafe { &*ptr.cast() }
}
- pub(crate) fn as_raw(&self) -> *mut bindings::drm_atomic_state {
+ pub(crate) fn as_raw(&self) -> *mut bindings::drm_atomic_commit {
self.state.get()
}
@@ -102,12 +103,12 @@ pub fn get_old_connector_state<C>(&self, connector: &C)
-> Option<&C::State>
unsafe impl<T: KmsDriver> AlwaysRefCounted for AtomicState<T> {
fn inc_ref(&self) {
// SAFETY: `state` is initialized for as long as this type is exposed
to users
- unsafe { bindings::drm_atomic_state_get(self.state.get()) }
+ unsafe { bindings::drm_atomic_commit_get(self.state.get()) }
}
unsafe fn dec_ref(obj: NonNull<Self>) {
// SAFETY: `obj` contains a valid non-null pointer to an initialized
`Self`.
- unsafe { bindings::drm_atomic_state_put(obj.as_ptr().cast()) }
+ unsafe { bindings::drm_atomic_commit_put(obj.as_ptr().cast()) }
}
}
@@ -141,11 +142,11 @@ impl<T: KmsDriver> AtomicStateMutator<T> {
///
/// # Safety
///
- /// `ptr` must point to a valid `drm_atomic_state`
+ /// `ptr` must point to a valid `drm_atomic_commit`
#[allow(dead_code)]
- pub(super) unsafe fn new(ptr: NonNull<bindings::drm_atomic_state>) -> Self
{
+ pub(super) unsafe fn new(ptr: NonNull<bindings::drm_atomic_commit>) ->
Self {
Self {
- // SAFETY: The data layout of `AtomicState<T>` is identical to
drm_atomic_state
+ // SAFETY: The data layout of `AtomicState<T>` is identical to
drm_atomic_commit
// We use `ManuallyDrop` because `AtomicStateMutator` is only ever
provided to users in
// the context of KMS callbacks. As such, skipping ref inc/dec for
the atomic state is
// convienent for our bindings.
@@ -156,7 +157,7 @@ pub(super) unsafe fn new(ptr:
NonNull<bindings::drm_atomic_state>) -> Self {
}
}
- pub(crate) fn as_raw(&self) -> *mut bindings::drm_atomic_state {
+ pub(crate) fn as_raw(&self) -> *mut bindings::drm_atomic_commit {
self.state.as_raw()
}
@@ -273,8 +274,8 @@ fn drop(&mut self) {
impl<T: KmsDriver> AtomicStateComposer<T> {
/// # Safety
///
- /// The caller guarantees that `ptr` points to a valid instance of
`drm_atomic_state`.
- pub(crate) unsafe fn new(ptr: NonNull<bindings::drm_atomic_state>) -> Self
{
+ /// The caller guarantees that `ptr` points to a valid instance of
`drm_atomic_commit`.
+ pub(crate) unsafe fn new(ptr: NonNull<bindings::drm_atomic_commit>) ->
Self {
// SAFETY: see `AtomicStateMutator::from_raw()`
Self(unsafe { AtomicStateMutator::new(ptr) })
}
@@ -681,11 +682,11 @@ pub fn commit_hw_done<'b>(
// The actual raw C callback for custom atomic commit tail implementations
pub(crate) unsafe extern "C" fn commit_tail_callback<T: KmsDriver>(
- state: *mut bindings::drm_atomic_state,
+ state: *mut bindings::drm_atomic_commit,
) {
// SAFETY:
// - We're guaranteed by DRM that `state` always points to a valid
instance of
- // `bindings::drm_atomic_state`
+ // `bindings::drm_atomic_commit`
// - This conversion is safe via the type invariants
let state = unsafe { AtomicState::from_raw(state.cast_const()) };
diff --git a/rust/kernel/drm/kms/crtc.rs b/rust/kernel/drm/kms/crtc.rs
index b9d095854ba6..0f579dc4ec75 100644
--- a/rust/kernel/drm/kms/crtc.rs
+++ b/rust/kernel/drm/kms/crtc.rs
@@ -995,14 +995,14 @@ impl<'a, T: DriverCrtc> CrtcAtomicCommit<'a, T> {
unsafe extern "C" fn atomic_check_callback<T: DriverCrtc>(
crtc: *mut bindings::drm_crtc,
- state: *mut bindings::drm_atomic_state,
+ state: *mut bindings::drm_atomic_commit,
) -> i32 {
// SAFETY:
// - We're guaranteed `crtc` is of type `Crtc<T>` via type invariants.
// - We're guaranteed by DRM that `crtc` is pointing to a valid
initialized state.
let crtc = unsafe { Crtc::from_raw(crtc) };
- // SAFETY: DRM guarantees `state` points to a valid `drm_atomic_state`
+ // SAFETY: DRM guarantees `state` points to a valid `drm_atomic_commit`
// We use a ManuallyDrop here to avoid AtomicStateComposer dropping an
owned reference we never
// acquired.
let state =
@@ -1023,14 +1023,14 @@ impl<'a, T: DriverCrtc> CrtcAtomicCommit<'a, T> {
unsafe extern "C" fn atomic_begin_callback<T: DriverCrtc>(
crtc: *mut bindings::drm_crtc,
- state: *mut bindings::drm_atomic_state,
+ state: *mut bindings::drm_atomic_commit,
) {
// SAFETY:
// * We're guaranteed `crtc` is of type `Crtc<T>` via type invariants.
// * We're guaranteed by DRM that `crtc` is pointing to a valid
initialized state.
let crtc = unsafe { Crtc::from_raw(crtc) };
- // SAFETY: We're guaranteed by DRM that `state` points to a valid instance
of `drm_atomic_state`
+ // SAFETY: We're guaranteed by DRM that `state` points to a valid instance
of `drm_atomic_commit`
let state = unsafe {
AtomicStateMutator::new(NonNull::new_unchecked(state)) };
// SAFETY:
@@ -1045,14 +1045,14 @@ impl<'a, T: DriverCrtc> CrtcAtomicCommit<'a, T> {
unsafe extern "C" fn atomic_flush_callback<T: DriverCrtc>(
crtc: *mut bindings::drm_crtc,
- state: *mut bindings::drm_atomic_state,
+ state: *mut bindings::drm_atomic_commit,
) {
// SAFETY:
// - We're guaranteed `crtc` is of type `Crtc<T>` via type invariants.
// - We're guaranteed by DRM that `crtc` is pointing to a valid
initialized state.
let crtc = unsafe { Crtc::from_raw(crtc) };
- // SAFETY: We're guaranteed by DRM that `state` points to a valid instance
of `drm_atomic_state`
+ // SAFETY: We're guaranteed by DRM that `state` points to a valid instance
of `drm_atomic_commit`
let state = unsafe {
AtomicStateMutator::new(NonNull::new_unchecked(state)) };
// SAFETY:
@@ -1067,7 +1067,7 @@ impl<'a, T: DriverCrtc> CrtcAtomicCommit<'a, T> {
unsafe extern "C" fn atomic_enable_callback<T: DriverCrtc>(
crtc: *mut bindings::drm_crtc,
- state: *mut bindings::drm_atomic_state,
+ state: *mut bindings::drm_atomic_commit,
) {
// SAFETY:
// - We're guaranteed `crtc` is of type `Crtc<T>` via type invariants.
@@ -1089,7 +1089,7 @@ impl<'a, T: DriverCrtc> CrtcAtomicCommit<'a, T> {
unsafe extern "C" fn atomic_disable_callback<T: DriverCrtc>(
crtc: *mut bindings::drm_crtc,
- state: *mut bindings::drm_atomic_state,
+ state: *mut bindings::drm_atomic_commit,
) {
// SAFETY:
// - We're guaranteed `crtc` points to a valid instance of `drm_crtc`
diff --git a/rust/kernel/drm/kms/plane.rs b/rust/kernel/drm/kms/plane.rs
index 661d82273099..6f547adcfdc9 100644
--- a/rust/kernel/drm/kms/plane.rs
+++ b/rust/kernel/drm/kms/plane.rs
@@ -1048,14 +1048,14 @@ impl<'a, T: DriverPlane> PlaneAtomicCommit<'a, T> {
unsafe extern "C" fn atomic_update_callback<T: DriverPlane>(
plane: *mut bindings::drm_plane,
- state: *mut bindings::drm_atomic_state,
+ state: *mut bindings::drm_atomic_commit,
) {
// SAFETY:
// - We're guaranteed `plane` is of type `Plane<T>` via type invariants.
// - We're guaranteed by DRM that `plane` is pointing to a valid
initialized state.
let plane = unsafe { Plane::from_raw(plane) };
- // SAFETY: DRM guarantees `state` points to a valid `drm_atomic_state`
+ // SAFETY: DRM guarantees `state` points to a valid `drm_atomic_commit`
let state = unsafe {
AtomicStateMutator::new(NonNull::new_unchecked(state)) };
// SAFETY:
@@ -1070,14 +1070,14 @@ impl<'a, T: DriverPlane> PlaneAtomicCommit<'a, T> {
unsafe extern "C" fn atomic_check_callback<T: DriverPlane>(
plane: *mut bindings::drm_plane,
- state: *mut bindings::drm_atomic_state,
+ state: *mut bindings::drm_atomic_commit,
) -> i32 {
// SAFETY:
// - We're guaranteed `plane` is of type `Plane<T>` via type invariants.
// - We're guaranteed by DRM that `plane` is pointing to a valid
initialized state.
let plane = unsafe { Plane::from_raw(plane) };
- // SAFETY: We're guaranteed by DRM that `state` points to a valid instance
of `drm_atomic_state`
+ // SAFETY: We're guaranteed by DRM that `state` points to a valid instance
of `drm_atomic_commit`
// We use ManuallyDrop here since AtomicStateComposer would otherwise drop
a owned reference to
// the atomic state upon finishing this callback.
let state = ManuallyDrop::new(unsafe {
--
2.55.0