public inbox for linux-kernel@vger.kernel.org
 help / color / mirror / Atom feed
* [PATCH 0/4] rust: Add ARef support for work items
@ 2026-01-16  0:35 Daniel Almeida
  2026-01-16  0:35 ` [PATCH 1/4] rust: workqueue: add support for ARef<T> Daniel Almeida
                   ` (4 more replies)
  0 siblings, 5 replies; 10+ messages in thread
From: Daniel Almeida @ 2026-01-16  0:35 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
  Cc: rust-for-linux, linux-kernel, dri-devel, Daniel Almeida

This series adds ARef<T> support for both regular and delayed work items. 

- Patches 1 and 3 actually implement the support in workqueue.rs
- Patches 2 and 4 adds a corresponding implementation in drm::Device that
  dispatches the calls to the underlying T::Data.

This was tested on Tyr, and is actually needed in order to obtain a
&drm::Device when handling work items. This is then needed in order to
allocate GEM objects inside the work handler that processes the tiler OOM
(out of memory) events. The current series sets the stage so that the above
is possible in the future.

This is currently based on v6.19-rc5. I hope we can land all four commits
on a single tree, but otherwise let me know whether I should split the
workqueue.rs changes from the drm::Device ones and rebase accordingly.

---
Daniel Almeida (4):
      rust: workqueue: add support for ARef<T>
      rust: drm: dispatch work items to the private data
      rust: workqueue: add delayed work support for ARef<T>
      rust: drm: dispatch delayed work items to the private data

 rust/kernel/drm/device.rs | 66 ++++++++++++++++++++++++++++++--
 rust/kernel/workqueue.rs  | 96 ++++++++++++++++++++++++++++++++++++++++++++---
 2 files changed, 152 insertions(+), 10 deletions(-)
---
base-commit: 0f61b1860cc3f52aef9036d7235ed1f017632193
change-id: 20260115-aref-workitem-0f57e4fb81ca

Best regards,
-- 
Daniel Almeida <daniel.almeida@collabora.com>


^ permalink raw reply	[flat|nested] 10+ messages in thread

* [PATCH 1/4] rust: workqueue: add support for ARef<T>
  2026-01-16  0:35 [PATCH 0/4] rust: Add ARef support for work items Daniel Almeida
@ 2026-01-16  0:35 ` Daniel Almeida
  2026-01-16  0:35 ` [PATCH 2/4] rust: drm: dispatch work items to the private data Daniel Almeida
                   ` (3 subsequent siblings)
  4 siblings, 0 replies; 10+ messages in thread
From: Daniel Almeida @ 2026-01-16  0:35 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
  Cc: rust-for-linux, linux-kernel, dri-devel, Daniel Almeida

Add support for the ARef<T> smart pointer. This allows an instance of
ARef<T> to handle deferred work directly, which can be convenient or even
necessary at times, depending on the specifics of the driver or subsystem.

The implementation is similar to that of Arc<T>, and a subsequent patch
will implement support for drm::Device as the first user. This is notably
important for work items that need access to the drm device, as it was not
possible to enqueue work on a ARef<drm::Device<T>> previously without
failing the orphan rule.

Signed-off-by: Daniel Almeida <daniel.almeida@collabora.com>
---
 rust/kernel/workqueue.rs | 85 ++++++++++++++++++++++++++++++++++++++++++++----
 1 file changed, 79 insertions(+), 6 deletions(-)

diff --git a/rust/kernel/workqueue.rs b/rust/kernel/workqueue.rs
index 706e833e9702..6ae7f3fb3496 100644
--- a/rust/kernel/workqueue.rs
+++ b/rust/kernel/workqueue.rs
@@ -192,9 +192,9 @@
     sync::Arc,
     sync::LockClassKey,
     time::Jiffies,
-    types::Opaque,
+    types::{ARef, AlwaysRefCounted, Opaque},
 };
-use core::marker::PhantomData;
+use core::{marker::PhantomData, ptr::NonNull};
 
 /// Creates a [`Work`] initialiser with the given name and a newly-created lock class.
 #[macro_export]
@@ -425,10 +425,11 @@ pub unsafe trait RawDelayedWorkItem<const ID: u64>: RawWorkItem<ID> {}
 
 /// Defines the method that should be called directly when a work item is executed.
 ///
-/// This trait is implemented by `Pin<KBox<T>>` and [`Arc<T>`], and is mainly intended to be
-/// implemented for smart pointer types. For your own structs, you would implement [`WorkItem`]
-/// instead. The [`run`] method on this trait will usually just perform the appropriate
-/// `container_of` translation and then call into the [`run`][WorkItem::run] method from the
+/// This trait is implemented by `Pin<KBox<T>>`, [`Arc<T>`] and [`ARef<T>`], and
+/// is mainly intended to be implemented for smart pointer types. For your own
+/// structs, you would implement [`WorkItem`] instead. The [`run`] method on
+/// this trait will usually just perform the appropriate `container_of`
+/// translation and then call into the [`run`][WorkItem::run] method from the
 /// [`WorkItem`] trait.
 ///
 /// This trait is used when the `work_struct` field is defined using the [`Work`] helper.
@@ -934,6 +935,78 @@ unsafe impl<T, const ID: u64> RawDelayedWorkItem<ID> for Pin<KBox<T>>
 {
 }
 
+// SAFETY: Like the `Arc<T>` implementation, the `__enqueue` implementation for
+// `ARef<T>` obtains a `work_struct` from the `Work` field using
+// `T::raw_get_work`, so the same safety reasoning applies:
+//
+//   - `__enqueue` gets the `work_struct` from the `Work` field, using `T::raw_get_work`.
+//   - The only safe way to create a `Work` object is through `Work::new`.
+//   - `Work::new` makes sure that `T::Pointer::run` is passed to `init_work_with_key`.
+//   - Finally `Work` and `RawWorkItem` guarantee that the correct `Work` field
+//     will be used because of the ID const generic bound. This makes sure that `T::raw_get_work`
+//     uses the correct offset for the `Work` field, and `Work::new` picks the correct
+//     implementation of `WorkItemPointer` for `ARef<T>`.
+unsafe impl<T, const ID: u64> WorkItemPointer<ID> for ARef<T>
+where
+    T: AlwaysRefCounted,
+    T: WorkItem<ID, Pointer = Self>,
+    T: HasWork<T, ID>,
+{
+    unsafe extern "C" fn run(ptr: *mut bindings::work_struct) {
+        // The `__enqueue` method always uses a `work_struct` stored in a `Work<T, ID>`.
+        let ptr = ptr.cast::<Work<T, ID>>();
+
+        // SAFETY: This computes the pointer that `__enqueue` got from
+        // `ARef::into_raw`.
+        let ptr = unsafe { T::work_container_of(ptr) };
+
+        // SAFETY: The safety contract of `work_container_of` ensures that it
+        // returns a valid non-null pointer.
+        let ptr = unsafe { NonNull::new_unchecked(ptr) };
+
+        // SAFETY: This pointer comes from `ARef::into_raw` and we've been given
+        // back ownership.
+        let aref = unsafe { ARef::from_raw(ptr) };
+
+        T::run(aref)
+    }
+}
+
+// SAFETY: The `work_struct` raw pointer is guaranteed to be valid for the duration of the call to
+// the closure because we get it from an `ARef`, which means that the ref count will be at least 1,
+// and we don't drop the `ARef` ourselves. If `queue_work_on` returns true, it is further guaranteed
+// to be valid until a call to the function pointer in `work_struct` because we leak the memory it
+// points to, and only reclaim it if the closure returns false, or in `WorkItemPointer::run`, which
+// is what the function pointer in the `work_struct` must be pointing to, according to the safety
+// requirements of `WorkItemPointer`.
+unsafe impl<T, const ID: u64> RawWorkItem<ID> for ARef<T>
+where
+    T: AlwaysRefCounted,
+    T: WorkItem<ID, Pointer = Self>,
+    T: HasWork<T, ID>,
+{
+    type EnqueueOutput = Result<(), Self>;
+
+    unsafe fn __enqueue<F>(self, queue_work_on: F) -> Self::EnqueueOutput
+    where
+        F: FnOnce(*mut bindings::work_struct) -> bool,
+    {
+        let ptr = ARef::into_raw(self);
+
+        // SAFETY: Pointers from ARef::into_raw are valid and non-null.
+        let work_ptr = unsafe { T::raw_get_work(ptr.as_ptr()) };
+        // SAFETY: `raw_get_work` returns a pointer to a valid value.
+        let work_ptr = unsafe { Work::raw_get(work_ptr) };
+
+        if queue_work_on(work_ptr) {
+            Ok(())
+        } else {
+            // SAFETY: The work queue has not taken ownership of the pointer.
+            Err(unsafe { ARef::from_raw(ptr) })
+        }
+    }
+}
+
 /// Returns the system work queue (`system_wq`).
 ///
 /// It is the one used by `schedule[_delayed]_work[_on]()`. Multi-CPU multi-threaded. There are

-- 
2.52.0


^ permalink raw reply related	[flat|nested] 10+ messages in thread

* [PATCH 2/4] rust: drm: dispatch work items to the private data
  2026-01-16  0:35 [PATCH 0/4] rust: Add ARef support for work items Daniel Almeida
  2026-01-16  0:35 ` [PATCH 1/4] rust: workqueue: add support for ARef<T> Daniel Almeida
@ 2026-01-16  0:35 ` Daniel Almeida
  2026-01-20 11:13   ` Danilo Krummrich
  2026-01-16  0:35 ` [PATCH 3/4] rust: workqueue: add delayed work support for ARef<T> Daniel Almeida
                   ` (2 subsequent siblings)
  4 siblings, 1 reply; 10+ messages in thread
From: Daniel Almeida @ 2026-01-16  0:35 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
  Cc: rust-for-linux, linux-kernel, dri-devel, Daniel Almeida

This implementation dispatches any work enqueued on ARef<drm::Device<T>> to
its driver-provided handler. It does so by building upon the newly-added
ARef<T> support in workqueue.rs in order to call into the driver
implementations for work_container_of and raw_get_work.

This is notably important for work items that need access to the drm
device, as it was not possible to enqueue work on a ARef<drm::Device<T>>
previously without failing the orphan rule.

The current implementation needs T::Data to live inline with drm::Device in
order for work_container_of to function. This restriction is already
captured by the trait bounds. Drivers that need to share their ownership of
T::Data may trivially get around this:

// Lives inline in drm::Device
struct DataWrapper {
  work: ...,
  // Heap-allocated, shared ownership.
  data: Arc<DriverData>,
}

Signed-off-by: Daniel Almeida <daniel.almeida@collabora.com>
---
 rust/kernel/drm/device.rs | 54 +++++++++++++++++++++++++++++++++++++++++++----
 1 file changed, 50 insertions(+), 4 deletions(-)

diff --git a/rust/kernel/drm/device.rs b/rust/kernel/drm/device.rs
index 3ce8f62a0056..c760a743e1df 100644
--- a/rust/kernel/drm/device.rs
+++ b/rust/kernel/drm/device.rs
@@ -6,13 +6,13 @@
 
 use crate::{
     alloc::allocator::Kmalloc,
-    bindings, device, drm,
-    drm::driver::AllocImpl,
-    error::from_err_ptr,
-    error::Result,
+    bindings, device,
+    drm::{self, driver::AllocImpl},
+    error::{from_err_ptr, Result},
     prelude::*,
     sync::aref::{ARef, AlwaysRefCounted},
     types::Opaque,
+    workqueue::{HasWork, Work, WorkItem},
 };
 use core::{alloc::Layout, mem, ops::Deref, ptr, ptr::NonNull};
 
@@ -227,3 +227,49 @@ unsafe impl<T: drm::Driver> Send for Device<T> {}
 // SAFETY: A `drm::Device` can be shared among threads because all immutable methods are protected
 // by the synchronization in `struct drm_device`.
 unsafe impl<T: drm::Driver> Sync for Device<T> {}
