* [PATCH 00/13] drm/tyr: add debugfs support
@ 2026-03-26 6:52 Alvin Sun
2026-03-26 6:52 ` [PATCH 01/13] rust: sync: support [pin_]init for `SetOnce` Alvin Sun
` (12 more replies)
0 siblings, 13 replies; 14+ messages in thread
From: Alvin Sun @ 2026-03-26 6:52 UTC (permalink / raw)
To: Miguel Ojeda, Boqun Feng, Gary Guo, Björn Roy Baron,
Benno Lossin, Andreas Hindborg, Alice Ryhl, Trevor Gross,
Danilo Krummrich, David Airlie, Simona Vetter, Sumit Semwal,
Christian König, Daniel Almeida
Cc: rust-for-linux, dri-devel, Alvin Sun
This patchset contains:
- hazptr: Add hazard pointer abstraction to kernel::sync
- revocable: Introduce HazPtrRevocable, and adapt Gary Guo's downstream
LazyRevocable implementation to use hazard pointers internally,
enabling safe sharing of debugfs-root data across the tyr module and
DRM driver
- drm: Add device and GEM helper functions to support debugfs
- tyr: Add debugfs infrastructure and interfaces to expose GEM/VM
information
See the full dependency and commit history at [1].
Link: https://gitlab.freedesktop.org/panfrost/linux/-/issues/11
Link: https://gitlab.freedesktop.org/panfrost/linux/-/merge_requests/59 [1]
Signed-off-by: Alvin Sun <alvin.sun@linux.dev>
---
Alvin Sun (11):
rust: sync: set_once: Rename InitError variants to fix clippy warning
rust: sync: add hazard pointer abstraction
rust: revocable: add HazPtrRevocable
rust: revocable: make LazyRevocable use HazPtrRevocable
rust: drm: add Device::primary_index()
rust: drm/gem: add GEM object query helpers for debugfs
rust: drm/gem/shmem: add resident_size() and madv() for debugfs
drm/tyr: expose Vm gpuvm_core, gpuvm and va_range as pub(crate)
drm/tyr: add debugfs infrastructure
drm/tyr: add vms and gpuvas debugfs interface
drm/tyr: add gems field and gems debugfs interface
Gary Guo (2):
rust: sync: support [pin_]init for `SetOnce`
rust: revocable: add lazily instantiated revocable variant
drivers/gpu/drm/tyr/debugfs.rs | 190 ++++++++++++++++++++++++++++++++++++
drivers/gpu/drm/tyr/driver.rs | 18 +++-
drivers/gpu/drm/tyr/fw.rs | 7 +-
drivers/gpu/drm/tyr/mmu.rs | 6 +-
drivers/gpu/drm/tyr/tyr.rs | 39 +++++++-
drivers/gpu/drm/tyr/vm.rs | 6 +-
rust/bindings/bindings_helper.h | 1 +
rust/helpers/hazptr.c | 13 +++
rust/helpers/helpers.c | 1 +
rust/kernel/drm/device.rs | 10 ++
rust/kernel/drm/gem/mod.rs | 49 +++++++++-
rust/kernel/drm/gem/shmem.rs | 21 ++++
rust/kernel/revocable.rs | 209 +++++++++++++++++++++++++++++++++++++++-
rust/kernel/sync.rs | 1 +
rust/kernel/sync/hazptr.rs | 91 +++++++++++++++++
rust/kernel/sync/set_once.rs | 120 +++++++++++++++++++----
16 files changed, 746 insertions(+), 36 deletions(-)
---
base-commit: 34cb4f916af10153c87fabaf6c34e4cafa170427
change-id: 20260320-b4-tyr-debugfs-3fcaff064297
prerequisite-change-id: 20260202-io-81fd368f7565:v2
prerequisite-patch-id: 74873afed2b65f5a11c33f0c0c54375c55079109
prerequisite-patch-id: ae853e8eb8d58c77881371960be4ae92755e83c6
prerequisite-patch-id: 0ab78b50648c7d8f66b83c32ed2af0ec3ede42a3
prerequisite-patch-id: 8d20a8db8cf4660c682ee91f3db04e640c144e33
prerequisite-patch-id: 299de9cd2789c19c22e2816f7c817d80d5a4f1db
prerequisite-patch-id: 661ee334905f359daa8fb8d808ed5f4a8085f5c9
prerequisite-change-id: 20260117-register-ccaba1d21713:v9
prerequisite-patch-id: e4cb34ef09bccb92e1c35435e346b3a0459d3cdf
prerequisite-patch-id: 2c3c42ae9f3f4544c088dffbe4a0527f28b1c135
prerequisite-patch-id: 9f40e176e1b67bada943e376950debabb3f196d5
prerequisite-patch-id: ccc86d3ab9f62883c90d1275c99720942bd2bcb3
prerequisite-patch-id: 216427f1fdf94755cca0ed0676c4290f85d45e5c
prerequisite-patch-id: 7e1ea4d184297dfaba1351a7cb23e3b6827fed46
prerequisite-patch-id: 29ff9ffe37669d23b5509bfefb0cc1f8950eaa7c
prerequisite-patch-id: e5723722ff970c585cbf559456fa4cda05f28952
prerequisite-patch-id: afdae76e12011bb158d2008b8cd1ffba084db0bb
prerequisite-patch-id: b0473d5c7af0bbeec6f6ec8dd36d8a09cc180fed
prerequisite-message-id: <20260206223431.693765-1-lyude@redhat.com>
prerequisite-patch-id: 454c4fe7a7bcc65b2c9cc69dd5dd8e4c1d952297
prerequisite-patch-id: aff529cc205f5ab35518b8e4568e6e1319eecaa9
prerequisite-patch-id: 9f7d5c4a8ed052f5c5f2a28c862a9392d7a812cc
prerequisite-patch-id: ec9d104ba7c67488f19e6dd1a50d1ec4f682f333
prerequisite-patch-id: e7a844bd6254643d1f23827886b487c196ee9968
prerequisite-patch-id: 3c57ebf13497cf57c586b955d5ce90f2f9fd8cdc
prerequisite-patch-id: 1a327345ac71599ece0b2272fba81472f70c568c
prerequisite-change-id: 20251128-gpuvm-rust-b719cac27ad6:v5
prerequisite-patch-id: 6a8ddd47a2e1c769c65a942b3d9315e6ae5cae7e
prerequisite-patch-id: d4ee9fb80025c4fd8129c3477cc3dc36e13076cb
prerequisite-patch-id: 0ad35cd3dfcf8a8804e9fed8df3e5612cf07da69
prerequisite-patch-id: 275a900645e14169911ee00bab54553c84b48ad0
prerequisite-patch-id: 2a2de2f6c4fac065de5c459026daa2c32f340d22
prerequisite-patch-id: 9a721bc700da778f2554cf32917dda4807744520
prerequisite-message-id: <20260131001602.2095470-1-lyude@redhat.com>
prerequisite-patch-id: 6c622d1df9166ad081acba46237f8cecbf728356
prerequisite-patch-id: 769892e477c161e6c7a57519ec635b1455310f1d
prerequisite-patch-id: 3c5f5070ded87e95a8045083a55501fbbe9f6313
prerequisite-patch-id: 10fbd8695264e67421946dda4d39e29d5fe77c64
Best regards,
--
Alvin Sun <alvin.sun@linux.dev>
^ permalink raw reply [flat|nested] 14+ messages in thread
* [PATCH 01/13] rust: sync: support [pin_]init for `SetOnce`
2026-03-26 6:52 [PATCH 00/13] drm/tyr: add debugfs support Alvin Sun
@ 2026-03-26 6:52 ` Alvin Sun
2026-03-26 6:52 ` [PATCH 02/13] rust: revocable: add lazily instantiated revocable variant Alvin Sun
` (11 subsequent siblings)
12 siblings, 0 replies; 14+ messages in thread
From: Alvin Sun @ 2026-03-26 6:52 UTC (permalink / raw)
To: Miguel Ojeda, Boqun Feng, Gary Guo, Björn Roy Baron,
Benno Lossin, Andreas Hindborg, Alice Ryhl, Trevor Gross,
Danilo Krummrich, David Airlie, Simona Vetter, Sumit Semwal,
Christian König, Daniel Almeida
Cc: rust-for-linux, dri-devel, Alvin Sun
From: Gary Guo <gary@garyguo.net>
Make `SetOnce` support initialization via `impl Init` or `impl PinInit`.
This adds a possible failing path if an initializer fails. In such case,
the state is dropped back to 0 instead of keep increasing; so the monotonicity
invariant is dropped. The order for initialization is upgraded from Relaxed
to Acquire so it can observe the effect of a previously failed initialization.
Signed-off-by: Gary Guo <gary@garyguo.net>
Signed-off-by: Alvin Sun <alvin.sun@linux.dev>
---
rust/kernel/sync/set_once.rs | 120 +++++++++++++++++++++++++++++++++++--------
1 file changed, 99 insertions(+), 21 deletions(-)
diff --git a/rust/kernel/sync/set_once.rs b/rust/kernel/sync/set_once.rs
index 139cef05e935f..db9c5423fade3 100644
--- a/rust/kernel/sync/set_once.rs
+++ b/rust/kernel/sync/set_once.rs
@@ -2,11 +2,23 @@
//! A container that can be initialized at most once.
+use core::{
+ cell::UnsafeCell,
+ mem::MaybeUninit, //
+};
+use pin_init::{
+ Init,
+ PinInit, //
+};
+
use super::atomic::{
- ordering::{Acquire, Relaxed, Release},
- Atomic,
+ ordering::{
+ Acquire,
+ Release, //
+ },
+ Atomic, //
};
-use core::{cell::UnsafeCell, mem::MaybeUninit};
+use crate::prelude::*;
/// A container that can be populated at most once. Thread safe.
///
@@ -15,13 +27,13 @@
///
/// # Invariants
///
-/// - `init` may only increase in value.
/// - `init` may only assume values in the range `0..=2`.
/// - `init == 0` if and only if `value` is uninitialized.
/// - `init == 1` if and only if there is exactly one thread with exclusive
/// access to `self.value`.
/// - `init == 2` if and only if `value` is initialized and valid for shared
/// access.
+/// - once `init == 2`, it must remain so.
///
/// # Example
///
@@ -51,6 +63,35 @@ fn default() -> Self {
}
}
+/// Error that can occur during initialization of `SetOnce`.
+#[derive(Debug)]
+pub enum InitError<E> {
+ /// The `Once` has already been initialized.
+ AlreadyInit,
+ /// The `Once` is being raced to initialize by another thread.
+ RacedInit,
+ /// Error occurs during initialization.
+ DuringInit(E),
+}
+
+impl<E> From<E> for InitError<E> {
+ #[inline]
+ fn from(err: E) -> Self {
+ InitError::DuringInit(err)
+ }
+}
+
+impl<E: Into<Error>> From<InitError<E>> for Error {
+ #[inline]
+ fn from(this: InitError<E>) -> Self {
+ match this {
+ InitError::AlreadyInit => EEXIST,
+ InitError::RacedInit => EBUSY,
+ InitError::DuringInit(e) => e.into(),
+ }
+ }
+}
+
impl<T> SetOnce<T> {
/// Create a new [`SetOnce`].
///
@@ -76,31 +117,68 @@ pub fn as_ref(&self) -> Option<&T> {
}
}
- /// Populate the [`SetOnce`].
+ /// Populate the [`SetOnce`] with an initializer.
///
- /// Returns `true` if the [`SetOnce`] was successfully populated.
- pub fn populate(&self, value: T) -> bool {
+ /// Returns the initialized reference if the [`SetOnce`] was successfully populated.
+ pub fn init<E>(&self, init: impl Init<T, E>) -> Result<&T, InitError<E>> {
// INVARIANT: If the swap succeeds:
- // - We increase `init`.
// - We write the valid value `1` to `init`.
+ // - The previous value is not `2`, so it is valid to move to `1`.
// - Only one thread can succeed in this write, so we have exclusive access after the
// write.
- if let Ok(0) = self.init.cmpxchg(0, 1, Relaxed) {
- // SAFETY: By the type invariants of `Self`, the fact that we succeeded in writing `1`
- // to `self.init` means we obtained exclusive access to `self.value`.
- unsafe { core::ptr::write(self.value.get().cast(), value) };
- // INVARIANT:
- // - We increase `init`.
- // - We write the valid value `2` to `init`.
- // - We release our exclusive access to `self.value` and it is now valid for shared
- // access.
- self.init.store(2, Release);
- true
- } else {
- false
+ match self.init.cmpxchg(0, 1, Acquire) {
+ Ok(_) => {
+ // SAFETY:
+ // - By the type invariants of `Self`, the fact that we succeeded in writing `1`
+ // to `self.init` means we obtained exclusive access to `self.value`.
+ // - When `Err` is returned, we did not set `self.init` to `2` so the `Drop` is not
+ // armed.
+ match unsafe { init.__init(self.value.get().cast()) } {
+ Ok(()) => {
+ // INVARIANT:
+ // - The previous value is `1`, so it is valid to move to `2`.
+ // - We write the valid value `2` to `init`.
+ // - We release our exclusive access to `self.value` and it is now valid
+ // for shared access.
+ self.init.store(2, Release);
+ // SAFETY: we have just initialized the value.
+ Ok(unsafe { &*self.value.get().cast() })
+ }
+ Err(err) => {
+ // INVARIANT:
+ // - The previous value is `1`, so it is valid to move to `0`.
+ // - We write the valid value `0` to `init`.
+ // - We release our exclusive access to `self.value` and it is now valid
+ // for shared access.
+ self.init.store(0, Release);
+ Err(err.into())
+ }
+ }
+ }
+ Err(1) => Err(InitError::RacedInit),
+ Err(_) => Err(InitError::AlreadyInit),
}
}
+ /// Populate the [`SetOnce`] with a pinned initializer.
+ ///
+ /// Returns the initialized reference if the [`SetOnce`] was successfully populated.
+ pub fn pin_init<E>(self: Pin<&Self>, init: impl PinInit<T, E>) -> Result<&T, InitError<E>> {
+ // SAFETY:
+ // - `__pinned_init` satisfy all requirements of `init_from_closure`
+ // - calling `__pinned_init` require additional that the slot is pinned, which is satisfied
+ // given `self: Pin<&Self>`.
+ self.get_ref()
+ .init(unsafe { pin_init::init_from_closure(|slot| init.__pinned_init(slot)) })
+ }
+
+ /// Populate the [`SetOnce`].
+ ///
+ /// Returns `true` if the [`SetOnce`] was successfully populated.
+ pub fn populate(&self, value: T) -> bool {
+ self.init(value).is_ok()
+ }
+
/// Get a copy of the contained object.
///
/// Returns [`None`] if the [`SetOnce`] is empty.
--
2.43.0
^ permalink raw reply related [flat|nested] 14+ messages in thread
* [PATCH 02/13] rust: revocable: add lazily instantiated revocable variant
2026-03-26 6:52 [PATCH 00/13] drm/tyr: add debugfs support Alvin Sun
2026-03-26 6:52 ` [PATCH 01/13] rust: sync: support [pin_]init for `SetOnce` Alvin Sun
@ 2026-03-26 6:52 ` Alvin Sun
2026-03-26 6:52 ` [PATCH 03/13] rust: sync: set_once: Rename InitError variants to fix clippy warning Alvin Sun
` (10 subsequent siblings)
12 siblings, 0 replies; 14+ messages in thread
From: Alvin Sun @ 2026-03-26 6:52 UTC (permalink / raw)
To: Miguel Ojeda, Boqun Feng, Gary Guo, Björn Roy Baron,
Benno Lossin, Andreas Hindborg, Alice Ryhl, Trevor Gross,
Danilo Krummrich, David Airlie, Simona Vetter, Sumit Semwal,
Christian König, Daniel Almeida
Cc: rust-for-linux, dri-devel, Alvin Sun
From: Gary Guo <gary@garyguo.net>
Add a `LazyRevocable` type, an variant to `Revocable` where
the data is initialized lazily. This type can be constructed as const and
put into statics.
Signed-off-by: Gary Guo <gary@garyguo.net>
Signed-off-by: Alvin Sun <alvin.sun@linux.dev>
---
rust/kernel/revocable.rs | 80 +++++++++++++++++++++++++++++++++++++++++++++++-
1 file changed, 79 insertions(+), 1 deletion(-)
diff --git a/rust/kernel/revocable.rs b/rust/kernel/revocable.rs
index 0f4ae673256d5..70733ff5961cd 100644
--- a/rust/kernel/revocable.rs
+++ b/rust/kernel/revocable.rs
@@ -7,7 +7,12 @@
use pin_init::Wrapper;
-use crate::{bindings, prelude::*, sync::rcu, types::Opaque};
+use crate::{
+ bindings,
+ prelude::*,
+ sync::{rcu, SetOnce},
+ types::Opaque,
+};
use core::{
marker::PhantomData,
ops::Deref,
@@ -261,3 +266,76 @@ fn deref(&self) -> &Self::Target {
unsafe { &*self.data_ref }
}
}
+
+/// A handle to perform revocation on a [`Revocable`].
+///
+/// The associated `Revocable` is revoked when the handle is dropped.
+pub struct RevokeHandle<'a, T>(&'a Revocable<T>);
+
+impl<'a, T> RevokeHandle<'a, T> {
+ /// Create a revoke-on-drop handle on an existing revocable.
+ pub fn new(revocable: &'a Revocable<T>) -> Self {
+ Self(revocable)
+ }
+
+ /// Dismiss the handle.
+ ///
+ /// This method consumes ownership without revoking the `Revocable`.
+ pub fn dismiss(self) {
+ core::mem::forget(self);
+ }
+}
+
+impl<'a, T> Drop for RevokeHandle<'a, T> {
+ fn drop(&mut self) {
+ self.0.revoke();
+ }
+}
+
+/// An object that is initialized and can become inaccessible at runtime.
+///
+/// [`Revocable`] is initialized at the beginning, and can be made inaccessible at runtime.
+/// `LazyRevocable` is uninitialized at the beginning, and can be initialized later; it can be
+/// revoked in a similar manner to [`Revocable`]. Once revoked, it cannot be initialized again.
+#[pin_data]
+pub struct LazyRevocable<T> {
+ #[pin]
+ once: SetOnce<Revocable<T>>,
+}
+
+impl<T> LazyRevocable<T> {
+ /// Creates a new lazy revocable instance.
+ ///
+ /// The instance starts uninitialized, where all accesses would fail.
+ pub const fn new() -> Self {
+ LazyRevocable {
+ once: SetOnce::new(),
+ }
+ }
+
+ /// Initialize a `LazyRevocable` and obtain a handle to revoke the content if successful.
+ ///
+ /// An error would be returned if the revocable has already been initialized.
+ pub fn init<E: Into<Error>>(
+ self: Pin<&Self>,
+ init: impl PinInit<T, E>,
+ ) -> Result<RevokeHandle<'_, T>> {
+ // SAFETY: `once` is structurally pinned.
+ let once = unsafe { self.map_unchecked(|x| &x.once) };
+ let revocable = once.pin_init(Revocable::new(init))?;
+ Ok(RevokeHandle::new(revocable))
+ }
+
+ /// Tries to access the revocable wrapped object.
+ ///
+ /// Returns `None` if the object has not been initialized, or it has been revoked and is therefore no longer accessible.
+ pub fn try_access(&self) -> Option<RevocableGuard<'_, T>> {
+ self.once.as_ref()?.try_access()
+ }
+}
+
+impl<T> Default for LazyRevocable<T> {
+ fn default() -> Self {
+ Self::new()
+ }
+}
--
2.43.0
^ permalink raw reply related [flat|nested] 14+ messages in thread
* [PATCH 03/13] rust: sync: set_once: Rename InitError variants to fix clippy warning
2026-03-26 6:52 [PATCH 00/13] drm/tyr: add debugfs support Alvin Sun
2026-03-26 6:52 ` [PATCH 01/13] rust: sync: support [pin_]init for `SetOnce` Alvin Sun
2026-03-26 6:52 ` [PATCH 02/13] rust: revocable: add lazily instantiated revocable variant Alvin Sun
@ 2026-03-26 6:52 ` Alvin Sun
2026-03-26 6:52 ` [PATCH 04/13] rust: sync: add hazard pointer abstraction Alvin Sun
` (9 subsequent siblings)
12 siblings, 0 replies; 14+ messages in thread
From: Alvin Sun @ 2026-03-26 6:52 UTC (permalink / raw)
To: Miguel Ojeda, Boqun Feng, Gary Guo, Björn Roy Baron,
Benno Lossin, Andreas Hindborg, Alice Ryhl, Trevor Gross,
Danilo Krummrich, David Airlie, Simona Vetter, Sumit Semwal,
Christian König, Daniel Almeida
Cc: rust-for-linux, dri-devel, Alvin Sun
Fixes clippy warning:
warning: all variants have the same postfix: `Init`
--> rust/kernel/sync/set_once.rs:68:1
Signed-off-by: Alvin Sun <alvin.sun@linux.dev>
---
rust/kernel/sync/set_once.rs | 18 +++++++++---------
1 file changed, 9 insertions(+), 9 deletions(-)
diff --git a/rust/kernel/sync/set_once.rs b/rust/kernel/sync/set_once.rs
index db9c5423fade3..3af5538aae1d4 100644
--- a/rust/kernel/sync/set_once.rs
+++ b/rust/kernel/sync/set_once.rs
@@ -67,17 +67,17 @@ fn default() -> Self {
#[derive(Debug)]
pub enum InitError<E> {
/// The `Once` has already been initialized.
- AlreadyInit,
+ Already,
/// The `Once` is being raced to initialize by another thread.
- RacedInit,
+ Raced,
/// Error occurs during initialization.
- DuringInit(E),
+ Inner(E),
}
impl<E> From<E> for InitError<E> {
#[inline]
fn from(err: E) -> Self {
- InitError::DuringInit(err)
+ InitError::Inner(err)
}
}
@@ -85,9 +85,9 @@ impl<E: Into<Error>> From<InitError<E>> for Error {
#[inline]
fn from(this: InitError<E>) -> Self {
match this {
- InitError::AlreadyInit => EEXIST,
- InitError::RacedInit => EBUSY,
- InitError::DuringInit(e) => e.into(),
+ InitError::Already => EEXIST,
+ InitError::Raced => EBUSY,
+ InitError::Inner(e) => e.into(),
}
}
}
@@ -155,8 +155,8 @@ pub fn init<E>(&self, init: impl Init<T, E>) -> Result<&T, InitError<E>> {
}
}
}
- Err(1) => Err(InitError::RacedInit),
- Err(_) => Err(InitError::AlreadyInit),
+ Err(1) => Err(InitError::Raced),
+ Err(_) => Err(InitError::Already),
}
}
--
2.43.0
^ permalink raw reply related [flat|nested] 14+ messages in thread
* [PATCH 04/13] rust: sync: add hazard pointer abstraction
2026-03-26 6:52 [PATCH 00/13] drm/tyr: add debugfs support Alvin Sun
` (2 preceding siblings ...)
2026-03-26 6:52 ` [PATCH 03/13] rust: sync: set_once: Rename InitError variants to fix clippy warning Alvin Sun
@ 2026-03-26 6:52 ` Alvin Sun
2026-03-26 6:52 ` [PATCH 05/13] rust: revocable: add HazPtrRevocable Alvin Sun
` (8 subsequent siblings)
12 siblings, 0 replies; 14+ messages in thread
From: Alvin Sun @ 2026-03-26 6:52 UTC (permalink / raw)
To: Miguel Ojeda, Boqun Feng, Gary Guo, Björn Roy Baron,
Benno Lossin, Andreas Hindborg, Alice Ryhl, Trevor Gross,
Danilo Krummrich, David Airlie, Simona Vetter, Sumit Semwal,
Christian König, Daniel Almeida
Cc: rust-for-linux, dri-devel, Alvin Sun
Add C helpers and Rust wrappers for the kernel hazard pointer API,
to be used by revocable and other code.
Signed-off-by: Alvin Sun <alvin.sun@linux.dev>
---
rust/bindings/bindings_helper.h | 1 +
rust/helpers/hazptr.c | 13 ++++++
rust/helpers/helpers.c | 1 +
rust/kernel/sync.rs | 1 +
rust/kernel/sync/hazptr.rs | 91 +++++++++++++++++++++++++++++++++++++++++
5 files changed, 107 insertions(+)
diff --git a/rust/bindings/bindings_helper.h b/rust/bindings/bindings_helper.h
index 9058b09a016ec..8ace50a3dc104 100644
--- a/rust/bindings/bindings_helper.h
+++ b/rust/bindings/bindings_helper.h
@@ -60,6 +60,7 @@
#include <linux/file.h>
#include <linux/firmware.h>
#include <linux/fs.h>
+#include <linux/hazptr.h>
#include <linux/i2c.h>
#include <linux/interrupt.h>
#include <linux/io-pgtable.h>
diff --git a/rust/helpers/hazptr.c b/rust/helpers/hazptr.c
new file mode 100644
index 0000000000000..aa53fbcd0da1d
--- /dev/null
+++ b/rust/helpers/hazptr.c
@@ -0,0 +1,13 @@
+// SPDX-License-Identifier: GPL-2.0
+
+#include <linux/hazptr.h>
+
+__rust_helper void *rust_helper_hazptr_acquire(struct hazptr_ctx *ctx, void *const *addr_p)
+{
+ return hazptr_acquire(ctx, addr_p);
+}
+
+__rust_helper void rust_helper_hazptr_release(struct hazptr_ctx *ctx, void *addr)
+{
+ hazptr_release(ctx, addr);
+}
diff --git a/rust/helpers/helpers.c b/rust/helpers/helpers.c
index f1ac40b0bd1a4..ed8cb74d394a3 100644
--- a/rust/helpers/helpers.c
+++ b/rust/helpers/helpers.c
@@ -34,6 +34,7 @@
#include "err.c"
#include "irq.c"
#include "fs.c"
+#include "hazptr.c"
#include "io.c"
#include "jump_label.c"
#include "kunit.c"
diff --git a/rust/kernel/sync.rs b/rust/kernel/sync.rs
index 993dbf2caa0e3..45da761eaee05 100644
--- a/rust/kernel/sync.rs
+++ b/rust/kernel/sync.rs
@@ -15,6 +15,7 @@
pub mod barrier;
pub mod completion;
mod condvar;
+pub mod hazptr;
pub mod lock;
mod locked_by;
pub mod poll;
diff --git a/rust/kernel/sync/hazptr.rs b/rust/kernel/sync/hazptr.rs
new file mode 100644
index 0000000000000..f94ae45dd3d66
--- /dev/null
+++ b/rust/kernel/sync/hazptr.rs
@@ -0,0 +1,91 @@
+// SPDX-License-Identifier: GPL-2.0
+
+//! Hazard pointer support.
+//!
+//! C header: [`include/linux/hazptr.h`](srctree/include/linux/hazptr.h)
+
+use crate::{
+ bindings,
+ ffi::c_void,
+ prelude::*,
+ types::Opaque, //
+};
+use core::{
+ ops::Deref,
+ ptr::NonNull, //
+};
+
+/// Per-thread context for one hazard-pointer acquire/release pair.
+#[repr(transparent)]
+pub struct HazptrCtx(Opaque<bindings::hazptr_ctx>);
+
+impl HazptrCtx {
+ /// Creates a new zero-initialized context for one acquire/release pair.
+ #[inline]
+ pub const fn new() -> Self {
+ Self(Opaque::zeroed())
+ }
+
+ /// Get the raw pointer.
+ #[inline]
+ pub fn as_raw(self: &Pin<&mut Self>) -> *mut bindings::hazptr_ctx {
+ self.0.get()
+ }
+}
+
+impl Default for HazptrCtx {
+ fn default() -> Self {
+ Self::new()
+ }
+}
+
+/// Guard holding a hazard-pointer-protected reference.
+pub struct Guard<'a, T> {
+ ctx: Pin<&'a mut HazptrCtx>,
+ ptr: NonNull<T>,
+}
+
+impl<'a, T> Guard<'a, T> {
+ #[inline]
+ fn new(ctx: Pin<&'a mut HazptrCtx>, ptr: NonNull<T>) -> Self {
+ Self { ctx, ptr }
+ }
+}
+
+impl<T> Deref for Guard<'_, T> {
+ type Target = T;
+
+ #[inline]
+ fn deref(&self) -> &T {
+ // SAFETY: hazptr protocol keeps the pointer valid until release.
+ unsafe { self.ptr.as_ref() }
+ }
+}
+
+impl<T> Drop for Guard<'_, T> {
+ #[inline]
+ fn drop(&mut self) {
+ // SAFETY: `self.ctx` and `self.ptr` are the same as the ones used in `acquire`.
+ unsafe { bindings::hazptr_release(self.ctx.as_raw().cast(), self.ptr.as_ptr().cast()) };
+ }
+}
+
+/// Acquires a hazard pointer for the pointer at `addr_p` and returns a guard.
+///
+/// Returns `None` if the loaded value is null.
+#[inline]
+pub fn acquire<'a, T>(
+ ctx: Pin<&'a mut HazptrCtx>,
+ addr_p: *const *const T,
+) -> Option<Guard<'a, T>> {
+ // SAFETY: ctx is valid and pinned, addr_p is a valid pointer to a pointer.
+ let ptr = unsafe { bindings::hazptr_acquire(ctx.as_raw().cast(), addr_p.cast()) };
+ NonNull::new(ptr.cast()).map(|p| Guard::new(ctx, p))
+}
+
+/// Waits until no slot holds `addr`.
+#[inline]
+pub fn synchronize(addr: usize) {
+ // SAFETY: addr is only compared with slot values, not dereferenced.
+ unsafe { bindings::hazptr_synchronize(addr as *mut c_void) };
+}
--
2.43.0
^ permalink raw reply related [flat|nested] 14+ messages in thread
* [PATCH 05/13] rust: revocable: add HazPtrRevocable
2026-03-26 6:52 [PATCH 00/13] drm/tyr: add debugfs support Alvin Sun
` (3 preceding siblings ...)
2026-03-26 6:52 ` [PATCH 04/13] rust: sync: add hazard pointer abstraction Alvin Sun
@ 2026-03-26 6:52 ` Alvin Sun
2026-03-26 6:52 ` [PATCH 06/13] rust: revocable: make LazyRevocable use HazPtrRevocable Alvin Sun
` (7 subsequent siblings)
12 siblings, 0 replies; 14+ messages in thread
From: Alvin Sun @ 2026-03-26 6:52 UTC (permalink / raw)
To: Miguel Ojeda, Boqun Feng, Gary Guo, Björn Roy Baron,
Benno Lossin, Andreas Hindborg, Alice Ryhl, Trevor Gross,
Danilo Krummrich, David Airlie, Simona Vetter, Sumit Semwal,
Christian König, Daniel Almeida
Cc: rust-for-linux, dri-devel, Alvin Sun
Add hazard-pointer-based revocable type and related handle/guard.
Signed-off-by: Alvin Sun <alvin.sun@linux.dev>
---
rust/kernel/revocable.rs | 127 +++++++++++++++++++++++++++++++++++++++++++++--
1 file changed, 124 insertions(+), 3 deletions(-)
diff --git a/rust/kernel/revocable.rs b/rust/kernel/revocable.rs
index 70733ff5961cd..eabb76ce92c43 100644
--- a/rust/kernel/revocable.rs
+++ b/rust/kernel/revocable.rs
@@ -10,14 +10,25 @@
use crate::{
bindings,
prelude::*,
- sync::{rcu, SetOnce},
+ sync::{
+ hazptr,
+ hazptr::HazptrCtx,
+ rcu,
+ SetOnce, //
+ },
types::Opaque,
};
use core::{
marker::PhantomData,
ops::Deref,
- ptr::drop_in_place,
- sync::atomic::{AtomicBool, Ordering},
+ ptr::{
+ addr_of,
+ drop_in_place, //
+ },
+ sync::atomic::{
+ AtomicBool,
+ Ordering, //
+ },
};
/// An object that can become inaccessible at runtime.
@@ -292,6 +303,116 @@ fn drop(&mut self) {
}
}
+/// Revocable protected by hazard pointer instead of RCU.
+#[pin_data(PinnedDrop)]
+pub struct HazPtrRevocable<T> {
+ #[pin]
+ data: Opaque<T>,
+ is_available: AtomicBool,
+}
+
+// SAFETY: HazPtrRevocable<T> only moves ownership of T across threads;
+// revocation/drop follow the hazptr protocol, so T: Send suffices.
+unsafe impl<T: Send> Send for HazPtrRevocable<T> {}
+
+// SAFETY: &HazPtrRevocable<T> may be shared across threads and yields
+// &T via hazptr guards; with T: Send + Sync such shared access is sound.
+unsafe impl<T: Sync + Send> Sync for HazPtrRevocable<T> {}
+
+impl<T> HazPtrRevocable<T> {
+ /// Creates a new hazard-pointer revocable instance.
+ pub fn new<E>(data_pin_init: impl PinInit<T, E>) -> impl PinInit<Self, E> {
+ try_pin_init!(Self {
+ data <- Opaque::pin_init(data_pin_init),
+ is_available: AtomicBool::new(true),
+ }? E)
+ }
+
+ /// Tries to access the wrapped object. Returns `None` if revoked.
+ ///
+ /// `ctx` is moved into the returned guard and released when the guard is dropped.
+ pub fn try_access<'a>(
+ &self,
+ ctx: Pin<&'a mut HazptrCtx>,
+ ) -> Option<HazPtrRevocableGuard<'a, T>> {
+ let data_ptr = self.data.get();
+ let guard = hazptr::acquire(ctx, addr_of!(data_ptr).cast())?;
+ if !self.is_available.load(Ordering::Relaxed) {
+ return None;
+ }
+ Some(HazPtrRevocableGuard::new(guard))
+ }
+
+ /// Revokes access and drops the wrapped object. Waits for readers via hazptr.
+ pub fn revoke(&self) -> bool {
+ let revoke = self.is_available.swap(false, Ordering::Relaxed);
+ if revoke {
+ hazptr::synchronize(self.data.get() as usize);
+ // SAFETY: `synchronize()` ensures no reader still holds the pointer,
+ // and `self.is_available` is false so no new reader can start, so
+ // `drop_in_place` is safe.
+ unsafe { drop_in_place(self.data.get()) };
+ }
+ revoke
+ }
+}
+
+#[pinned_drop]
+impl<T> PinnedDrop for HazPtrRevocable<T> {
+ fn drop(self: Pin<&mut Self>) {
+ // Drop only if the data hasn't been revoked yet (in which case it has already been
+ // dropped).
+ // SAFETY: We are not moving out of `p`, only dropping in place
+ let p = unsafe { self.get_unchecked_mut() };
+ if *p.is_available.get_mut() {
+ // SAFETY: We know `self.data` is valid because no other CPU has changed
+ // `is_available` to `false` yet, and no other CPU can do it anymore because this CPU
+ // holds the only reference (mutable) to `self` now.
+ unsafe { drop_in_place(p.data.get()) };
+ }
+ }
+}
+
+/// A handle to perform revocation on a [`HazPtrRevocable`]. Revokes when dropped.
+pub struct HazPtrRevokeHandle<'a, T>(&'a HazPtrRevocable<T>);
+
+impl<'a, T> HazPtrRevokeHandle<'a, T> {
+ /// Create a revoke-on-drop handle.
+ pub fn new(revocable: &'a HazPtrRevocable<T>) -> Self {
+ Self(revocable)
+ }
+
+ /// Dismiss the handle without revoking.
+ pub fn dismiss(self) {
+ core::mem::forget(self);
+ }
+}
+
+impl<T> Drop for HazPtrRevokeHandle<'_, T> {
+ fn drop(&mut self) {
+ self.0.revoke();
+ }
+}
+
+/// Guard for a [`HazPtrRevocable`].
+pub struct HazPtrRevocableGuard<'a, T> {
+ guard: hazptr::Guard<'a, T>,
+}
+
+impl<'a, T> HazPtrRevocableGuard<'a, T> {
+ fn new(guard: hazptr::Guard<'a, T>) -> Self {
+ Self { guard }
+ }
+}
+
+impl<T> Deref for HazPtrRevocableGuard<'_, T> {
+ type Target = T;
+
+ fn deref(&self) -> &Self::Target {
+ &self.guard
+ }
+}
+
/// An object that is initialized and can become inaccessible at runtime.
///
/// [`Revocable`] is initialized at the beginning, and can be made inaccessible at runtime.
--
2.43.0
^ permalink raw reply related [flat|nested] 14+ messages in thread
* [PATCH 06/13] rust: revocable: make LazyRevocable use HazPtrRevocable
2026-03-26 6:52 [PATCH 00/13] drm/tyr: add debugfs support Alvin Sun
` (4 preceding siblings ...)
2026-03-26 6:52 ` [PATCH 05/13] rust: revocable: add HazPtrRevocable Alvin Sun
@ 2026-03-26 6:52 ` Alvin Sun
2026-03-26 6:53 ` [PATCH 07/13] rust: drm: add Device::primary_index() Alvin Sun
` (6 subsequent siblings)
12 siblings, 0 replies; 14+ messages in thread
From: Alvin Sun @ 2026-03-26 6:52 UTC (permalink / raw)
To: Miguel Ojeda, Boqun Feng, Gary Guo, Björn Roy Baron,
Benno Lossin, Andreas Hindborg, Alice Ryhl, Trevor Gross,
Danilo Krummrich, David Airlie, Simona Vetter, Sumit Semwal,
Christian König, Daniel Almeida
Cc: rust-for-linux, dri-devel, Alvin Sun
Change LazyRevocable to use the existing HazPtrRevocable backend instead
of the RCU-based Revocable. init() now returns HazPtrRevokeHandle and
try_access(ctx) forwards to the hazptr-based implementation.
Signed-off-by: Alvin Sun <alvin.sun@linux.dev>
---
rust/kernel/revocable.rs | 18 +++++++++++-------
1 file changed, 11 insertions(+), 7 deletions(-)
diff --git a/rust/kernel/revocable.rs b/rust/kernel/revocable.rs
index eabb76ce92c43..e974c75a90ec0 100644
--- a/rust/kernel/revocable.rs
+++ b/rust/kernel/revocable.rs
@@ -421,7 +421,7 @@ fn deref(&self) -> &Self::Target {
#[pin_data]
pub struct LazyRevocable<T> {
#[pin]
- once: SetOnce<Revocable<T>>,
+ once: SetOnce<HazPtrRevocable<T>>,
}
impl<T> LazyRevocable<T> {
@@ -440,18 +440,22 @@ pub const fn new() -> Self {
pub fn init<E: Into<Error>>(
self: Pin<&Self>,
init: impl PinInit<T, E>,
- ) -> Result<RevokeHandle<'_, T>> {
+ ) -> Result<HazPtrRevokeHandle<'_, T>> {
// SAFETY: `once` is structurally pinned.
let once = unsafe { self.map_unchecked(|x| &x.once) };
- let revocable = once.pin_init(Revocable::new(init))?;
- Ok(RevokeHandle::new(revocable))
+ let revocable = once.pin_init(HazPtrRevocable::new(init))?;
+ Ok(HazPtrRevokeHandle::new(revocable))
}
/// Tries to access the revocable wrapped object.
///
- /// Returns `None` if the object has not been initialized, or it has been revoked and is therefore no longer accessible.
- pub fn try_access(&self) -> Option<RevocableGuard<'_, T>> {
- self.once.as_ref()?.try_access()
+ /// Returns `None` if the object has not been initialized, or it has been revoked and is
+ /// therefore no longer accessible.
+ pub fn try_access<'a>(
+ &self,
+ ctx: Pin<&'a mut HazptrCtx>,
+ ) -> Option<HazPtrRevocableGuard<'a, T>> {
+ self.once.as_ref()?.try_access(ctx)
}
}
--
2.43.0
^ permalink raw reply related [flat|nested] 14+ messages in thread
* [PATCH 07/13] rust: drm: add Device::primary_index()
2026-03-26 6:52 [PATCH 00/13] drm/tyr: add debugfs support Alvin Sun
` (5 preceding siblings ...)
2026-03-26 6:52 ` [PATCH 06/13] rust: revocable: make LazyRevocable use HazPtrRevocable Alvin Sun
@ 2026-03-26 6:53 ` Alvin Sun
2026-03-26 6:53 ` [PATCH 08/13] rust: drm/gem: add GEM object query helpers for debugfs Alvin Sun
` (5 subsequent siblings)
12 siblings, 0 replies; 14+ messages in thread
From: Alvin Sun @ 2026-03-26 6:53 UTC (permalink / raw)
To: Miguel Ojeda, Boqun Feng, Gary Guo, Björn Roy Baron,
Benno Lossin, Andreas Hindborg, Alice Ryhl, Trevor Gross,
Danilo Krummrich, David Airlie, Simona Vetter, Sumit Semwal,
Christian König, Daniel Almeida
Cc: rust-for-linux, dri-devel, Alvin Sun
Add primary_index() to return the primary minor index (e.g. the N in
/dev/dri/cardN). Needed by drivers to register per-device debugfs under
a unique directory name.
Signed-off-by: Alvin Sun <alvin.sun@linux.dev>
---
rust/kernel/drm/device.rs | 10 ++++++++++
1 file changed, 10 insertions(+)
diff --git a/rust/kernel/drm/device.rs b/rust/kernel/drm/device.rs
index d7bb338efb9d8..268ac02e800fd 100644
--- a/rust/kernel/drm/device.rs
+++ b/rust/kernel/drm/device.rs
@@ -336,6 +336,16 @@ pub(crate) unsafe fn assume_ctx<NewCtx: DeviceContext>(&self) -> &Device<T, NewC
}
}
+impl<T: drm::Driver> Device<T, Registered> {
+ /// Returns the primary minor index (the number in `/dev/dri/cardN`).
+ #[inline]
+ pub fn primary_index(&self) -> u32 {
+ // SAFETY: `self.as_raw()` is guaranteed to be a valid pointer to a `struct drm_device`.
+ let index = unsafe { (*(*self.as_raw()).primary).index };
+ index as u32
+ }
+}
+
impl<T: drm::Driver> Deref for Device<T, Registered> {
type Target = T::Data;
--
2.43.0
^ permalink raw reply related [flat|nested] 14+ messages in thread
* [PATCH 08/13] rust: drm/gem: add GEM object query helpers for debugfs
2026-03-26 6:52 [PATCH 00/13] drm/tyr: add debugfs support Alvin Sun
` (6 preceding siblings ...)
2026-03-26 6:53 ` [PATCH 07/13] rust: drm: add Device::primary_index() Alvin Sun
@ 2026-03-26 6:53 ` Alvin Sun
2026-03-26 6:53 ` [PATCH 09/13] rust: drm/gem/shmem: add resident_size() and madv() " Alvin Sun
` (4 subsequent siblings)
12 siblings, 0 replies; 14+ messages in thread
From: Alvin Sun @ 2026-03-26 6:53 UTC (permalink / raw)
To: Miguel Ojeda, Boqun Feng, Gary Guo, Björn Roy Baron,
Benno Lossin, Andreas Hindborg, Alice Ryhl, Trevor Gross,
Danilo Krummrich, David Airlie, Simona Vetter, Sumit Semwal,
Christian König, Daniel Almeida
Cc: rust-for-linux, dri-devel, Alvin Sun
Add name(), refcount(), is_imported(), is_exported(), and mmap_offset()
to BaseObject so drivers can expose GEM state in debugfs.
Signed-off-by: Alvin Sun <alvin.sun@linux.dev>
---
rust/kernel/drm/gem/mod.rs | 49 +++++++++++++++++++++++++++++++++++++++++++---
1 file changed, 46 insertions(+), 3 deletions(-)
diff --git a/rust/kernel/drm/gem/mod.rs b/rust/kernel/drm/gem/mod.rs
index 276ba3c53475d..b6188c8873ece 100644
--- a/rust/kernel/drm/gem/mod.rs
+++ b/rust/kernel/drm/gem/mod.rs
@@ -21,9 +21,13 @@
},
error::to_result,
prelude::*,
- sync::aref::{
- ARef,
- AlwaysRefCounted, //
+ sync::{
+ aref::{
+ ARef,
+ AlwaysRefCounted, //
+ },
+ atomic::Relaxed,
+ Refcount, //
},
types::Opaque,
};
@@ -177,6 +181,45 @@ fn size(&self) -> usize {
unsafe { (*self.as_raw()).size }
}
+ /// Returns the name of the object.
+ #[inline]
+ fn name(&self) -> i32 {
+ // SAFETY: `self.as_raw()` is guaranteed to be a pointer to a valid `struct drm_gem_object`.
+ unsafe { (*self.as_raw()).name }
+ }
+
+ /// Returns the reference count of the object.
+ #[inline]
+ fn refcount(&self) -> u32 {
+ // SAFETY: `self.as_raw()` is guaranteed to be a pointer to a valid `struct drm_gem_object`.
+ let raw_refcount = unsafe { &raw mut (*self.as_raw()).refcount }.cast::<Refcount>();
+ // SAFETY: `raw_refcount` has the same layout as `Refcount`.
+ let refcount = unsafe { &*raw_refcount };
+
+ refcount.as_atomic().load(Relaxed) as u32
+ }
+
+ /// Returns true if the object is imported.
+ #[inline]
+ fn is_imported(&self) -> bool {
+ // SAFETY: `self.as_raw()` is guaranteed to be a pointer to a valid `struct drm_gem_object`.
+ !unsafe { (*self.as_raw()).import_attach }.is_null()
+ }
+
+ /// Returns true if the object is exported.
+ #[inline]
+ fn is_exported(&self) -> bool {
+ // SAFETY: `self.as_raw()` is guaranteed to be a pointer to a valid `struct drm_gem_object`.
+ !unsafe { (*self.as_raw()).dma_buf }.is_null()
+ }
+
+ /// Returns the offset for mmap, or 0 if no offset has been allocated.
+ #[inline]
+ fn mmap_offset(&self) -> u64 {
+ // SAFETY: `self.as_raw()` is guaranteed to be a pointer to a valid `struct drm_gem_object`.
+ unsafe { (*self.as_raw()).vma_node.vm_node.start }
+ }
+
/// Creates a new handle for the object associated with a given `File`
/// (or returns an existing one).
fn create_handle<D, F>(&self, file: &drm::File<F>) -> Result<u32>
--
2.43.0
^ permalink raw reply related [flat|nested] 14+ messages in thread
* [PATCH 09/13] rust: drm/gem/shmem: add resident_size() and madv() for debugfs
2026-03-26 6:52 [PATCH 00/13] drm/tyr: add debugfs support Alvin Sun
` (7 preceding siblings ...)
2026-03-26 6:53 ` [PATCH 08/13] rust: drm/gem: add GEM object query helpers for debugfs Alvin Sun
@ 2026-03-26 6:53 ` Alvin Sun
2026-03-26 6:53 ` [PATCH 10/13] drm/tyr: expose Vm gpuvm_core, gpuvm and va_range as pub(crate) Alvin Sun
` (3 subsequent siblings)
12 siblings, 0 replies; 14+ messages in thread
From: Alvin Sun @ 2026-03-26 6:53 UTC (permalink / raw)
To: Miguel Ojeda, Boqun Feng, Gary Guo, Björn Roy Baron,
Benno Lossin, Andreas Hindborg, Alice Ryhl, Trevor Gross,
Danilo Krummrich, David Airlie, Simona Vetter, Sumit Semwal,
Christian König, Daniel Almeida
Cc: rust-for-linux, dri-devel, Alvin Sun
Expose resident size and madvise state of shmem GEM objects so drivers
can show per-BO memory usage and reclaimable size in debugfs.
Signed-off-by: Alvin Sun <alvin.sun@linux.dev>
---
rust/kernel/drm/gem/shmem.rs | 21 +++++++++++++++++++++
1 file changed, 21 insertions(+)
diff --git a/rust/kernel/drm/gem/shmem.rs b/rust/kernel/drm/gem/shmem.rs
index 065bdd78d1ba6..ba25a4a832db6 100644
--- a/rust/kernel/drm/gem/shmem.rs
+++ b/rust/kernel/drm/gem/shmem.rs
@@ -196,6 +196,27 @@ extern "C" fn free_callback(obj: *mut bindings::drm_gem_object) {
let _ = unsafe { KBox::from_raw(this) };
}
+ /// Returns the resident size of this object.
+ #[inline]
+ pub fn resident_size(&self) -> usize {
+ // SAFETY: `self.as_raw_shmem()` is guaranteed to be a valid pointer to a
+ // drm_gem_shmem_object.
+ if unsafe { (*self.as_raw_shmem()).pages }.is_null() {
+ 0
+ } else {
+ // SAFETY: `self.as_raw()` is guaranteed to be a valid pointer to a drm_gem_object.
+ unsafe { (*self.as_raw()).size }
+ }
+ }
+
+ /// Returns the state for madvise of this object.
+ #[inline]
+ pub fn madv(&self) -> i32 {
+ // SAFETY: `self.as_raw_shmem()` is guaranteed to be a valid pointer to a
+ // drm_gem_shmem_object.
+ unsafe { (*self.as_raw_shmem()).madv }
+ }
+
/// Creates (if necessary) and returns an immutable reference to a scatter-gather table of DMA
/// pages for this object.
///
--
2.43.0
^ permalink raw reply related [flat|nested] 14+ messages in thread
* [PATCH 10/13] drm/tyr: expose Vm gpuvm_core, gpuvm and va_range as pub(crate)
2026-03-26 6:52 [PATCH 00/13] drm/tyr: add debugfs support Alvin Sun
` (8 preceding siblings ...)
2026-03-26 6:53 ` [PATCH 09/13] rust: drm/gem/shmem: add resident_size() and madv() " Alvin Sun
@ 2026-03-26 6:53 ` Alvin Sun
2026-03-26 6:53 ` [PATCH 11/13] drm/tyr: add debugfs infrastructure Alvin Sun
` (2 subsequent siblings)
12 siblings, 0 replies; 14+ messages in thread
From: Alvin Sun @ 2026-03-26 6:53 UTC (permalink / raw)
To: Miguel Ojeda, Boqun Feng, Gary Guo, Björn Roy Baron,
Benno Lossin, Andreas Hindborg, Alice Ryhl, Trevor Gross,
Danilo Krummrich, David Airlie, Simona Vetter, Sumit Semwal,
Christian König, Daniel Almeida
Cc: rust-for-linux, dri-devel, Alvin Sun
Allow the debugfs module to read VM and GPU VA state for the gpuvas file.
Signed-off-by: Alvin Sun <alvin.sun@linux.dev>
---
drivers/gpu/drm/tyr/vm.rs | 6 +++---
1 file changed, 3 insertions(+), 3 deletions(-)
diff --git a/drivers/gpu/drm/tyr/vm.rs b/drivers/gpu/drm/tyr/vm.rs
index 936c3049812b3..ccf4493065a49 100644
--- a/drivers/gpu/drm/tyr/vm.rs
+++ b/drivers/gpu/drm/tyr/vm.rs
@@ -306,12 +306,12 @@ pub(crate) struct Vm {
pdev: ARef<platform::Device>,
/// DRM GPUVM core for managing virtual address space.
#[pin]
- gpuvm_core: Mutex<GpuVmCore<GpuVmData>>,
+ pub(crate) gpuvm_core: Mutex<GpuVmCore<GpuVmData>>,
/// Non-core part of the GPUVM. Can be used for stuff that doesn't modify the
/// internal mapping tree, like GpuVm::obtain()
- gpuvm: ARef<GpuVm<GpuVmData>>,
+ pub(crate) gpuvm: ARef<GpuVm<GpuVmData>>,
/// VA range for this VM.
- va_range: Range<u64>,
+ pub(crate) va_range: Range<u64>,
}
impl Vm {
--
2.43.0
^ permalink raw reply related [flat|nested] 14+ messages in thread
* [PATCH 11/13] drm/tyr: add debugfs infrastructure
2026-03-26 6:52 [PATCH 00/13] drm/tyr: add debugfs support Alvin Sun
` (9 preceding siblings ...)
2026-03-26 6:53 ` [PATCH 10/13] drm/tyr: expose Vm gpuvm_core, gpuvm and va_range as pub(crate) Alvin Sun
@ 2026-03-26 6:53 ` Alvin Sun
2026-03-26 6:53 ` [PATCH 12/13] drm/tyr: add vms and gpuvas debugfs interface Alvin Sun
2026-03-26 6:53 ` [PATCH 13/13] drm/tyr: add gems field and gems " Alvin Sun
12 siblings, 0 replies; 14+ messages in thread
From: Alvin Sun @ 2026-03-26 6:53 UTC (permalink / raw)
To: Miguel Ojeda, Boqun Feng, Gary Guo, Björn Roy Baron,
Benno Lossin, Andreas Hindborg, Alice Ryhl, Trevor Gross,
Danilo Krummrich, David Airlie, Simona Vetter, Sumit Semwal,
Christian König, Daniel Almeida
Cc: rust-for-linux, dri-devel, Alvin Sun
Add module debugfs root, per-device directory and TyrDebugFSData; wire
into driver and call debugfs_init.
Signed-off-by: Alvin Sun <alvin.sun@linux.dev>
---
drivers/gpu/drm/tyr/debugfs.rs | 46 ++++++++++++++++++++++++++++++++++++++++++
drivers/gpu/drm/tyr/driver.rs | 11 +++++++++-
drivers/gpu/drm/tyr/tyr.rs | 39 ++++++++++++++++++++++++++++++++---
3 files changed, 92 insertions(+), 4 deletions(-)
diff --git a/drivers/gpu/drm/tyr/debugfs.rs b/drivers/gpu/drm/tyr/debugfs.rs
new file mode 100644
index 0000000000000..254ecef43ea9a
--- /dev/null
+++ b/drivers/gpu/drm/tyr/debugfs.rs
@@ -0,0 +1,46 @@
+// SPDX-License-Identifier: GPL-2.0 or MIT
+
+//! Debugfs support for the Tyr DRM driver.
+
+use core::pin;
+
+use kernel::{
+ debugfs,
+ device::Core,
+ drm,
+ platform,
+ prelude::*,
+ revocable::LazyRevocable,
+ str::CString,
+ sync::{
+ hazptr::HazptrCtx,
+ Arc,
+ ArcBorrow, //
+ }, //
+};
+
+use crate::driver::TyrDrmDriver;
+
+pub(crate) static DEBUGFS_ROOT: LazyRevocable<debugfs::Dir> = LazyRevocable::new();
+
+/// Per-device debugfs data.
+pub(crate) struct TyrDebugFSData {}
+
+/// Registers per-device debugfs directory under the module's debugfs root.
+pub(crate) fn debugfs_init(
+ ddev: &drm::Device<TyrDrmDriver>,
+ pdev: &platform::Device<Core>,
+ debugfs_data: ArcBorrow<'_, TyrDebugFSData>,
+) -> Result {
+ let idx = ddev.primary_index();
+ let dir_name = CString::try_from_fmt(fmt!("{}", idx))?;
+ let ctx = pin::pin!(HazptrCtx::new());
+ let root_dir = DEBUGFS_ROOT.try_access(ctx).ok_or_else(|| {
+ pr_err!("DEBUGFS_ROOT is not set");
+ ENOENT
+ })?;
+ let debugfs_data: Arc<TyrDebugFSData> = debugfs_data.into();
+ let scope_init = root_dir.scope(debugfs_data, &dir_name, |_data, _dir| {});
+
+ kernel::devres::register(pdev.as_ref(), scope_init, GFP_KERNEL)
+}
diff --git a/drivers/gpu/drm/tyr/driver.rs b/drivers/gpu/drm/tyr/driver.rs
index 593f71c550e08..c8c929fda06ac 100644
--- a/drivers/gpu/drm/tyr/driver.rs
+++ b/drivers/gpu/drm/tyr/driver.rs
@@ -38,6 +38,7 @@
};
use crate::{
+ debugfs::TyrDebugFSData,
file::TyrDrmFileData,
fw::Firmware,
gem::BoData,
@@ -75,6 +76,9 @@ pub(crate) struct TyrDrmDeviceData {
///
/// This is mainly queried by userspace, i.e.: Mesa.
pub(crate) gpu_info: GpuInfo,
+
+ /// Per-device debugfs data.
+ pub(crate) debugfs_data: Arc<TyrDebugFSData>,
}
// Both `Clk` and `Regulator` do not implement `Send` or `Sync`, but they
@@ -150,6 +154,8 @@ fn probe(
let platform: ARef<platform::Device> = pdev.into();
let mmu = Mmu::new(pdev, iomem.as_arc_borrow(), &gpu_info)?;
+ let debugfs_data = Arc::new(TyrDebugFSData {}, GFP_KERNEL)?;
+ let debugfs_data_clone = debugfs_data.clone();
let firmware = Firmware::new(
pdev,
@@ -174,9 +180,12 @@ fn probe(
_sram: sram_regulator,
}),
gpu_info,
+ debugfs_data: debugfs_data_clone,
});
-
let ddev = Registration::new_foreign_owned(uninit_ddev, pdev.as_ref(), data, 0)?;
+
+ crate::debugfs::debugfs_init(ddev, pdev, debugfs_data.as_arc_borrow())?;
+
let driver = TyrPlatformDriverData {
_device: ddev.into(),
};
diff --git a/drivers/gpu/drm/tyr/tyr.rs b/drivers/gpu/drm/tyr/tyr.rs
index 18b0668bb2178..cda4955db4dc9 100644
--- a/drivers/gpu/drm/tyr/tyr.rs
+++ b/drivers/gpu/drm/tyr/tyr.rs
@@ -5,8 +5,20 @@
//! The name "Tyr" is inspired by Norse mythology, reflecting Arm's tradition of
//! naming their GPUs after Nordic mythological figures and places.
-use crate::driver::TyrPlatformDriverData;
+use crate::{
+ debugfs::DEBUGFS_ROOT,
+ driver::TyrPlatformDriverData, //
+};
+use kernel::{
+ driver::Registration,
+ error,
+ platform,
+ prelude::*,
+ revocable::HazPtrRevokeHandle,
+ InPlaceModule, //
+};
+mod debugfs;
mod driver;
mod file;
mod fw;
@@ -17,8 +29,29 @@
mod slot;
mod vm;
-kernel::module_platform_driver! {
- type: TyrPlatformDriverData,
+pub(crate) const MODULE_NAME: &kernel::str::CStr = <LocalModule as kernel::ModuleMetadata>::NAME;
+
+#[pin_data]
+struct TyrModule {
+ _debugfs_root: HazPtrRevokeHandle<'static, kernel::debugfs::Dir>,
+ #[pin]
+ _driver: Registration<platform::Adapter<TyrPlatformDriverData>>,
+}
+
+impl InPlaceModule for TyrModule {
+ fn init(module: &'static kernel::ThisModule) -> impl PinInit<Self, error::Error> {
+ let dir = kernel::debugfs::Dir::new(kernel::c_str!("tyr"));
+ let debugfs_root_handle = Pin::static_ref(&DEBUGFS_ROOT).init(dir);
+
+ try_pin_init!(Self {
+ _driver <- Registration::new(MODULE_NAME, module),
+ _debugfs_root <- debugfs_root_handle,
+ })
+ }
+}
+
+module! {
+ type: TyrModule,
name: "tyr",
authors: ["The Tyr driver authors"],
description: "Arm Mali Tyr DRM driver",
--
2.43.0
^ permalink raw reply related [flat|nested] 14+ messages in thread
* [PATCH 12/13] drm/tyr: add vms and gpuvas debugfs interface
2026-03-26 6:52 [PATCH 00/13] drm/tyr: add debugfs support Alvin Sun
` (10 preceding siblings ...)
2026-03-26 6:53 ` [PATCH 11/13] drm/tyr: add debugfs infrastructure Alvin Sun
@ 2026-03-26 6:53 ` Alvin Sun
2026-03-26 6:53 ` [PATCH 13/13] drm/tyr: add gems field and gems " Alvin Sun
12 siblings, 0 replies; 14+ messages in thread
From: Alvin Sun @ 2026-03-26 6:53 UTC (permalink / raw)
To: Miguel Ojeda, Boqun Feng, Gary Guo, Björn Roy Baron,
Benno Lossin, Andreas Hindborg, Alice Ryhl, Trevor Gross,
Danilo Krummrich, David Airlie, Simona Vetter, Sumit Semwal,
Christian König, Daniel Almeida
Cc: rust-for-linux, dri-devel, Alvin Sun
Add vms list to Mmu and vms field to TyrDebugFSData; populate vms in
Firmware::new and register gpuvas read-only file under debugfs
per-device directory.
Signed-off-by: Alvin Sun <alvin.sun@linux.dev>
---
drivers/gpu/drm/tyr/debugfs.rs | 59 +++++++++++++++++++++++++++++++++++++++---
drivers/gpu/drm/tyr/driver.rs | 5 +++-
drivers/gpu/drm/tyr/fw.rs | 5 +++-
drivers/gpu/drm/tyr/mmu.rs | 6 ++++-
4 files changed, 69 insertions(+), 6 deletions(-)
diff --git a/drivers/gpu/drm/tyr/debugfs.rs b/drivers/gpu/drm/tyr/debugfs.rs
index 254ecef43ea9a..edbdb83a5b132 100644
--- a/drivers/gpu/drm/tyr/debugfs.rs
+++ b/drivers/gpu/drm/tyr/debugfs.rs
@@ -8,6 +8,9 @@
debugfs,
device::Core,
drm,
+ drm::gem::IntoGEMObject,
+ fmt,
+ fmt::Write,
platform,
prelude::*,
revocable::LazyRevocable,
@@ -15,16 +18,64 @@
sync::{
hazptr::HazptrCtx,
Arc,
- ArcBorrow, //
+ ArcBorrow,
+ Mutex, //
}, //
};
use crate::driver::TyrDrmDriver;
+use crate::vm::Vm;
pub(crate) static DEBUGFS_ROOT: LazyRevocable<debugfs::Dir> = LazyRevocable::new();
/// Per-device debugfs data.
-pub(crate) struct TyrDebugFSData {}
+#[pin_data]
+pub(crate) struct TyrDebugFSData {
+ #[pin]
+ pub(crate) vms: Mutex<KVec<Arc<Vm>>>,
+}
+
+/// Writes VM debug information for the "gpuvas" debugfs file.
+fn show_vm(vm: &Vm, f: &mut impl Write) -> core::fmt::Result {
+ writeln!(
+ f,
+ "DRM GPU VA space ({:?}) [0x{:016x};0x{:016x}]",
+ vm.gpuvm.name(),
+ vm.va_range.start,
+ vm.va_range.end,
+ )?;
+
+ let kva = vm.gpuvm.kernel_alloc_va();
+ writeln!(
+ f,
+ "Kernel reserved node [0x{:016x};0x{:016x}]",
+ kva.addr(),
+ kva.addr() + kva.length(),
+ )?;
+
+ writeln!(f, " VAs | start | range | end | object | object offset")?;
+ writeln!(f, "-------------------------------------------------------------------------------------------------------------")?;
+ for va in vm.gpuvm_core.lock().va_mappings() {
+ f.write_fmt(fmt!(
+ " | 0x{:016x} | 0x{:016x} | 0x{:016x} | {:18p} | 0x{:016x}\n",
+ va.addr(),
+ va.length(),
+ va.addr() + va.length(),
+ va.obj().as_raw(),
+ va.gem_offset(),
+ ))?;
+ }
+ Ok(())
+}
+
+fn show_gpuvas(data: &Arc<TyrDebugFSData>, f: &mut fmt::Formatter<'_>) -> core::fmt::Result {
+ let vms = data.vms.lock();
+ for vm in vms.iter() {
+ show_vm(vm, f)?;
+ writeln!(f)?;
+ }
+ Ok(())
+}
/// Registers per-device debugfs directory under the module's debugfs root.
pub(crate) fn debugfs_init(
@@ -40,7 +91,9 @@ pub(crate) fn debugfs_init(
ENOENT
})?;
let debugfs_data: Arc<TyrDebugFSData> = debugfs_data.into();
- let scope_init = root_dir.scope(debugfs_data, &dir_name, |_data, _dir| {});
+ let scope_init = root_dir.scope(debugfs_data, &dir_name, |data, dir| {
+ dir.read_callback_file(c"gpuvas", data, &show_gpuvas);
+ });
kernel::devres::register(pdev.as_ref(), scope_init, GFP_KERNEL)
}
diff --git a/drivers/gpu/drm/tyr/driver.rs b/drivers/gpu/drm/tyr/driver.rs
index c8c929fda06ac..e1d5e908de876 100644
--- a/drivers/gpu/drm/tyr/driver.rs
+++ b/drivers/gpu/drm/tyr/driver.rs
@@ -154,7 +154,9 @@ fn probe(
let platform: ARef<platform::Device> = pdev.into();
let mmu = Mmu::new(pdev, iomem.as_arc_borrow(), &gpu_info)?;
- let debugfs_data = Arc::new(TyrDebugFSData {}, GFP_KERNEL)?;
+ let debugfs_data = Arc::pin_init(try_pin_init!(TyrDebugFSData {
+ vms <- new_mutex!(KVec::new()),
+ }), GFP_KERNEL)?;
let debugfs_data_clone = debugfs_data.clone();
let firmware = Firmware::new(
@@ -163,6 +165,7 @@ fn probe(
&uninit_ddev,
mmu.as_arc_borrow(),
&gpu_info,
+ debugfs_data.as_arc_borrow(),
)?;
firmware.boot()?;
diff --git a/drivers/gpu/drm/tyr/fw.rs b/drivers/gpu/drm/tyr/fw.rs
index b62e5ed69c4d4..c46320bb54516 100644
--- a/drivers/gpu/drm/tyr/fw.rs
+++ b/drivers/gpu/drm/tyr/fw.rs
@@ -37,6 +37,7 @@
};
use crate::{
+ debugfs::TyrDebugFSData,
driver::{
IoMem,
TyrDrmDevice, //
@@ -200,6 +201,7 @@ pub(crate) fn new(
ddev: &TyrDrmDevice<Uninit>,
mmu: ArcBorrow<'_, Mmu>,
gpu_info: &GpuInfo,
+ debugfs_data: ArcBorrow<'_, TyrDebugFSData>,
) -> Result<Arc<Firmware>> {
let vm = Vm::new(pdev, ddev, mmu, gpu_info)?;
@@ -238,11 +240,12 @@ pub(crate) fn new(
Firmware {
pdev: pdev.into(),
iomem: iomem.into(),
- vm,
+ vm: vm.clone(),
sections,
},
GFP_KERNEL,
)?;
+ debugfs_data.vms.lock().push(vm, GFP_KERNEL)?;
Ok(firmware)
}
diff --git a/drivers/gpu/drm/tyr/mmu.rs b/drivers/gpu/drm/tyr/mmu.rs
index 52a6bbbb179a2..d5e6af4b804e4 100644
--- a/drivers/gpu/drm/tyr/mmu.rs
+++ b/drivers/gpu/drm/tyr/mmu.rs
@@ -35,7 +35,8 @@
VmAsData, //
},
regs::MAX_AS_REGISTERS,
- slot::SlotManager, //
+ slot::SlotManager,
+ vm, //
};
pub(crate) mod address_space;
@@ -51,6 +52,8 @@
/// threads. Methods may block if another thread holds the lock.
#[pin_data]
pub(crate) struct Mmu {
+ #[pin]
+ pub(crate) vms: Mutex<KVec<Arc<vm::Vm>>>,
/// Manages the allocation of hardware MMU slots to GPU address spaces.
///
/// Tracks which address spaces are currently active in hardware slots and
@@ -75,6 +78,7 @@ pub(crate) fn new(
let as_manager = AddressSpaceManager::new(pdev, iomem, gpu_info.as_present)?;
let mmu_init = try_pin_init!(Self{
as_manager <- new_mutex!(SlotManager::new(as_manager, slot_count)?),
+ vms <- new_mutex!(KVec::new()),
});
Arc::pin_init(mmu_init, GFP_KERNEL)
}
--
2.43.0
^ permalink raw reply related [flat|nested] 14+ messages in thread
* [PATCH 13/13] drm/tyr: add gems field and gems debugfs interface
2026-03-26 6:52 [PATCH 00/13] drm/tyr: add debugfs support Alvin Sun
` (11 preceding siblings ...)
2026-03-26 6:53 ` [PATCH 12/13] drm/tyr: add vms and gpuvas debugfs interface Alvin Sun
@ 2026-03-26 6:53 ` Alvin Sun
12 siblings, 0 replies; 14+ messages in thread
From: Alvin Sun @ 2026-03-26 6:53 UTC (permalink / raw)
To: Miguel Ojeda, Boqun Feng, Gary Guo, Björn Roy Baron,
Benno Lossin, Andreas Hindborg, Alice Ryhl, Trevor Gross,
Danilo Krummrich, David Airlie, Simona Vetter, Sumit Semwal,
Christian König, Daniel Almeida
Cc: rust-for-linux, dri-devel, Alvin Sun
Add gems field to TyrDebugFSData; populate gems in Firmware::new and
register gems read-only file under debugfs per-device directory.
Signed-off-by: Alvin Sun <alvin.sun@linux.dev>
---
drivers/gpu/drm/tyr/debugfs.rs | 93 +++++++++++++++++++++++++++++++++++++++++-
drivers/gpu/drm/tyr/driver.rs | 10 +++--
drivers/gpu/drm/tyr/fw.rs | 2 +
3 files changed, 101 insertions(+), 4 deletions(-)
diff --git a/drivers/gpu/drm/tyr/debugfs.rs b/drivers/gpu/drm/tyr/debugfs.rs
index edbdb83a5b132..d0e9e268aeac2 100644
--- a/drivers/gpu/drm/tyr/debugfs.rs
+++ b/drivers/gpu/drm/tyr/debugfs.rs
@@ -8,14 +8,19 @@
debugfs,
device::Core,
drm,
- drm::gem::IntoGEMObject,
+ drm::gem::{
+ BaseObject,
+ IntoGEMObject, //
+ },
fmt,
fmt::Write,
+ impl_flags,
platform,
prelude::*,
revocable::LazyRevocable,
str::CString,
sync::{
+ aref::ARef,
hazptr::HazptrCtx,
Arc,
ArcBorrow,
@@ -24,15 +29,100 @@
};
use crate::driver::TyrDrmDriver;
+use crate::gem::Bo;
use crate::vm::Vm;
pub(crate) static DEBUGFS_ROOT: LazyRevocable<debugfs::Dir> = LazyRevocable::new();
+impl_flags!(
+ #[derive(Debug, Clone, Default, Copy, PartialEq, Eq)]
+ struct BoStateFlags(u32);
+
+ #[derive(Debug, Clone, Copy, PartialEq, Eq)]
+ enum BoStateFlag {
+ Imported = 1 << 0,
+ Exported = 1 << 1,
+ }
+);
+
+/// Writes per-BO debug information for the "gems" debugfs file.
+fn show_bo(bo: &Bo, f: &mut impl Write) -> core::fmt::Result {
+ let name: i32 = bo.name();
+ let refcount: u32 = bo.refcount();
+ let size: usize = bo.size();
+ let resident_size: usize = bo.resident_size();
+ let mmap_offset = bo.mmap_offset();
+ let mut gem_state_flags = BoStateFlags::default();
+
+ if bo.is_imported() {
+ gem_state_flags |= BoStateFlag::Imported;
+ }
+ if bo.is_exported() {
+ gem_state_flags |= BoStateFlag::Exported;
+ }
+
+ writeln!(
+ f,
+ "{:<16}{:<16}{:<16}{:<16}0x{:<16x}0x{:<8x}",
+ name,
+ refcount,
+ size,
+ resident_size,
+ mmap_offset,
+ u32::from(gem_state_flags),
+ )
+}
+
+fn show_gems(data: &Arc<TyrDebugFSData>, f: &mut fmt::Formatter<'_>) -> core::fmt::Result {
+ writeln!(
+ f,
+ "GEM state flags: {:?} (0x{:x}), {:?} (0x{:x})",
+ BoStateFlag::Imported,
+ BoStateFlag::Imported as u32,
+ BoStateFlag::Exported,
+ BoStateFlag::Exported as u32,
+ )?;
+ writeln!(
+ f,
+ "global-name refcount size resident-size file-offset state",
+ )?;
+ writeln!(
+ f,
+ "--------------------------------------------------------------------------------------------",
+ )?;
+
+ let mut total_size: usize = 0;
+ let mut total_resident: usize = 0;
+ let mut total_reclaimable: usize = 0;
+ let gems = data.gems.lock();
+ for bo in gems.iter() {
+ total_size += bo.size();
+ total_resident += bo.resident_size();
+ if bo.madv() > 0 {
+ total_reclaimable += bo.resident_size();
+ }
+ show_bo(bo, f)?;
+ }
+
+ writeln!(
+ f,
+ "============================================================================================",
+ )?;
+ writeln!(
+ f,
+ "Total size: {}, Total resident: {}, Total reclaimable: {}",
+ total_size, total_resident, total_reclaimable,
+ )?;
+ Ok(())
+}
+
/// Per-device debugfs data.
#[pin_data]
pub(crate) struct TyrDebugFSData {
#[pin]
pub(crate) vms: Mutex<KVec<Arc<Vm>>>,
+ #[pin]
+ pub(crate) gems: Mutex<KVec<ARef<Bo>>>,
}
/// Writes VM debug information for the "gpuvas" debugfs file.
@@ -93,6 +183,7 @@ pub(crate) fn debugfs_init(
let debugfs_data: Arc<TyrDebugFSData> = debugfs_data.into();
let scope_init = root_dir.scope(debugfs_data, &dir_name, |data, dir| {
dir.read_callback_file(c"gpuvas", data, &show_gpuvas);
+ dir.read_callback_file(c"gems", data, &show_gems);
});
kernel::devres::register(pdev.as_ref(), scope_init, GFP_KERNEL)
diff --git a/drivers/gpu/drm/tyr/driver.rs b/drivers/gpu/drm/tyr/driver.rs
index e1d5e908de876..a6d8760070d44 100644
--- a/drivers/gpu/drm/tyr/driver.rs
+++ b/drivers/gpu/drm/tyr/driver.rs
@@ -154,9 +154,13 @@ fn probe(
let platform: ARef<platform::Device> = pdev.into();
let mmu = Mmu::new(pdev, iomem.as_arc_borrow(), &gpu_info)?;
- let debugfs_data = Arc::pin_init(try_pin_init!(TyrDebugFSData {
- vms <- new_mutex!(KVec::new()),
- }), GFP_KERNEL)?;
+ let debugfs_data = Arc::pin_init(
+ try_pin_init!(TyrDebugFSData {
+ vms <- new_mutex!(KVec::new()),
+ gems <- new_mutex!(KVec::new()),
+ }),
+ GFP_KERNEL,
+ )?;
let debugfs_data_clone = debugfs_data.clone();
let firmware = Firmware::new(
diff --git a/drivers/gpu/drm/tyr/fw.rs b/drivers/gpu/drm/tyr/fw.rs
index c46320bb54516..4d5efa79a7348 100644
--- a/drivers/gpu/drm/tyr/fw.rs
+++ b/drivers/gpu/drm/tyr/fw.rs
@@ -222,6 +222,8 @@ pub(crate) fn new(
parsed.vm_map_flags,
)?;
+ debugfs_data.gems.lock().push(mem.bo.clone(), GFP_KERNEL)?;
+
let section_start = parsed.data_range.start as usize;
let section_end = parsed.data_range.end as usize;
let mut data = KVec::new();
--
2.43.0
^ permalink raw reply related [flat|nested] 14+ messages in thread
end of thread, other threads:[~2026-03-26 6:53 UTC | newest]
Thread overview: 14+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2026-03-26 6:52 [PATCH 00/13] drm/tyr: add debugfs support Alvin Sun
2026-03-26 6:52 ` [PATCH 01/13] rust: sync: support [pin_]init for `SetOnce` Alvin Sun
2026-03-26 6:52 ` [PATCH 02/13] rust: revocable: add lazily instantiated revocable variant Alvin Sun
2026-03-26 6:52 ` [PATCH 03/13] rust: sync: set_once: Rename InitError variants to fix clippy warning Alvin Sun
2026-03-26 6:52 ` [PATCH 04/13] rust: sync: add hazard pointer abstraction Alvin Sun
2026-03-26 6:52 ` [PATCH 05/13] rust: revocable: add HazPtrRevocable Alvin Sun
2026-03-26 6:52 ` [PATCH 06/13] rust: revocable: make LazyRevocable use HazPtrRevocable Alvin Sun
2026-03-26 6:53 ` [PATCH 07/13] rust: drm: add Device::primary_index() Alvin Sun
2026-03-26 6:53 ` [PATCH 08/13] rust: drm/gem: add GEM object query helpers for debugfs Alvin Sun
2026-03-26 6:53 ` [PATCH 09/13] rust: drm/gem/shmem: add resident_size() and madv() " Alvin Sun
2026-03-26 6:53 ` [PATCH 10/13] drm/tyr: expose Vm gpuvm_core, gpuvm and va_range as pub(crate) Alvin Sun
2026-03-26 6:53 ` [PATCH 11/13] drm/tyr: add debugfs infrastructure Alvin Sun
2026-03-26 6:53 ` [PATCH 12/13] drm/tyr: add vms and gpuvas debugfs interface Alvin Sun
2026-03-26 6:53 ` [PATCH 13/13] drm/tyr: add gems field and gems " Alvin Sun
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox