All of lore.kernel.org
 help / color / mirror / Atom feed
From: Philipp Stanner <phasta@kernel.org>
To: "David Airlie" <airlied@gmail.com>,
	"Simona Vetter" <simona@ffwll.ch>,
	"Danilo Krummrich" <dakr@kernel.org>,
	"Alice Ryhl" <aliceryhl@google.com>,
	"Gary Guo" <gary@garyguo.net>, "Benno Lossin" <lossin@kernel.org>,
	"Christian König" <christian.koenig@amd.com>,
	"Boris Brezillon" <boris.brezillon@collabora.com>,
	"Daniel Almeida" <daniel.almeida@collabora.com>,
	"Joel Fernandes" <joelagnelf@nvidia.com>
Cc: linux-kernel@vger.kernel.org, dri-devel@lists.freedesktop.org,
	rust-for-linux@vger.kernel.org,
	Philipp Stanner <phasta@kernel.org>
Subject: [RFC PATCH 4/4] samples: rust: Add jobqueue tester
Date: Tue,  3 Feb 2026 09:14:03 +0100	[thread overview]
Message-ID: <20260203081403.68733-6-phasta@kernel.org> (raw)
In-Reply-To: <20260203081403.68733-2-phasta@kernel.org>

The DRM Jobqueue is a new piece of (highly asynchronous) infrastructure
for submitting jobs to graphics processing units (GPUs).

It is difficult to test such a mechanism purely with unit tests. Thus,
provide this driver solely for testing drm::Jobqueue.

Signed-off-by: Philipp Stanner <phasta@kernel.org>
---
 samples/rust/Kconfig                 |  11 ++
 samples/rust/Makefile                |   1 +
 samples/rust/rust_jobqueue_tester.rs | 180 +++++++++++++++++++++++++++
 3 files changed, 192 insertions(+)
 create mode 100644 samples/rust/rust_jobqueue_tester.rs

diff --git a/samples/rust/Kconfig b/samples/rust/Kconfig
index c376eb899b7a..a9a3a671bb0b 100644
--- a/samples/rust/Kconfig
+++ b/samples/rust/Kconfig
@@ -145,4 +145,15 @@ config SAMPLE_RUST_HOSTPROGS
 
 	  If unsure, say N.
 
+config SAMPLE_RUST_JOBQUEUE_TESTER
+	tristate "Jobqueue Tester"
+	select JOBQUEUE_TESTER
+	help
+	  This option builds the Rust Jobqueue Tester.
+
+	  To compile this as a module, choose M here:
+	  the module will be called rust_jobqueue_tester.
+
+	  If unsure, say N.
+
 endif # SAMPLES_RUST
diff --git a/samples/rust/Makefile b/samples/rust/Makefile
index cf8422f8f219..9cc1f021dc39 100644
--- a/samples/rust/Makefile
+++ b/samples/rust/Makefile
@@ -13,6 +13,7 @@ obj-$(CONFIG_SAMPLE_RUST_DRIVER_USB)		+= rust_driver_usb.o
 obj-$(CONFIG_SAMPLE_RUST_DRIVER_FAUX)		+= rust_driver_faux.o
 obj-$(CONFIG_SAMPLE_RUST_DRIVER_AUXILIARY)	+= rust_driver_auxiliary.o
 obj-$(CONFIG_SAMPLE_RUST_CONFIGFS)		+= rust_configfs.o
+obj-$(CONFIG_SAMPLE_RUST_JOBQUEUE_TESTER)	+= rust_jobqueue_tester.o
 
 rust_print-y := rust_print_main.o rust_print_events.o
 
diff --git a/samples/rust/rust_jobqueue_tester.rs b/samples/rust/rust_jobqueue_tester.rs
new file mode 100644
index 000000000000..c2590a1b4f8a
--- /dev/null
+++ b/samples/rust/rust_jobqueue_tester.rs
@@ -0,0 +1,180 @@
+// SPDX-License-Identifier: GPL-2.0
+
+//! Small example demonstrating how to use [`drm::Jobqueue`].
+
+use kernel::prelude::*;
+use kernel::sync::{DmaFenceCtx, DmaFence, Arc};
+use kernel::drm::jq::{Job, Jobqueue};
+use kernel::types::{ARef};
+use kernel::time::{delay::fsleep, Delta};
+use kernel::workqueue::{self, impl_has_work, new_work, Work, WorkItem};
+
+module! {
+    type: RustJobqueueTester,
+    name: "rust_jobqueue_tester",
+    authors: ["Philipp Stanner"],
+    description: "Rust minimal sample",
+    license: "GPL",
+}
+
+#[pin_data]
+struct GPUWorker {
+    hw_fence: ARef<DmaFence<i32>>,
+    #[pin]
+    work: Work<GPUWorker>,
+}
+
+impl GPUWorker {
+    fn new(
+        hw_fence: ARef<DmaFence<i32>>,
+    ) -> Result<Arc<Self>> {
+        Arc::pin_init(
+            pin_init!(Self {hw_fence, work <- new_work!("Jobqueue::GPUWorker")}),
+            GFP_KERNEL,
+        )
+    }
+}
+
+impl_has_work! {
+    impl HasWork<Self> for GPUWorker { self.work }
+}
+
+impl WorkItem for GPUWorker {
+    type Pointer = Arc<GPUWorker>;
+
+    fn run(this: Arc<GPUWorker>) {
+        fsleep(Delta::from_secs(1));
+        this.hw_fence.signal().unwrap();
+    }
+}
+
+fn run_job(job: &Pin<&mut Job<Arc<DmaFenceCtx>>>) -> ARef<DmaFence<i32>> {
+    let fence = job.data.as_arc_borrow().new_fence(42 as i32).unwrap();
+
+    let gpu_worker = GPUWorker::new(fence.clone()).unwrap();
+    let _ = workqueue::system().enqueue(gpu_worker);
+
+    fence
+}
+
+struct RustJobqueueTester { }
+
+impl kernel::Module for RustJobqueueTester {
+    fn init(_module: &'static ThisModule) -> Result<Self> {
+        pr_info!("Rust Jobqueue Tester (init)\n");
+        pr_info!("Am I built-in? {}\n", !cfg!(MODULE));
+
+        let dep_fctx = DmaFenceCtx::new()?;
+        let hw_fctx = DmaFenceCtx::new()?;
+        let jq = Jobqueue::new(1_000_000, run_job)?;
+
+
+        pr_info!("Test 1: Test submitting two jobs without dependencies.\n");
+        let job1 = Job::new(1, hw_fctx.clone())?;
+        let job2 = Job::new(1, hw_fctx.clone())?;
+
+        let fence1 = jq.submit_job(job1)?;
+        let fence2 = jq.submit_job(job2)?;
+
+        while !fence1.is_signaled() || !fence2.is_signaled() {
+            fsleep(Delta::from_secs(2));
+        }
+        pr_info!("Test 1 succeeded.\n");
+
+
+        pr_info!("Test 2: Test submitting a job with already-fullfilled dependency.\n");
+        let mut job3 = Job::new(1, hw_fctx.clone())?;
+        job3.add_dependency(fence1)?;
+
+        let fence3 = jq.submit_job(job3)?;
+        fsleep(Delta::from_secs(2));
+        if !fence3.is_signaled() {
+            pr_info!("Test 2 failed.\n");
+            return Err(EAGAIN);
+        }
+        pr_info!("Test 2 succeeded.\n");
+
+
+        pr_info!("Test 3: Test that a job with unfullfilled dependency gets never run.\n");
+        let unsignaled_fence = dep_fctx.as_arc_borrow().new_fence(9001 as i32)?;
+
+        let mut job4 = Job::new(1, hw_fctx.clone())?;
+        job4.add_dependency(unsignaled_fence.clone())?;
+
+        let blocked_job_fence = jq.submit_job(job4)?;
+        fsleep(Delta::from_secs(2));
+        if blocked_job_fence.is_signaled() {
+            pr_info!("Test 3 failed.\n");
+            return Err(EAGAIN);
+        }
+        pr_info!("Test 3 succeeded.\n");
+
+
+        pr_info!("Test 4: Test whether Test 3's blocked job can be unblocked.\n");
+        unsignaled_fence.signal()?;
+        while !blocked_job_fence.is_signaled() {
+            fsleep(Delta::from_secs(2));
+        }
+        pr_info!("Test 4 succeeded.\n");
+
+
+        pr_info!("Test 5: Submit a bunch of unblocked jobs, then a blocked one, then an unblocked one.\n");
+        let job1 = Job::new(1, hw_fctx.clone())?;
+        let job2 = Job::new(1, hw_fctx.clone())?;
+        let mut job3 = Job::new(1, hw_fctx.clone())?;
+        let job4 = Job::new(1, hw_fctx.clone())?;
+        let job5 = Job::new(1, hw_fctx.clone())?;
+
+        let unsignaled_fence1 = dep_fctx.as_arc_borrow().new_fence(9001 as i32)?;
+        let unsignaled_fence2 = dep_fctx.as_arc_borrow().new_fence(9001 as i32)?;
+        let unsignaled_fence3 = dep_fctx.as_arc_borrow().new_fence(9001 as i32)?;
+        job3.add_dependency(unsignaled_fence1.clone())?;
+        job3.add_dependency(unsignaled_fence2.clone())?;
+        job3.add_dependency(unsignaled_fence3.clone())?;
+
+        let fence1 = jq.submit_job(job1)?;
+        let fence2 = jq.submit_job(job2)?;
+        let fence3 = jq.submit_job(job3)?;
+
+        fsleep(Delta::from_secs(2));
+        if fence3.is_signaled() || !fence1.is_signaled() || !fence2.is_signaled() {
+            pr_info!("Test 5 failed.\n");
+            return Err(EAGAIN);
+        }
+
+        unsignaled_fence1.signal()?;
+        unsignaled_fence3.signal()?;
+        fsleep(Delta::from_secs(2));
+        if fence3.is_signaled() {
+            pr_info!("Test 5 failed.\n");
+            return Err(EAGAIN);
+        }
+
+        unsignaled_fence2.signal()?;
+        fsleep(Delta::from_secs(2));
+        if !fence3.is_signaled() {
+            pr_info!("Test 5 failed.\n");
+            return Err(EAGAIN);
+        }
+
+        let fence4 = jq.submit_job(job4)?;
+        let fence5 = jq.submit_job(job5)?;
+
+        fsleep(Delta::from_secs(2));
+
+        if !fence4.is_signaled() || !fence5.is_signaled() {
+            pr_info!("Test 5 failed.\n");
+            return Err(EAGAIN);
+        }
+        pr_info!("Test 5 succeeded.\n");
+
+
+        Ok(RustJobqueueTester { })
+    }
+}
+
+impl Drop for RustJobqueueTester {
+    fn drop(&mut self) {
+        pr_info!("Rust Jobqueue Tester (exit)\n");
+    }
+}
-- 
2.49.0


  parent reply	other threads:[~2026-02-03  8:14 UTC|newest]

Thread overview: 105+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2026-02-03  8:13 [RFC PATCH 0/4] Add dma_fence abstractions and DRM Jobqueue Philipp Stanner
2026-02-03  8:14 ` [RFC PATCH 1/4] rust: list: Add unsafe for container_of Philipp Stanner
2026-02-03 15:25   ` Gary Guo
2026-02-04 10:30   ` Alice Ryhl
2026-02-03  8:14 ` [RFC PATCH 2/4] rust: sync: Add dma_fence abstractions Philipp Stanner
2026-02-05  8:57   ` Boris Brezillon
2026-02-06 10:23     ` Danilo Krummrich
2026-02-09  8:19       ` Philipp Stanner
2026-02-09 14:58         ` Boris Brezillon
2026-02-10  8:16           ` Christian König
2026-02-10  8:38             ` Alice Ryhl
2026-02-10  9:06               ` Philipp Stanner
2026-02-10  9:54                 ` Christian König
2026-02-10  9:15               ` Boris Brezillon
2026-02-10 10:15                 ` Alice Ryhl
2026-02-10 10:36                   ` Danilo Krummrich
2026-02-10 10:46                     ` Christian König
2026-02-10 11:40                       ` Alice Ryhl
2026-02-10 12:28                         ` Boris Brezillon
2026-02-11  9:57                         ` Danilo Krummrich
2026-02-11 10:08                           ` Philipp Stanner
2026-02-11 10:28                             ` Boris Brezillon
2026-02-11 10:20                           ` Boris Brezillon
2026-02-11 11:00                             ` Danilo Krummrich
2026-02-11 11:12                               ` Boris Brezillon
2026-02-11 14:38                                 ` Danilo Krummrich
2026-02-11 15:00                                   ` Boris Brezillon
2026-02-11 15:05                                     ` Danilo Krummrich
2026-02-11 15:14                                       ` Boris Brezillon
2026-02-11 15:16                                         ` Danilo Krummrich
2026-03-13 17:27                                     ` Matthew Brost
2026-02-10 10:46                   ` Boris Brezillon
2026-02-10 11:34                   ` Boris Brezillon
2026-02-10 11:45                     ` Alice Ryhl
2026-02-10 12:21                       ` Boris Brezillon
2026-02-10 13:34                         ` Alice Ryhl
2026-02-10 12:36                   ` Boris Brezillon
2026-02-10 13:15                     ` Alice Ryhl
2026-02-10 13:26                       ` Boris Brezillon
2026-02-10 13:49                         ` Alice Ryhl
2026-02-10 13:56                           ` Christian König
2026-02-10 14:00                             ` Philipp Stanner
2026-02-10 14:06                               ` Christian König
2026-02-10 15:32                                 ` Philipp Stanner
2026-02-10 15:50                                   ` Christian König
2026-02-10 15:07                             ` Alice Ryhl
2026-02-10 15:45                               ` Christian König
2026-02-11  8:16                                 ` Philipp Stanner
2026-02-17 14:03                                 ` Philipp Stanner
2026-02-17 14:09                                   ` Alice Ryhl
2026-02-17 14:22                                     ` Christian König
2026-02-17 14:28                                       ` Philipp Stanner
2026-02-17 14:44                                         ` Danilo Krummrich
2026-03-13 23:20                                           ` Matthew Brost
2026-02-17 15:01                                         ` Christian König
2026-02-18  9:50                                         ` Alice Ryhl
2026-02-18 10:48                                           ` Boris Brezillon
2026-02-10 12:49                   ` Boris Brezillon
2026-02-10 12:56                     ` Boris Brezillon
2026-02-10 13:26                     ` Alice Ryhl
2026-02-10 13:51                       ` Boris Brezillon
2026-02-10 14:11                         ` Alice Ryhl
2026-02-10 14:50                           ` Boris Brezillon
2026-02-11  8:16                             ` Alice Ryhl
2026-02-11  9:20                               ` Boris Brezillon
2026-02-10  9:26               ` Christian König
2026-02-05 10:16   ` Boris Brezillon
2026-02-05 13:16     ` Gary Guo
2026-02-06  9:32       ` Philipp Stanner
2026-02-06 10:16         ` Danilo Krummrich
2026-02-06 13:24           ` Philipp Stanner
2026-02-06 11:04         ` Boris Brezillon
2026-02-09  8:21           ` Philipp Stanner
2026-02-06 11:23         ` Boris Brezillon
2026-02-05 12:35   ` kernel test robot
2026-02-09 11:30   ` Alice Ryhl
2026-02-03  8:14 ` [RFC PATCH 3/4] rust/drm: Add DRM Jobqueue Philipp Stanner
2026-02-05 13:58   ` kernel test robot
2026-02-10 14:57   ` Boris Brezillon
2026-02-11 10:47     ` Philipp Stanner
2026-02-11 11:07       ` Boris Brezillon
2026-02-11 11:19         ` Danilo Krummrich
2026-02-11 12:10           ` Boris Brezillon
2026-02-11 12:32             ` Danilo Krummrich
2026-02-11 12:51               ` Boris Brezillon
2026-02-11 11:19         ` Philipp Stanner
2026-02-11 11:59           ` Boris Brezillon
2026-02-11 12:14             ` Philipp Stanner
2026-02-11 12:24               ` Boris Brezillon
2026-02-11 12:22           ` Alice Ryhl
2026-02-11 12:44             ` Philipp Stanner
2026-02-11 12:52               ` Alice Ryhl
2026-02-11 13:53                 ` Philipp Stanner
2026-02-11 15:28                   ` Alice Ryhl
2026-02-11 12:45             ` Danilo Krummrich
2026-02-11 13:45             ` Gary Guo
2026-02-11 14:07               ` Boris Brezillon
2026-02-11 15:17                 ` Alice Ryhl
2026-02-11 15:20                   ` Philipp Stanner
2026-02-11 15:51                     ` Boris Brezillon
2026-02-11 15:53                     ` Alice Ryhl
2026-02-11 15:54                     ` Danilo Krummrich
2026-02-11 15:33               ` Alice Ryhl
2026-02-03  8:14 ` Philipp Stanner [this message]
2026-02-03 16:46 ` [RFC PATCH 0/4] Add dma_fence abstractions and " Daniel Almeida

Reply instructions:

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

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

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

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

  git send-email \
    --in-reply-to=20260203081403.68733-6-phasta@kernel.org \
    --to=phasta@kernel.org \
    --cc=airlied@gmail.com \
    --cc=aliceryhl@google.com \
    --cc=boris.brezillon@collabora.com \
    --cc=christian.koenig@amd.com \
    --cc=dakr@kernel.org \
    --cc=daniel.almeida@collabora.com \
    --cc=dri-devel@lists.freedesktop.org \
    --cc=gary@garyguo.net \
    --cc=joelagnelf@nvidia.com \
    --cc=linux-kernel@vger.kernel.org \
    --cc=lossin@kernel.org \
    --cc=rust-for-linux@vger.kernel.org \
    --cc=simona@ffwll.ch \
    /path/to/YOUR_REPLY

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

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