+
+impl<T, const ID: u64> WorkItem<ID> for Device<T>
+where
+    T: drm::Driver,
+    T::Data: WorkItem<ID, Pointer = ARef<Device<T>>>,
+    T::Data: HasWork<Device<T>, ID>,
+{
+    type Pointer = ARef<Device<T>>;
+
+    fn run(ptr: ARef<Device<T>>) {
+        T::Data::run(ptr);
+    }
+}
+
+// SAFETY:
+//
+// - `raw_get_work` and `work_container_of` return valid pointers by relying on
+// `T::Data::raw_get_work` and `container_of`. In particular, `T::Data` is
+// stored inline in `drm::Device`, so the `container_of` call is valid.
+//
+// - The two methods are true inverses of each other: given `ptr: *mut
+// Device<T>`, `raw_get_work` will return a `*mut Work<Device<T>, ID>` through
+// `T::Data::raw_get_work` and given a `ptr: *mut Work<Device<T>, ID>`,
+// `work_container_of` will return a `*mut Device<T>` through `container_of`.
+unsafe impl<T, const ID: u64> HasWork<Device<T>, ID> for Device<T>
+where
+    T: drm::Driver,
+    T::Data: HasWork<Device<T>, ID>,
+{
+    unsafe fn raw_get_work(ptr: *mut Self) -> *mut Work<Device<T>, ID> {
+        // SAFETY: The caller promises that `ptr` points to a valid `Device<T>`.
+        let data_ptr = unsafe { &raw mut (*ptr).data };
+
+        // SAFETY: `data_ptr` is a valid pointer to `T::Data`.
+        unsafe { T::Data::raw_get_work(data_ptr) }
+    }
+
+    unsafe fn work_container_of(ptr: *mut Work<Device<T>, ID>) -> *mut Self {
+        // SAFETY: The caller promises that `ptr` points at a `Work` field in
+        // `T::Data`.
+        let data_ptr = unsafe { T::Data::work_container_of(ptr) };
+
+        // SAFETY: `T::Data` is stored as the `data` field in `Device<T>`.
+        unsafe { crate::container_of!(data_ptr, Self, data) }
+    }
+}

-- 
2.52.0


^ permalink raw reply related	[flat|nested] 10+ messages in thread

* [PATCH 3/4] rust: workqueue: add delayed work support for ARef<T>
  2026-01-16  0:35 [PATCH 0/4] rust: Add ARef support for work items Daniel Almeida
  2026-01-16  0:35 ` [PATCH 1/4] rust: workqueue: add support for ARef<T> Daniel Almeida
  2026-01-16  0:35 ` [PATCH 2/4] rust: drm: dispatch work items to the private data Daniel Almeida
@ 2026-01-16  0:35 ` Daniel Almeida
  2026-01-16  0:36 ` [PATCH 4/4] rust: drm: dispatch delayed work items to the private data Daniel Almeida
  2026-01-20 10:37 ` [PATCH 0/4] rust: Add ARef support for work items Alice Ryhl
  4 siblings, 0 replies; 10+ messages in thread
From: Daniel Almeida @ 2026-01-16  0:35 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
  Cc: rust-for-linux, linux-kernel, dri-devel, Daniel Almeida

The preceding patches added support for ARef<T> work items. By the same
token, add support for delayed work items too.

The rationale is the same: it may be convenient or even necessary at times
to implement HasDelayedWork directly on ARef<T>. A follow up patch will
also implement support for drm::Device as the first user.

Signed-off-by: Daniel Almeida <daniel.almeida@collabora.com>
---
 rust/kernel/workqueue.rs | 11 +++++++++++
 1 file changed, 11 insertions(+)

diff --git a/rust/kernel/workqueue.rs b/rust/kernel/workqueue.rs
index 6ae7f3fb3496..4ee4ff567197 100644
--- a/rust/kernel/workqueue.rs
+++ b/rust/kernel/workqueue.rs
@@ -1007,6 +1007,17 @@ unsafe fn __enqueue<F>(self, queue_work_on: F) -> Self::EnqueueOutput
     }
 }
 
+// SAFETY: By the safety requirements of `HasDelayedWork`, the `work_struct` returned by methods in
+// `HasWork` provides a `work_struct` that is the `work` field of a `delayed_work`, and the rest of
+// the `delayed_work` has the same access rules as its `work` field.
+unsafe impl<T, const ID: u64> RawDelayedWorkItem<ID> for ARef<T>
+where
+    T: WorkItem<ID, Pointer = Self>,
+    T: HasDelayedWork<T, ID>,
+    T: AlwaysRefCounted,
+{
+}
+
 /// Returns the system work queue (`system_wq`).
 ///
 /// It is the one used by `schedule[_delayed]_work[_on]()`. Multi-CPU multi-threaded. There are

-- 
2.52.0


^ permalink raw reply related	[flat|nested] 10+ messages in thread

* [PATCH 4/4] rust: drm: dispatch delayed work items to the private data
  2026-01-16  0:35 [PATCH 0/4] rust: Add ARef support for work items Daniel Almeida
                   ` (2 preceding siblings ...)
  2026-01-16  0:35 ` [PATCH 3/4] rust: workqueue: add delayed work support for ARef<T> Daniel Almeida
@ 2026-01-16  0:36 ` Daniel Almeida
  2026-01-20 11:14   ` Danilo Krummrich
  2026-01-20 10:37 ` [PATCH 0/4] rust: Add ARef support for work items Alice Ryhl
  4 siblings, 1 reply; 10+ messages in thread
From: Daniel Almeida @ 2026-01-16  0:36 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
  Cc: rust-for-linux, linux-kernel, dri-devel, Daniel Almeida

Much like the patch that dispatched (regular) work items, we also need to
dispatch delayed work items in order not to trigger the orphan rule. This
allows a drm::Device<T> to dispatch the delayed work to T::Data.

Signed-off-by: Daniel Almeida <daniel.almeida@collabora.com>
---
 rust/kernel/drm/device.rs | 14 +++++++++++++-
 1 file changed, 13 insertions(+), 1 deletion(-)

diff --git a/rust/kernel/drm/device.rs b/rust/kernel/drm/device.rs
index c760a743e1df..ad0447e8763f 100644
--- a/rust/kernel/drm/device.rs
+++ b/rust/kernel/drm/device.rs
@@ -12,7 +12,7 @@
     prelude::*,
     sync::aref::{ARef, AlwaysRefCounted},
     types::Opaque,
-    workqueue::{HasWork, Work, WorkItem},
+    workqueue::{HasDelayedWork, HasWork, Work, WorkItem},
 };
 use core::{alloc::Layout, mem, ops::Deref, ptr, ptr::NonNull};
 
@@ -273,3 +273,15 @@ unsafe fn work_container_of(ptr: *mut Work<Device<T>, ID>) -> *mut Self {
         unsafe { crate::container_of!(data_ptr, Self, data) }
     }
 }
+
+// SAFETY: Our `HasWork<T, ID>` implementation returns a `work_struct` that is
+// stored in the `work` field of a `delayed_work` with the same access rules as
+// the `work_struct` owing to the bound on `T::Data: HasDelayedWork<Device<T>,
+// ID>`, which requires that `T::Data::raw_get_work` return a `work_struct` that
+// is inside a `delayed_work`.
+unsafe impl<T, const ID: u64> HasDelayedWork<Device<T>, ID> for Device<T>
+where
+    T: drm::Driver,
+    T::Data: HasDelayedWork<Device<T>, ID>,
+{
+}

-- 
2.52.0


^ permalink raw reply related	[flat|nested] 10+ messages in thread

* Re: [PATCH 0/4] rust: Add ARef support for work items
  2026-01-16  0:35 [PATCH 0/4] rust: Add ARef support for work items Daniel Almeida
                   ` (3 preceding siblings ...)
  2026-01-16  0:36 ` [PATCH 4/4] rust: drm: dispatch delayed work items to the private data Daniel Almeida
@ 2026-01-20 10:37 ` Alice Ryhl
  2026-01-20 14:41   ` Daniel Almeida
  4 siblings, 1 reply; 10+ messages in thread
From: Alice Ryhl @ 2026-01-20 10:37 UTC (permalink / raw)
  To: Daniel Almeida
  Cc: Miguel Ojeda, Boqun Feng, Gary Guo, Björn Roy Baron,
	Benno Lossin, Andreas Hindborg, Trevor Gross, Danilo Krummrich,
	David Airlie, Simona Vetter, rust-for-linux, linux-kernel,
	dri-devel

On Thu, Jan 15, 2026 at 09:35:56PM -0300, Daniel Almeida wrote:
> This series adds ARef<T> support for both regular and delayed work items. 
> 
> - Patches 1 and 3 actually implement the support in workqueue.rs
> - Patches 2 and 4 adds a corresponding implementation in drm::Device that
>   dispatches the calls to the underlying T::Data.
> 
> This was tested on Tyr, and is actually needed in order to obtain a
> &drm::Device when handling work items. This is then needed in order to
> allocate GEM objects inside the work handler that processes the tiler OOM
> (out of memory) events. The current series sets the stage so that the above
> is possible in the future.
> 
> This is currently based on v6.19-rc5. I hope we can land all four commits
> on a single tree, but otherwise let me know whether I should split the
> workqueue.rs changes from the drm::Device ones and rebase accordingly.

Please send a new version that CCs workqueue maintainers.

Reviewed-by: Alice Ryhl <aliceryhl@google.com>


^ permalink raw reply	[flat|nested] 10+ messages in thread

* Re: [PATCH 2/4] rust: drm: dispatch work items to the private data
  2026-01-16  0:35 ` [PATCH 2/4] rust: drm: dispatch work items to the private data Daniel Almeida
@ 2026-01-20 11:13   ` Danilo Krummrich
  0 siblings, 0 replies; 10+ messages in thread
From: Danilo Krummrich @ 2026-01-20 11:13 UTC (permalink / raw)
  To: Daniel Almeida
  Cc: Miguel Ojeda, Boqun Feng, Gary Guo, Björn Roy Baron,
	Benno Lossin, Andreas Hindborg, Alice Ryhl, Trevor Gross,
	David Airlie, Simona Vetter, rust-for-linux, linux-kernel,
	dri-devel

On Fri Jan 16, 2026 at 1:35 AM CET, Daniel Almeida wrote:
> diff --git a/rust/kernel/drm/device.rs b/rust/kernel/drm/device.rs
> index 3ce8f62a0056..c760a743e1df 100644
> --- a/rust/kernel/drm/device.rs
> +++ b/rust/kernel/drm/device.rs
> @@ -6,13 +6,13 @@
>  
>  use crate::{
>      alloc::allocator::Kmalloc,
> -    bindings, device, drm,
> -    drm::driver::AllocImpl,
> -    error::from_err_ptr,
> -    error::Result,
> +    bindings, device,
> +    drm::{self, driver::AllocImpl},
> +    error::{from_err_ptr, Result},
>      prelude::*,
>      sync::aref::{ARef, AlwaysRefCounted},
>      types::Opaque,
> +    workqueue::{HasWork, Work, WorkItem},
>  };

Please use the kernel's import style when making changes.

^ permalink raw reply	[flat|nested] 10+ messages in thread

* Re: [PATCH 4/4] rust: drm: dispatch delayed work items to the private data
  2026-01-16  0:36 ` [PATCH 4/4] rust: drm: dispatch delayed work items to the private data Daniel Almeida
@ 2026-01-20 11:14   ` Danilo Krummrich
  2026-01-20 14:32     ` Daniel Almeida
  0 siblings, 1 reply; 10+ messages in thread
From: Danilo Krummrich @ 2026-01-20 11:14 UTC (permalink / raw)
  To: Daniel Almeida
  Cc: Miguel Ojeda, Boqun Feng, Gary Guo, Björn Roy Baron,
	Benno Lossin, Andreas Hindborg, Alice Ryhl, Trevor Gross,
	David Airlie, Simona Vetter, rust-for-linux, linux-kernel,
	dri-devel

On Fri Jan 16, 2026 at 1:36 AM CET, Daniel Almeida wrote:
> +// SAFETY: Our `HasWork<T, ID>` implementation returns a `work_struct` that is
> +// stored in the `work` field of a `delayed_work` with the same access rules as
> +// the `work_struct` owing to the bound on `T::Data: HasDelayedWork<Device<T>,
> +// ID>`, which requires that `T::Data::raw_get_work` return a `work_struct` that
> +// is inside a `delayed_work`.
> +unsafe impl<T, const ID: u64> HasDelayedWork<Device<T>, ID> for Device<T>
> +where
> +    T: drm::Driver,
> +    T::Data: HasDelayedWork<Device<T>, ID>,
> +{
> +}

What do you intend to do within work that is queued for a DRM device? I assume
you have to access bus device resources?

Also, it would be nice to see how this is used in a driver. Can you please add a
patch for Tyr to the series?

^ permalink raw reply	[flat|nested] 10+ messages in thread

* Re: [PATCH 4/4] rust: drm: dispatch delayed work items to the private data
  2026-01-20 11:14   ` Danilo Krummrich
@ 2026-01-20 14:32     ` Daniel Almeida
  0 siblings, 0 replies; 10+ messages in thread
From: Daniel Almeida @ 2026-01-20 14:32 UTC (permalink / raw)
  To: Danilo Krummrich
  Cc: Miguel Ojeda, Boqun Feng, Gary Guo, Björn Roy Baron,
	Benno Lossin, Andreas Hindborg, Alice Ryhl, Trevor Gross,
	David Airlie, Simona Vetter, rust-for-linux, linux-kernel,
	dri-devel

Hi Danilo,

> On 20 Jan 2026, at 08:14, Danilo Krummrich <dakr@kernel.org> wrote:
> 
> On Fri Jan 16, 2026 at 1:36 AM CET, Daniel Almeida wrote:
>> +// SAFETY: Our `HasWork<T, ID>` implementation returns a `work_struct` that is
>> +// stored in the `work` field of a `delayed_work` with the same access rules as
>> +// the `work_struct` owing to the bound on `T::Data: HasDelayedWork<Device<T>,
>> +// ID>`, which requires that `T::Data::raw_get_work` return a `work_struct` that
>> +// is inside a `delayed_work`.
>> +unsafe impl<T, const ID: u64> HasDelayedWork<Device<T>, ID> for Device<T>
>> +where
>> +    T: drm::Driver,
>> +    T::Data: HasDelayedWork<Device<T>, ID>,
>> +{
>> +}
> 
> What do you intend to do within work that is queued for a DRM device? I assume
> you have to access bus device resources?
> 
> Also, it would be nice to see how this is used in a driver. Can you please add a
> patch for Tyr to the series?

Yes, we need resources from the bus device, as need to access the underlying
mmio range for register reads and writes. We also need to allocate GEM objects
in that path, which requires the drm class device.


I've just pushed a demo with some WIP at [0] for illustration purposes. Apart
from the other cruft in that code, the main point is:

- impl WorkItem<2> for TyrData {
-    type Pointer = Arc<Self>;
+ impl WorkItem<2> for crate::driver::TyrInlineData {
+    type Pointer = ARef<TyrDevice>;

1) The data is now defined inline with the drm::Device. This is used by the
work_container_of implementation in commit #2 in this series.

2) This inline data now has the work and an Arc<TyrData> to keep the shared
ownership semantics of TyrData, i.e.:

/// Inline data stored directly in the DRM device.
/// Contains work items that need access to the device itself.
#[pin_data]
pub(crate) struct TyrInlineData {
    /// The work to process firmware events (tiler OOM, etc.)
    #[pin]
    pub(crate) fw_events_work: Work<TyrDevice, 2>,

    /// The scheduler tick work
    #[pin]
    pub(crate) tick_work: Work<TyrDevice, 1>,

    /// The actual driver data
    pub(crate) data: Arc<TyrData>,
}

3) When processing a TILER_OOM event, we now have access to ARef<TyrDevice>
which lets us allocate more memory to the tiler inside the handler routine.

This applies for regular work items, but there is a use-case for delayed work
items as well. As we spoke during Kangrejos, Tyr and Panthor have this internal
job scheduler that bridges the gap between the outstanding jobs and the limited
amount of ring buffers exposed by the firmware. This runs periodically, which
is a major use case for delayed work items in Tyr.

This is not implemented in the prototype at the moment, because it's not needed
for a demo. We simply reject jobs with -EBUSY if all the firmware slots are
full. Sadly, there is not enough upstream at the moment to provide a patch that is
actually useful for Tyr itself in this series, but I am sure we will eventually
need it. This statement applies to both regular and delayed work items.

I assume you're worried about the device being unbound in the meantime? These types
of discussions are precisely why I am submitting this a bit in advance :)

By the way, I’d say in any case we should merge patch #1 once there’s no more comments,
as implementing ARef support seems to be orthogonal to the issue I raised above, unless
you’re worried about something else?

[0]: https://gitlab.collabora.com/dwlsalmeida/for-upstream/-/commit/4ac5ec7d8b13d4d4fc5280b414b02ba5ab8e8f23

^ permalink raw reply	[flat|nested] 10+ messages in thread

* Re: [PATCH 0/4] rust: Add ARef support for work items
  2026-01-20 10:37 ` [PATCH 0/4] rust: Add ARef support for work items Alice Ryhl
@ 2026-01-20 14:41   ` Daniel Almeida
  0 siblings, 0 replies; 10+ messages in thread
From: Daniel Almeida @ 2026-01-20 14:41 UTC (permalink / raw)
  To: Alice Ryhl
  Cc: Miguel Ojeda, Boqun Feng, Gary Guo, Björn Roy Baron,
	Benno Lossin, Andreas Hindborg, Trevor Gross, Danilo Krummrich,
	David Airlie, Simona Vetter, rust-for-linux, linux-kernel,
	dri-devel



> On 20 Jan 2026, at 07:37, Alice Ryhl <aliceryhl@google.com> wrote:
> 
> On Thu, Jan 15, 2026 at 09:35:56PM -0300, Daniel Almeida wrote:
>> This series adds ARef<T> support for both regular and delayed work items. 
>> 
>> - Patches 1 and 3 actually implement the support in workqueue.rs
>> - Patches 2 and 4 adds a corresponding implementation in drm::Device that
>>  dispatches the calls to the underlying T::Data.
>> 
>> This was tested on Tyr, and is actually needed in order to obtain a
>> &drm::Device when handling work items. This is then needed in order to
>> allocate GEM objects inside the work handler that processes the tiler OOM
>> (out of memory) events. The current series sets the stage so that the above
>> is possible in the future.
>> 
>> This is currently based on v6.19-rc5. I hope we can land all four commits
>> on a single tree, but otherwise let me know whether I should split the
>> workqueue.rs changes from the drm::Device ones and rebase accordingly.
> 
> Please send a new version that CCs workqueue maintainers.
> 
> Reviewed-by: Alice Ryhl <aliceryhl@google.com>

That was the usual “b4 prep —auto-to-cc”, perhaps we need to fix something
in MAINTAINERS?

— Daniel

^ permalink raw reply	[flat|nested] 10+ messages in thread

end of thread, other threads:[~2026-01-20 14:42 UTC | newest]

Thread overview: 10+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2026-01-16  0:35 [PATCH 0/4] rust: Add ARef support for work items Daniel Almeida
2026-01-16  0:35 ` [PATCH 1/4] rust: workqueue: add support for ARef<T> Daniel Almeida
2026-01-16  0:35 ` [PATCH 2/4] rust: drm: dispatch work items to the private data Daniel Almeida
2026-01-20 11:13   ` Danilo Krummrich
2026-01-16  0:35 ` [PATCH 3/4] rust: workqueue: add delayed work support for ARef<T> Daniel Almeida
2026-01-16  0:36 ` [PATCH 4/4] rust: drm: dispatch delayed work items to the private data Daniel Almeida
2026-01-20 11:14   ` Danilo Krummrich
2026-01-20 14:32     ` Daniel Almeida
2026-01-20 10:37 ` [PATCH 0/4] rust: Add ARef support for work items Alice Ryhl
2026-01-20 14:41   ` Daniel Almeida

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox