mirror of https://lore.kernel.org/lkml/
 help / color / mirror / Atom feed
* [PATCH v4] accel/rocket: Report NPU usage through fdinfo
@ 2026-11-03 15:53 Sidong Yang
  2026-11-05  3:22 ` Gyeyoung Baek
  2026-11-05  9:22 ` Tvrtko Ursulin
  0 siblings, 2 replies; 7+ messages in thread
From: Sidong Yang @ 2026-11-03 15:53 UTC (permalink / raw)
  To: Tomeu Vizoso, Oded Gabbay
  Cc: Gyeyoung Baek, dri-devel, linux-doc, linux-kernel, Sidong Yang

There is no way to tell how much of the NPU a client uses. Implement the
DRM usage stats: account the time each job occupies a core and report
it per client as drm-engine-npu, along with drm_show_memory_stats() for
the BOs.

The cores are identical, so they are reported as a single engine with
drm-engine-capacity-npu set to rdev->max_cores, the number of core
slots. The time is summed over all cores, with an atomic counter as the
cores complete jobs concurrently.

Jobs can outlive the file that submitted them, so the counter is
refcounted and each job holds a reference. The time covers the whole
period a job owns a core, so it also includes handling the completion
interrupt and the gaps between the tasks of a multi-task job.

Document the keys in the rocket driver documentation.

Signed-off-by: Sidong Yang <sidong.yang@furiosa.ai>
---
v4: Report a single drm-engine-npu key with drm-engine-capacity-npu,
    instead of drm-engine-npu0..2, as drm-usage-stats.rst specifies for
    a group of identical engines, and document the keys (Tomeu Vizoso).
    The subject no longer says per-core. Gyeyoung's tags are dropped as
    the accounting changed.

    Still depends on commit 6eff1d69dae8 ("accel/rocket: search every
    core slot when a core is removed") for rdev->max_cores.

v3: Add a rocket_engine_usage_create() helper for the counter
    allocation in rocket_open(), to pair with
    rocket_engine_usage_destroy() (Gyeyoung Baek).

v2: Size the per-core counters by rdev->max_cores, the number of core
    slots, instead of the number of cores bound when the file is opened.
    Sashiko reported the out-of-bounds read and Gyeyoung Baek reproduced
    it with KASAN.

Link to v3: https://lore.kernel.org/all/20261103104804.1887489-1-sidong.yang@furiosa.ai/
Link to v2: https://lore.kernel.org/all/20261101152723.1430312-1-sidong.yang@furiosa.ai/
Link to v1: https://lore.kernel.org/all/20261031083642.1076356-1-sidong.yang@furiosa.ai/

 Documentation/accel/rocket/index.rst  | 28 +++++++++++
 Documentation/gpu/drm-usage-stats.rst |  1 +
 drivers/accel/rocket/rocket_drv.c     | 70 ++++++++++++++++++++++++++-
 drivers/accel/rocket/rocket_drv.h     | 15 ++++++
 drivers/accel/rocket/rocket_job.c     |  7 +++
 drivers/accel/rocket/rocket_job.h     |  4 ++
 6 files changed, 123 insertions(+), 2 deletions(-)

diff --git a/Documentation/accel/rocket/index.rst b/Documentation/accel/rocket/index.rst
index 70f97bccf100..53c9aa7e2229 100644
--- a/Documentation/accel/rocket/index.rst
+++ b/Documentation/accel/rocket/index.rst
@@ -17,3 +17,31 @@ project.
 Hardware currently supported:
 
 * RK3588
+
+.. _rocket-usage-stats:
+
+Rocket DRM client usage stats implementation
+============================================
+
+The accel/rocket driver implements the DRM client usage stats specification as
+documented in :ref:`drm-client-usage-stats`.
+
+The NPU cores are reported as a single engine, npu, with a capacity equal to the
+number of cores. The time is summed over all cores, and covers the whole period
+a job occupies a core.
+
+Example of the output showing the implemented key value pairs:
+
+::
+
+        pos:	0
+        flags:	02400002
+        mnt_id:	33
+        ino:	749
+        drm-driver:	rocket
+        drm-client-id:	246
+        drm-engine-npu:	2296549300 ns
+        drm-engine-capacity-npu:	3
+        drm-total-memory:	24216 KiB
+        drm-shared-memory:	0
+        drm-active-memory:	1920 KiB
diff --git a/Documentation/gpu/drm-usage-stats.rst b/Documentation/gpu/drm-usage-stats.rst
index 70b7cfcc194f..288764730d23 100644
--- a/Documentation/gpu/drm-usage-stats.rst
+++ b/Documentation/gpu/drm-usage-stats.rst
@@ -218,3 +218,4 @@ Driver specific implementations
 * :ref:`panthor-usage-stats`
 * :ref:`xe-usage-stats`
 * :ref:`amdxdna-usage-stats`
+* :ref:`rocket-usage-stats`
diff --git a/drivers/accel/rocket/rocket_drv.c b/drivers/accel/rocket/rocket_drv.c
index 2bcfe4ab3c68..e22e8623db64 100644
--- a/drivers/accel/rocket/rocket_drv.c
+++ b/drivers/accel/rocket/rocket_drv.c
@@ -3,8 +3,10 @@
 
 #include <drm/drm_accel.h>
 #include <drm/drm_drv.h>
+#include <drm/drm_file.h>
 #include <drm/drm_gem.h>
 #include <drm/drm_ioctl.h>
+#include <drm/drm_print.h>
 #include <drm/rocket_accel.h>
 #include <linux/clk.h>
 #include <linux/err.h>
@@ -68,6 +70,38 @@ rocket_iommu_domain_put(struct rocket_iommu_domain *domain)
 	kref_put(&domain->kref, rocket_iommu_domain_destroy);
 }
 
+static struct rocket_engine_usage *
+rocket_engine_usage_create(void)
+{
+	struct rocket_engine_usage *usage;
+
+	usage = kzalloc_obj(*usage);
+	if (!usage)
+		return NULL;
+	kref_init(&usage->kref);
+
+	return usage;
+}
+
+static void
+rocket_engine_usage_destroy(struct kref *kref)
+{
+	kfree(container_of(kref, struct rocket_engine_usage, kref));
+}
+
+struct rocket_engine_usage *
+rocket_engine_usage_get(struct rocket_file_priv *rocket_priv)
+{
+	kref_get(&rocket_priv->engine_usage->kref);
+	return rocket_priv->engine_usage;
+}
+
+void
+rocket_engine_usage_put(struct rocket_engine_usage *usage)
+{
+	kref_put(&usage->kref, rocket_engine_usage_destroy);
+}
+
 static int
 rocket_open(struct drm_device *dev, struct drm_file *file)
 {
@@ -86,10 +120,17 @@ rocket_open(struct drm_device *dev, struct drm_file *file)
 	}
 
 	rocket_priv->rdev = rdev;
+
+	rocket_priv->engine_usage = rocket_engine_usage_create();
+	if (!rocket_priv->engine_usage) {
+		ret = -ENOMEM;
+		goto err_free;
+	}
+
 	rocket_priv->domain = rocket_iommu_domain_create(rdev->cores[0].dev);
 	if (IS_ERR(rocket_priv->domain)) {
 		ret = PTR_ERR(rocket_priv->domain);
-		goto err_free;
+		goto err_put_engine_usage;
 	}
 
 	file->driver_priv = rocket_priv;
@@ -109,6 +150,8 @@ rocket_open(struct drm_device *dev, struct drm_file *file)
 	mutex_destroy(&rocket_priv->mm_lock);
 	drm_mm_takedown(&rocket_priv->mm);
 	rocket_iommu_domain_put(rocket_priv->domain);
+err_put_engine_usage:
+	rocket_engine_usage_put(rocket_priv->engine_usage);
 err_free:
 	kfree(rocket_priv);
 err_put_mod:
@@ -125,6 +168,7 @@ rocket_postclose(struct drm_device *dev, struct drm_file *file)
 	mutex_destroy(&rocket_priv->mm_lock);
 	drm_mm_takedown(&rocket_priv->mm);
 	rocket_iommu_domain_put(rocket_priv->domain);
+	rocket_engine_usage_put(rocket_priv->engine_usage);
 	kfree(rocket_priv);
 	module_put(THIS_MODULE);
 }
@@ -139,7 +183,28 @@ static const struct drm_ioctl_desc rocket_drm_driver_ioctls[] = {
 	ROCKET_IOCTL(FINI_BO, fini_bo),
 };
 
-DEFINE_DRM_ACCEL_FOPS(rocket_accel_driver_fops);
+static void rocket_show_fdinfo(struct drm_printer *p, struct drm_file *file)
+{
+	struct rocket_device *rdev = to_rocket_device(file->minor->dev);
+	struct rocket_file_priv *rocket_priv = file->driver_priv;
+
+	/*
+	 * This is an estimate: the time is taken around the whole period a job
+	 * occupies a core, so it also covers handling the completion interrupt
+	 * and, for a job made of several tasks, the gaps between them.
+	 */
+	drm_printf(p, "drm-engine-npu:\t%lld ns\n",
+		   atomic64_read(&rocket_priv->engine_usage->elapsed_ns));
+	drm_printf(p, "drm-engine-capacity-npu:\t%u\n", rdev->max_cores);
+
+	drm_show_memory_stats(p, file);
+}
+
+static const struct file_operations rocket_accel_driver_fops = {
+	.owner = THIS_MODULE,
+	DRM_ACCEL_FOPS,
+	.show_fdinfo = drm_show_fdinfo,
+};
 
 /*
  * Rocket driver version:
@@ -150,6 +215,7 @@ static const struct drm_driver rocket_drm_driver = {
 	.open			= rocket_open,
 	.postclose		= rocket_postclose,
 	.gem_create_object	= rocket_gem_create_object,
+	.show_fdinfo		= rocket_show_fdinfo,
 	.ioctls			= rocket_drm_driver_ioctls,
 	.num_ioctls		= ARRAY_SIZE(rocket_drm_driver_ioctls),
 	.fops			= &rocket_accel_driver_fops,
diff --git a/drivers/accel/rocket/rocket_drv.h b/drivers/accel/rocket/rocket_drv.h
index 2c673bb99ccc..495d8b4a4d43 100644
--- a/drivers/accel/rocket/rocket_drv.h
+++ b/drivers/accel/rocket/rocket_drv.h
@@ -16,6 +16,16 @@ struct rocket_iommu_domain {
 	struct kref kref;
 };
 
+/*
+ * Time the cores have spent running a client's jobs, in nanoseconds, summed over
+ * all cores. Jobs hold a reference, as they can outlive the file that submitted
+ * them.
+ */
+struct rocket_engine_usage {
+	struct kref kref;
+	atomic64_t elapsed_ns;
+};
+
 struct rocket_file_priv {
 	struct rocket_device *rdev;
 
@@ -24,9 +34,14 @@ struct rocket_file_priv {
 	struct mutex mm_lock;
 
 	struct drm_sched_entity sched_entity;
+
+	struct rocket_engine_usage *engine_usage;
 };
 
 struct rocket_iommu_domain *rocket_iommu_domain_get(struct rocket_file_priv *rocket_priv);
 void rocket_iommu_domain_put(struct rocket_iommu_domain *domain);
 
+struct rocket_engine_usage *rocket_engine_usage_get(struct rocket_file_priv *rocket_priv);
+void rocket_engine_usage_put(struct rocket_engine_usage *usage);
+
 #endif
diff --git a/drivers/accel/rocket/rocket_job.c b/drivers/accel/rocket/rocket_job.c
index ce994748dd5d..e613fae133e4 100644
--- a/drivers/accel/rocket/rocket_job.c
+++ b/drivers/accel/rocket/rocket_job.c
@@ -13,6 +13,7 @@
 #include <linux/iommu.h>
 #include <linux/platform_device.h>
 #include <linux/pm_runtime.h>
+#include <linux/sched/clock.h>
 
 #include "rocket_core.h"
 #include "rocket_device.h"
@@ -265,6 +266,7 @@ static void rocket_job_cleanup(struct kref *ref)
 	unsigned int i;
 
 	rocket_iommu_domain_put(job->domain);
+	rocket_engine_usage_put(job->engine_usage);
 
 	dma_fence_put(job->done_fence);
 	dma_fence_put(job->inference_done_fence);
@@ -351,6 +353,7 @@ static struct dma_fence *rocket_job_run(struct drm_sched_job *sched_job)
 
 	scoped_guard(mutex, &core->job_lock) {
 		core->in_flight_job = job;
+		job->start_ns = local_clock();
 		rocket_job_hw_submit(core, job);
 	}
 
@@ -379,6 +382,9 @@ static void rocket_job_handle_irq(struct rocket_core *core)
 				return;
 			}
 
+			atomic64_add(local_clock() - core->in_flight_job->start_ns,
+				     &core->in_flight_job->engine_usage->elapsed_ns);
+
 			iommu_detach_group(NULL, iommu_group_get(core->dev));
 			dma_fence_signal(core->in_flight_job->done_fence);
 			pm_runtime_put_autosuspend(core->dev);
@@ -587,6 +593,7 @@ static int rocket_ioctl_submit_job(struct drm_device *dev, struct drm_file *file
 
 	rjob->rdev = rdev;
 	rjob->domain = rocket_iommu_domain_get(file_priv);
+	rjob->engine_usage = rocket_engine_usage_get(file_priv);
 
 	ret = drm_sched_job_init(&rjob->base,
 				 &file_priv->sched_entity,
diff --git a/drivers/accel/rocket/rocket_job.h b/drivers/accel/rocket/rocket_job.h
index 4ae00feec3b9..14aa78aebc99 100644
--- a/drivers/accel/rocket/rocket_job.h
+++ b/drivers/accel/rocket/rocket_job.h
@@ -38,6 +38,10 @@ struct rocket_job {
 
 	struct rocket_iommu_domain *domain;
 
+	/* When the job was handed to a core, and where to account the time */
+	u64 start_ns;
+	struct rocket_engine_usage *engine_usage;
+
 	struct kref refcount;
 };
 

base-commit: a1e63ab695ad76850ab9787b9eb6aab695dc2965
prerequisite-patch-id: 519bcdfdde80d902309c8346f749ebc4bb6b29c0
-- 
2.53.0


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

* Re: [PATCH v4] accel/rocket: Report NPU usage through fdinfo
  2026-11-03 15:53 [PATCH v4] accel/rocket: Report NPU usage through fdinfo Sidong Yang
@ 2026-11-05  3:22 ` Gyeyoung Baek
  2026-11-05  6:58   ` Tomeu Vizoso
  2026-11-05  9:22 ` Tvrtko Ursulin
  1 sibling, 1 reply; 7+ messages in thread
From: Gyeyoung Baek @ 2026-11-05  3:22 UTC (permalink / raw)
  To: Sidong Yang; +Cc: Tomeu Vizoso, Oded Gabbay, dri-devel, linux-doc, linux-kernel

Hi Sidong,

On Wed, Nov 4, 2026 at 12:53 AM Sidong Yang <sidong.yang@furiosa.ai> wrote:
>
> There is no way to tell how much of the NPU a client uses. Implement the
> DRM usage stats: account the time each job occupies a core and report
> it per client as drm-engine-npu, along with drm_show_memory_stats() for
> the BOs.
>
> The cores are identical, so they are reported as a single engine with
> drm-engine-capacity-npu set to rdev->max_cores, the number of core
> slots. The time is summed over all cores, with an atomic counter as the
> cores complete jobs concurrently.
>
> Jobs can outlive the file that submitted them, so the counter is
> refcounted and each job holds a reference. The time covers the whole
> period a job owns a core, so it also includes handling the completion
> interrupt and the gaps between the tasks of a multi-task job.

nit: "the time completed jobs occupy a core" would be more accurate than
"the whole period", as timed-out jobs are not accounted.


>  * RK3588
> +
> +.. _rocket-usage-stats:
> +
> +Rocket DRM client usage stats implementation
> +============================================
> +
> +The accel/rocket driver implements the DRM client usage stats specification as
> +documented in :ref:`drm-client-usage-stats`.
> +
> +The NPU cores are reported as a single engine, npu, with a capacity equal to the
> +number of cores. The time is summed over all cores, and covers the whole period
> +a job occupies a core.

Same here

> @@ -139,7 +183,28 @@ static const struct drm_ioctl_desc rocket_drm_driver_ioctls[] = {
>         ROCKET_IOCTL(FINI_BO, fini_bo),
>  };
>
> -DEFINE_DRM_ACCEL_FOPS(rocket_accel_driver_fops);
> +static void rocket_show_fdinfo(struct drm_printer *p, struct drm_file *file)
> +{
> +       struct rocket_device *rdev = to_rocket_device(file->minor->dev);
> +       struct rocket_file_priv *rocket_priv = file->driver_priv;
> +
> +       /*
> +        * This is an estimate: the time is taken around the whole period a job
> +        * occupies a core, so it also covers handling the completion interrupt
> +        * and, for a job made of several tasks, the gaps between them.
> +        */

And here.

with these addressed:

Tested on RK3588: no OOB access, and fdinfo reads correctly with several
apps running concurrently.

Reviewed-by: Gyeyoung Baek <gyeyoung7182@gmail.com>
Tested-by: Gyeyoung Baek <gyeyoung7182@gmail.com>

-- 
Thanks,
Gyeyoung

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

* Re: [PATCH v4] accel/rocket: Report NPU usage through fdinfo
  2026-11-05  3:22 ` Gyeyoung Baek
@ 2026-11-05  6:58   ` Tomeu Vizoso
  0 siblings, 0 replies; 7+ messages in thread
From: Tomeu Vizoso @ 2026-11-05  6:58 UTC (permalink / raw)
  To: Gyeyoung Baek
  Cc: Sidong Yang, Oded Gabbay, dri-devel, linux-doc, linux-kernel

I agree with Gyeyoung.

With that:

Reviewed-by: Tomeu Vizoso <tomeu@tomeuvizoso.net>

Btw, I think we have had a backmerge already.

Thanks,

Tomeu

On Thu, Nov 5, 2026 at 4:22 AM Gyeyoung Baek <gye976@gmail.com> wrote:
>
> Hi Sidong,
>
> On Wed, Nov 4, 2026 at 12:53 AM Sidong Yang <sidong.yang@furiosa.ai> wrote:
> >
> > There is no way to tell how much of the NPU a client uses. Implement the
> > DRM usage stats: account the time each job occupies a core and report
> > it per client as drm-engine-npu, along with drm_show_memory_stats() for
> > the BOs.
> >
> > The cores are identical, so they are reported as a single engine with
> > drm-engine-capacity-npu set to rdev->max_cores, the number of core
> > slots. The time is summed over all cores, with an atomic counter as the
> > cores complete jobs concurrently.
> >
> > Jobs can outlive the file that submitted them, so the counter is
> > refcounted and each job holds a reference. The time covers the whole
> > period a job owns a core, so it also includes handling the completion
> > interrupt and the gaps between the tasks of a multi-task job.
>
> nit: "the time completed jobs occupy a core" would be more accurate than
> "the whole period", as timed-out jobs are not accounted.
>
>
> >  * RK3588
> > +
> > +.. _rocket-usage-stats:
> > +
> > +Rocket DRM client usage stats implementation
> > +============================================
> > +
> > +The accel/rocket driver implements the DRM client usage stats specification as
> > +documented in :ref:`drm-client-usage-stats`.
> > +
> > +The NPU cores are reported as a single engine, npu, with a capacity equal to the
> > +number of cores. The time is summed over all cores, and covers the whole period
> > +a job occupies a core.
>
> Same here
>
> > @@ -139,7 +183,28 @@ static const struct drm_ioctl_desc rocket_drm_driver_ioctls[] = {
> >         ROCKET_IOCTL(FINI_BO, fini_bo),
> >  };
> >
> > -DEFINE_DRM_ACCEL_FOPS(rocket_accel_driver_fops);
> > +static void rocket_show_fdinfo(struct drm_printer *p, struct drm_file *file)
> > +{
> > +       struct rocket_device *rdev = to_rocket_device(file->minor->dev);
> > +       struct rocket_file_priv *rocket_priv = file->driver_priv;
> > +
> > +       /*
> > +        * This is an estimate: the time is taken around the whole period a job
> > +        * occupies a core, so it also covers handling the completion interrupt
> > +        * and, for a job made of several tasks, the gaps between them.
> > +        */
>
> And here.
>
> with these addressed:
>
> Tested on RK3588: no OOB access, and fdinfo reads correctly with several
> apps running concurrently.
>
> Reviewed-by: Gyeyoung Baek <gyeyoung7182@gmail.com>
> Tested-by: Gyeyoung Baek <gyeyoung7182@gmail.com>
>
> --
> Thanks,
> Gyeyoung

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

* Re: [PATCH v4] accel/rocket: Report NPU usage through fdinfo
  2026-11-03 15:53 [PATCH v4] accel/rocket: Report NPU usage through fdinfo Sidong Yang
  2026-11-05  3:22 ` Gyeyoung Baek
@ 2026-11-05  9:22 ` Tvrtko Ursulin
  2026-11-05 10:43   ` Maíra Canal
  1 sibling, 1 reply; 7+ messages in thread
From: Tvrtko Ursulin @ 2026-11-05  9:22 UTC (permalink / raw)
  To: Sidong Yang, Tomeu Vizoso, Oded Gabbay
  Cc: Gyeyoung Baek, dri-devel, linux-doc, linux-kernel


On 03/11/2026 15:53, Sidong Yang wrote:
> There is no way to tell how much of the NPU a client uses. Implement the
> DRM usage stats: account the time each job occupies a core and report
> it per client as drm-engine-npu, along with drm_show_memory_stats() for
> the BOs.
> 
> The cores are identical, so they are reported as a single engine with
> drm-engine-capacity-npu set to rdev->max_cores, the number of core
> slots. The time is summed over all cores, with an atomic counter as the
> cores complete jobs concurrently.
> 
> Jobs can outlive the file that submitted them, so the counter is
> refcounted and each job holds a reference. The time covers the whole
> period a job owns a core, so it also includes handling the completion
> interrupt and the gaps between the tasks of a multi-task job.
> 
> Document the keys in the rocket driver documentation.
> 
> Signed-off-by: Sidong Yang <sidong.yang@furiosa.ai>
> ---
> v4: Report a single drm-engine-npu key with drm-engine-capacity-npu,
>      instead of drm-engine-npu0..2, as drm-usage-stats.rst specifies for
>      a group of identical engines, and document the keys (Tomeu Vizoso).
>      The subject no longer says per-core. Gyeyoung's tags are dropped as
>      the accounting changed.
> 
>      Still depends on commit 6eff1d69dae8 ("accel/rocket: search every
>      core slot when a core is removed") for rdev->max_cores.
> 
> v3: Add a rocket_engine_usage_create() helper for the counter
>      allocation in rocket_open(), to pair with
>      rocket_engine_usage_destroy() (Gyeyoung Baek).
> 
> v2: Size the per-core counters by rdev->max_cores, the number of core
>      slots, instead of the number of cores bound when the file is opened.
>      Sashiko reported the out-of-bounds read and Gyeyoung Baek reproduced
>      it with KASAN.
> 
> Link to v3: https://lore.kernel.org/all/20261103104804.1887489-1-sidong.yang@furiosa.ai/
> Link to v2: https://lore.kernel.org/all/20261101152723.1430312-1-sidong.yang@furiosa.ai/
> Link to v1: https://lore.kernel.org/all/20261031083642.1076356-1-sidong.yang@furiosa.ai/
> 
>   Documentation/accel/rocket/index.rst  | 28 +++++++++++
>   Documentation/gpu/drm-usage-stats.rst |  1 +
>   drivers/accel/rocket/rocket_drv.c     | 70 ++++++++++++++++++++++++++-
>   drivers/accel/rocket/rocket_drv.h     | 15 ++++++
>   drivers/accel/rocket/rocket_job.c     |  7 +++
>   drivers/accel/rocket/rocket_job.h     |  4 ++
>   6 files changed, 123 insertions(+), 2 deletions(-)
> 
> diff --git a/Documentation/accel/rocket/index.rst b/Documentation/accel/rocket/index.rst
> index 70f97bccf100..53c9aa7e2229 100644
> --- a/Documentation/accel/rocket/index.rst
> +++ b/Documentation/accel/rocket/index.rst
> @@ -17,3 +17,31 @@ project.
>   Hardware currently supported:
>   
>   * RK3588
> +
> +.. _rocket-usage-stats:
> +
> +Rocket DRM client usage stats implementation
> +============================================
> +
> +The accel/rocket driver implements the DRM client usage stats specification as
> +documented in :ref:`drm-client-usage-stats`.
> +
> +The NPU cores are reported as a single engine, npu, with a capacity equal to the
> +number of cores. The time is summed over all cores, and covers the whole period
> +a job occupies a core.
> +
> +Example of the output showing the implemented key value pairs:
> +
> +::
> +
> +        pos:	0
> +        flags:	02400002
> +        mnt_id:	33
> +        ino:	749
> +        drm-driver:	rocket
> +        drm-client-id:	246
> +        drm-engine-npu:	2296549300 ns
> +        drm-engine-capacity-npu:	3
> +        drm-total-memory:	24216 KiB
> +        drm-shared-memory:	0
> +        drm-active-memory:	1920 KiB
> diff --git a/Documentation/gpu/drm-usage-stats.rst b/Documentation/gpu/drm-usage-stats.rst
> index 70b7cfcc194f..288764730d23 100644
> --- a/Documentation/gpu/drm-usage-stats.rst
> +++ b/Documentation/gpu/drm-usage-stats.rst
> @@ -218,3 +218,4 @@ Driver specific implementations
>   * :ref:`panthor-usage-stats`
>   * :ref:`xe-usage-stats`
>   * :ref:`amdxdna-usage-stats`
> +* :ref:`rocket-usage-stats`
> diff --git a/drivers/accel/rocket/rocket_drv.c b/drivers/accel/rocket/rocket_drv.c
> index 2bcfe4ab3c68..e22e8623db64 100644
> --- a/drivers/accel/rocket/rocket_drv.c
> +++ b/drivers/accel/rocket/rocket_drv.c
> @@ -3,8 +3,10 @@
>   
>   #include <drm/drm_accel.h>
>   #include <drm/drm_drv.h>
> +#include <drm/drm_file.h>
>   #include <drm/drm_gem.h>
>   #include <drm/drm_ioctl.h>
> +#include <drm/drm_print.h>
>   #include <drm/rocket_accel.h>
>   #include <linux/clk.h>
>   #include <linux/err.h>
> @@ -68,6 +70,38 @@ rocket_iommu_domain_put(struct rocket_iommu_domain *domain)
>   	kref_put(&domain->kref, rocket_iommu_domain_destroy);
>   }
>   
> +static struct rocket_engine_usage *
> +rocket_engine_usage_create(void)
> +{
> +	struct rocket_engine_usage *usage;
> +
> +	usage = kzalloc_obj(*usage);
> +	if (!usage)
> +		return NULL;
> +	kref_init(&usage->kref);
> +
> +	return usage;
> +}
> +
> +static void
> +rocket_engine_usage_destroy(struct kref *kref)
> +{
> +	kfree(container_of(kref, struct rocket_engine_usage, kref));
> +}
> +
> +struct rocket_engine_usage *
> +rocket_engine_usage_get(struct rocket_file_priv *rocket_priv)
> +{
> +	kref_get(&rocket_priv->engine_usage->kref);
> +	return rocket_priv->engine_usage;
> +}
> +
> +void
> +rocket_engine_usage_put(struct rocket_engine_usage *usage)
> +{
> +	kref_put(&usage->kref, rocket_engine_usage_destroy);
> +}
> +
>   static int
>   rocket_open(struct drm_device *dev, struct drm_file *file)
>   {
> @@ -86,10 +120,17 @@ rocket_open(struct drm_device *dev, struct drm_file *file)
>   	}
>   
>   	rocket_priv->rdev = rdev;
> +
> +	rocket_priv->engine_usage = rocket_engine_usage_create();
> +	if (!rocket_priv->engine_usage) {
> +		ret = -ENOMEM;
> +		goto err_free;
> +	}

Glanced over this patch by chance and it very reminded me of 
drm_sched_entity_stats tracking. That object is reference counted by the 
entity so I think it would satisfy your requirements. We would only need 
to add an accessor like drm_sched_entity_get_runtime() and just call it 
from rocket. Thoughts?

Regards,

Tvrtko

> +
>   	rocket_priv->domain = rocket_iommu_domain_create(rdev->cores[0].dev);
>   	if (IS_ERR(rocket_priv->domain)) {
>   		ret = PTR_ERR(rocket_priv->domain);
> -		goto err_free;
> +		goto err_put_engine_usage;
>   	}
>   
>   	file->driver_priv = rocket_priv;
> @@ -109,6 +150,8 @@ rocket_open(struct drm_device *dev, struct drm_file *file)
>   	mutex_destroy(&rocket_priv->mm_lock);
>   	drm_mm_takedown(&rocket_priv->mm);
>   	rocket_iommu_domain_put(rocket_priv->domain);
> +err_put_engine_usage:
> +	rocket_engine_usage_put(rocket_priv->engine_usage);
>   err_free:
>   	kfree(rocket_priv);
>   err_put_mod:
> @@ -125,6 +168,7 @@ rocket_postclose(struct drm_device *dev, struct drm_file *file)
>   	mutex_destroy(&rocket_priv->mm_lock);
>   	drm_mm_takedown(&rocket_priv->mm);
>   	rocket_iommu_domain_put(rocket_priv->domain);
> +	rocket_engine_usage_put(rocket_priv->engine_usage);
>   	kfree(rocket_priv);
>   	module_put(THIS_MODULE);
>   }
> @@ -139,7 +183,28 @@ static const struct drm_ioctl_desc rocket_drm_driver_ioctls[] = {
>   	ROCKET_IOCTL(FINI_BO, fini_bo),
>   };
>   
> -DEFINE_DRM_ACCEL_FOPS(rocket_accel_driver_fops);
> +static void rocket_show_fdinfo(struct drm_printer *p, struct drm_file *file)
> +{
> +	struct rocket_device *rdev = to_rocket_device(file->minor->dev);
> +	struct rocket_file_priv *rocket_priv = file->driver_priv;
> +
> +	/*
> +	 * This is an estimate: the time is taken around the whole period a job
> +	 * occupies a core, so it also covers handling the completion interrupt
> +	 * and, for a job made of several tasks, the gaps between them.
> +	 */
> +	drm_printf(p, "drm-engine-npu:\t%lld ns\n",
> +		   atomic64_read(&rocket_priv->engine_usage->elapsed_ns));
> +	drm_printf(p, "drm-engine-capacity-npu:\t%u\n", rdev->max_cores);
> +
> +	drm_show_memory_stats(p, file);
> +}
> +
> +static const struct file_operations rocket_accel_driver_fops = {
> +	.owner = THIS_MODULE,
> +	DRM_ACCEL_FOPS,
> +	.show_fdinfo = drm_show_fdinfo,
> +};
>   
>   /*
>    * Rocket driver version:
> @@ -150,6 +215,7 @@ static const struct drm_driver rocket_drm_driver = {
>   	.open			= rocket_open,
>   	.postclose		= rocket_postclose,
>   	.gem_create_object	= rocket_gem_create_object,
> +	.show_fdinfo		= rocket_show_fdinfo,
>   	.ioctls			= rocket_drm_driver_ioctls,
>   	.num_ioctls		= ARRAY_SIZE(rocket_drm_driver_ioctls),
>   	.fops			= &rocket_accel_driver_fops,
> diff --git a/drivers/accel/rocket/rocket_drv.h b/drivers/accel/rocket/rocket_drv.h
> index 2c673bb99ccc..495d8b4a4d43 100644
> --- a/drivers/accel/rocket/rocket_drv.h
> +++ b/drivers/accel/rocket/rocket_drv.h
> @@ -16,6 +16,16 @@ struct rocket_iommu_domain {
>   	struct kref kref;
>   };
>   
> +/*
> + * Time the cores have spent running a client's jobs, in nanoseconds, summed over
> + * all cores. Jobs hold a reference, as they can outlive the file that submitted
> + * them.
> + */
> +struct rocket_engine_usage {
> +	struct kref kref;
> +	atomic64_t elapsed_ns;
> +};
> +
>   struct rocket_file_priv {
>   	struct rocket_device *rdev;
>   
> @@ -24,9 +34,14 @@ struct rocket_file_priv {
>   	struct mutex mm_lock;
>   
>   	struct drm_sched_entity sched_entity;
> +
> +	struct rocket_engine_usage *engine_usage;
>   };
>   
>   struct rocket_iommu_domain *rocket_iommu_domain_get(struct rocket_file_priv *rocket_priv);
>   void rocket_iommu_domain_put(struct rocket_iommu_domain *domain);
>   
> +struct rocket_engine_usage *rocket_engine_usage_get(struct rocket_file_priv *rocket_priv);
> +void rocket_engine_usage_put(struct rocket_engine_usage *usage);
> +
>   #endif
> diff --git a/drivers/accel/rocket/rocket_job.c b/drivers/accel/rocket/rocket_job.c
> index ce994748dd5d..e613fae133e4 100644
> --- a/drivers/accel/rocket/rocket_job.c
> +++ b/drivers/accel/rocket/rocket_job.c
> @@ -13,6 +13,7 @@
>   #include <linux/iommu.h>
>   #include <linux/platform_device.h>
>   #include <linux/pm_runtime.h>
> +#include <linux/sched/clock.h>
>   
>   #include "rocket_core.h"
>   #include "rocket_device.h"
> @@ -265,6 +266,7 @@ static void rocket_job_cleanup(struct kref *ref)
>   	unsigned int i;
>   
>   	rocket_iommu_domain_put(job->domain);
> +	rocket_engine_usage_put(job->engine_usage);
>   
>   	dma_fence_put(job->done_fence);
>   	dma_fence_put(job->inference_done_fence);
> @@ -351,6 +353,7 @@ static struct dma_fence *rocket_job_run(struct drm_sched_job *sched_job)
>   
>   	scoped_guard(mutex, &core->job_lock) {
>   		core->in_flight_job = job;
> +		job->start_ns = local_clock();
>   		rocket_job_hw_submit(core, job);
>   	}
>   
> @@ -379,6 +382,9 @@ static void rocket_job_handle_irq(struct rocket_core *core)
>   				return;
>   			}
>   
> +			atomic64_add(local_clock() - core->in_flight_job->start_ns,
> +				     &core->in_flight_job->engine_usage->elapsed_ns);
> +
>   			iommu_detach_group(NULL, iommu_group_get(core->dev));
>   			dma_fence_signal(core->in_flight_job->done_fence);
>   			pm_runtime_put_autosuspend(core->dev);
> @@ -587,6 +593,7 @@ static int rocket_ioctl_submit_job(struct drm_device *dev, struct drm_file *file
>   
>   	rjob->rdev = rdev;
>   	rjob->domain = rocket_iommu_domain_get(file_priv);
> +	rjob->engine_usage = rocket_engine_usage_get(file_priv);
>   
>   	ret = drm_sched_job_init(&rjob->base,
>   				 &file_priv->sched_entity,
> diff --git a/drivers/accel/rocket/rocket_job.h b/drivers/accel/rocket/rocket_job.h
> index 4ae00feec3b9..14aa78aebc99 100644
> --- a/drivers/accel/rocket/rocket_job.h
> +++ b/drivers/accel/rocket/rocket_job.h
> @@ -38,6 +38,10 @@ struct rocket_job {
>   
>   	struct rocket_iommu_domain *domain;
>   
> +	/* When the job was handed to a core, and where to account the time */
> +	u64 start_ns;
> +	struct rocket_engine_usage *engine_usage;
> +
>   	struct kref refcount;
>   };
>   
> 
> base-commit: a1e63ab695ad76850ab9787b9eb6aab695dc2965
> prerequisite-patch-id: 519bcdfdde80d902309c8346f749ebc4bb6b29c0


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

* Re: [PATCH v4] accel/rocket: Report NPU usage through fdinfo
  2026-11-05  9:22 ` Tvrtko Ursulin
@ 2026-11-05 10:43   ` Maíra Canal
  2026-11-05 11:04     ` Tvrtko Ursulin
  0 siblings, 1 reply; 7+ messages in thread
From: Maíra Canal @ 2026-11-05 10:43 UTC (permalink / raw)
  To: Tvrtko Ursulin, Sidong Yang, Tomeu Vizoso, Oded Gabbay
  Cc: Gyeyoung Baek, dri-devel, linux-doc, linux-kernel

Hi Tvrtko,

On 05/11/26 06:22, Tvrtko Ursulin wrote:
> 
> On 03/11/2026 15:53, Sidong Yang wrote:
>> There is no way to tell how much of the NPU a client uses. Implement the
>> DRM usage stats: account the time each job occupies a core and report
>> it per client as drm-engine-npu, along with drm_show_memory_stats() for
>> the BOs.
>>
>> The cores are identical, so they are reported as a single engine with
>> drm-engine-capacity-npu set to rdev->max_cores, the number of core
>> slots. The time is summed over all cores, with an atomic counter as the
>> cores complete jobs concurrently.
>>
>> Jobs can outlive the file that submitted them, so the counter is
>> refcounted and each job holds a reference. The time covers the whole
>> period a job owns a core, so it also includes handling the completion
>> interrupt and the gaps between the tasks of a multi-task job.
>>
>> Document the keys in the rocket driver documentation.
>>
>> Signed-off-by: Sidong Yang <sidong.yang@furiosa.ai>
>> ---
>> v4: Report a single drm-engine-npu key with drm-engine-capacity-npu,
>>      instead of drm-engine-npu0..2, as drm-usage-stats.rst specifies for
>>      a group of identical engines, and document the keys (Tomeu Vizoso).
>>      The subject no longer says per-core. Gyeyoung's tags are dropped as
>>      the accounting changed.
>>
>>      Still depends on commit 6eff1d69dae8 ("accel/rocket: search every
>>      core slot when a core is removed") for rdev->max_cores.
>>
>> v3: Add a rocket_engine_usage_create() helper for the counter
>>      allocation in rocket_open(), to pair with
>>      rocket_engine_usage_destroy() (Gyeyoung Baek).
>>
>> v2: Size the per-core counters by rdev->max_cores, the number of core
>>      slots, instead of the number of cores bound when the file is opened.
>>      Sashiko reported the out-of-bounds read and Gyeyoung Baek reproduced
>>      it with KASAN.
>>
>> Link to v3: https://lore.kernel.org/all/20261103104804.1887489-1- 
>> sidong.yang@furiosa.ai/
>> Link to v2: https://lore.kernel.org/all/20261101152723.1430312-1- 
>> sidong.yang@furiosa.ai/
>> Link to v1: https://lore.kernel.org/all/20261031083642.1076356-1- 
>> sidong.yang@furiosa.ai/
>>
>>   Documentation/accel/rocket/index.rst  | 28 +++++++++++
>>   Documentation/gpu/drm-usage-stats.rst |  1 +
>>   drivers/accel/rocket/rocket_drv.c     | 70 ++++++++++++++++++++++++++-
>>   drivers/accel/rocket/rocket_drv.h     | 15 ++++++
>>   drivers/accel/rocket/rocket_job.c     |  7 +++
>>   drivers/accel/rocket/rocket_job.h     |  4 ++
>>   6 files changed, 123 insertions(+), 2 deletions(-)
>>
>> diff --git a/Documentation/accel/rocket/index.rst b/Documentation/ 
>> accel/rocket/index.rst
>> index 70f97bccf100..53c9aa7e2229 100644
>> --- a/Documentation/accel/rocket/index.rst
>> +++ b/Documentation/accel/rocket/index.rst
>> @@ -17,3 +17,31 @@ project.
>>   Hardware currently supported:
>>   * RK3588
>> +
>> +.. _rocket-usage-stats:
>> +
>> +Rocket DRM client usage stats implementation
>> +============================================
>> +
>> +The accel/rocket driver implements the DRM client usage stats 
>> specification as
>> +documented in :ref:`drm-client-usage-stats`.
>> +
>> +The NPU cores are reported as a single engine, npu, with a capacity 
>> equal to the
>> +number of cores. The time is summed over all cores, and covers the 
>> whole period
>> +a job occupies a core.
>> +
>> +Example of the output showing the implemented key value pairs:
>> +
>> +::
>> +
>> +        pos:    0
>> +        flags:    02400002
>> +        mnt_id:    33
>> +        ino:    749
>> +        drm-driver:    rocket
>> +        drm-client-id:    246
>> +        drm-engine-npu:    2296549300 ns
>> +        drm-engine-capacity-npu:    3
>> +        drm-total-memory:    24216 KiB
>> +        drm-shared-memory:    0
>> +        drm-active-memory:    1920 KiB
>> diff --git a/Documentation/gpu/drm-usage-stats.rst b/Documentation/ 
>> gpu/drm-usage-stats.rst
>> index 70b7cfcc194f..288764730d23 100644
>> --- a/Documentation/gpu/drm-usage-stats.rst
>> +++ b/Documentation/gpu/drm-usage-stats.rst
>> @@ -218,3 +218,4 @@ Driver specific implementations
>>   * :ref:`panthor-usage-stats`
>>   * :ref:`xe-usage-stats`
>>   * :ref:`amdxdna-usage-stats`
>> +* :ref:`rocket-usage-stats`
>> diff --git a/drivers/accel/rocket/rocket_drv.c b/drivers/accel/rocket/ 
>> rocket_drv.c
>> index 2bcfe4ab3c68..e22e8623db64 100644
>> --- a/drivers/accel/rocket/rocket_drv.c
>> +++ b/drivers/accel/rocket/rocket_drv.c
>> @@ -3,8 +3,10 @@
>>   #include <drm/drm_accel.h>
>>   #include <drm/drm_drv.h>
>> +#include <drm/drm_file.h>
>>   #include <drm/drm_gem.h>
>>   #include <drm/drm_ioctl.h>
>> +#include <drm/drm_print.h>
>>   #include <drm/rocket_accel.h>
>>   #include <linux/clk.h>
>>   #include <linux/err.h>
>> @@ -68,6 +70,38 @@ rocket_iommu_domain_put(struct rocket_iommu_domain 
>> *domain)
>>       kref_put(&domain->kref, rocket_iommu_domain_destroy);
>>   }
>> +static struct rocket_engine_usage *
>> +rocket_engine_usage_create(void)
>> +{
>> +    struct rocket_engine_usage *usage;
>> +
>> +    usage = kzalloc_obj(*usage);
>> +    if (!usage)
>> +        return NULL;
>> +    kref_init(&usage->kref);
>> +
>> +    return usage;
>> +}
>> +
>> +static void
>> +rocket_engine_usage_destroy(struct kref *kref)
>> +{
>> +    kfree(container_of(kref, struct rocket_engine_usage, kref));
>> +}
>> +
>> +struct rocket_engine_usage *
>> +rocket_engine_usage_get(struct rocket_file_priv *rocket_priv)
>> +{
>> +    kref_get(&rocket_priv->engine_usage->kref);
>> +    return rocket_priv->engine_usage;
>> +}
>> +
>> +void
>> +rocket_engine_usage_put(struct rocket_engine_usage *usage)
>> +{
>> +    kref_put(&usage->kref, rocket_engine_usage_destroy);
>> +}
>> +
>>   static int
>>   rocket_open(struct drm_device *dev, struct drm_file *file)
>>   {
>> @@ -86,10 +120,17 @@ rocket_open(struct drm_device *dev, struct 
>> drm_file *file)
>>       }
>>       rocket_priv->rdev = rdev;
>> +
>> +    rocket_priv->engine_usage = rocket_engine_usage_create();
>> +    if (!rocket_priv->engine_usage) {
>> +        ret = -ENOMEM;
>> +        goto err_free;
>> +    }
> 
> Glanced over this patch by chance and it very reminded me of 
> drm_sched_entity_stats tracking. That object is reference counted by the 
> entity so I think it would satisfy your requirements. We would only need 
> to add an accessor like drm_sched_entity_get_runtime() and just call it 
> from rocket. Thoughts?
> 

I believe we tried something similar in the past (commit 97804a133c68)
and it ended up being reverted after this regression [1]. I would be
great to give this idea another change (specially now that we have
drm_sched_entity_stats), as it would also be useful for V3D.

[1] 
https://lore.kernel.org/dri-devel/3e00d8a9-b6c4-8202-4f2d-5a659c61d094@redhat.com/

Best regards,
- Maíra

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

* Re: [PATCH v4] accel/rocket: Report NPU usage through fdinfo
  2026-11-05 10:43   ` Maíra Canal
@ 2026-11-05 11:04     ` Tvrtko Ursulin
  2026-11-05 11:07       ` Maíra Canal
  0 siblings, 1 reply; 7+ messages in thread
From: Tvrtko Ursulin @ 2026-11-05 11:04 UTC (permalink / raw)
  To: Maíra Canal, Sidong Yang, Tomeu Vizoso, Oded Gabbay
  Cc: Gyeyoung Baek, dri-devel, linux-doc, linux-kernel,
	Philipp Stanner, Danilo Krummrich


On 05/11/2026 10:43, Maíra Canal wrote:
> Hi Tvrtko,
> 
> On 05/11/26 06:22, Tvrtko Ursulin wrote:
>>
>> On 03/11/2026 15:53, Sidong Yang wrote:
>>> There is no way to tell how much of the NPU a client uses. Implement the
>>> DRM usage stats: account the time each job occupies a core and report
>>> it per client as drm-engine-npu, along with drm_show_memory_stats() for
>>> the BOs.
>>>
>>> The cores are identical, so they are reported as a single engine with
>>> drm-engine-capacity-npu set to rdev->max_cores, the number of core
>>> slots. The time is summed over all cores, with an atomic counter as the
>>> cores complete jobs concurrently.
>>>
>>> Jobs can outlive the file that submitted them, so the counter is
>>> refcounted and each job holds a reference. The time covers the whole
>>> period a job owns a core, so it also includes handling the completion
>>> interrupt and the gaps between the tasks of a multi-task job.
>>>
>>> Document the keys in the rocket driver documentation.
>>>
>>> Signed-off-by: Sidong Yang <sidong.yang@furiosa.ai>
>>> ---
>>> v4: Report a single drm-engine-npu key with drm-engine-capacity-npu,
>>>      instead of drm-engine-npu0..2, as drm-usage-stats.rst specifies for
>>>      a group of identical engines, and document the keys (Tomeu Vizoso).
>>>      The subject no longer says per-core. Gyeyoung's tags are dropped as
>>>      the accounting changed.
>>>
>>>      Still depends on commit 6eff1d69dae8 ("accel/rocket: search every
>>>      core slot when a core is removed") for rdev->max_cores.
>>>
>>> v3: Add a rocket_engine_usage_create() helper for the counter
>>>      allocation in rocket_open(), to pair with
>>>      rocket_engine_usage_destroy() (Gyeyoung Baek).
>>>
>>> v2: Size the per-core counters by rdev->max_cores, the number of core
>>>      slots, instead of the number of cores bound when the file is 
>>> opened.
>>>      Sashiko reported the out-of-bounds read and Gyeyoung Baek 
>>> reproduced
>>>      it with KASAN.
>>>
>>> Link to v3: https://lore.kernel.org/all/20261103104804.1887489-1- 
>>> sidong.yang@furiosa.ai/
>>> Link to v2: https://lore.kernel.org/all/20261101152723.1430312-1- 
>>> sidong.yang@furiosa.ai/
>>> Link to v1: https://lore.kernel.org/all/20261031083642.1076356-1- 
>>> sidong.yang@furiosa.ai/
>>>
>>>   Documentation/accel/rocket/index.rst  | 28 +++++++++++
>>>   Documentation/gpu/drm-usage-stats.rst |  1 +
>>>   drivers/accel/rocket/rocket_drv.c     | 70 ++++++++++++++++++++++++++-
>>>   drivers/accel/rocket/rocket_drv.h     | 15 ++++++
>>>   drivers/accel/rocket/rocket_job.c     |  7 +++
>>>   drivers/accel/rocket/rocket_job.h     |  4 ++
>>>   6 files changed, 123 insertions(+), 2 deletions(-)
>>>
>>> diff --git a/Documentation/accel/rocket/index.rst b/Documentation/ 
>>> accel/rocket/index.rst
>>> index 70f97bccf100..53c9aa7e2229 100644
>>> --- a/Documentation/accel/rocket/index.rst
>>> +++ b/Documentation/accel/rocket/index.rst
>>> @@ -17,3 +17,31 @@ project.
>>>   Hardware currently supported:
>>>   * RK3588
>>> +
>>> +.. _rocket-usage-stats:
>>> +
>>> +Rocket DRM client usage stats implementation
>>> +============================================
>>> +
>>> +The accel/rocket driver implements the DRM client usage stats 
>>> specification as
>>> +documented in :ref:`drm-client-usage-stats`.
>>> +
>>> +The NPU cores are reported as a single engine, npu, with a capacity 
>>> equal to the
>>> +number of cores. The time is summed over all cores, and covers the 
>>> whole period
>>> +a job occupies a core.
>>> +
>>> +Example of the output showing the implemented key value pairs:
>>> +
>>> +::
>>> +
>>> +        pos:    0
>>> +        flags:    02400002
>>> +        mnt_id:    33
>>> +        ino:    749
>>> +        drm-driver:    rocket
>>> +        drm-client-id:    246
>>> +        drm-engine-npu:    2296549300 ns
>>> +        drm-engine-capacity-npu:    3
>>> +        drm-total-memory:    24216 KiB
>>> +        drm-shared-memory:    0
>>> +        drm-active-memory:    1920 KiB
>>> diff --git a/Documentation/gpu/drm-usage-stats.rst b/Documentation/ 
>>> gpu/drm-usage-stats.rst
>>> index 70b7cfcc194f..288764730d23 100644
>>> --- a/Documentation/gpu/drm-usage-stats.rst
>>> +++ b/Documentation/gpu/drm-usage-stats.rst
>>> @@ -218,3 +218,4 @@ Driver specific implementations
>>>   * :ref:`panthor-usage-stats`
>>>   * :ref:`xe-usage-stats`
>>>   * :ref:`amdxdna-usage-stats`
>>> +* :ref:`rocket-usage-stats`
>>> diff --git a/drivers/accel/rocket/rocket_drv.c b/drivers/accel/ 
>>> rocket/ rocket_drv.c
>>> index 2bcfe4ab3c68..e22e8623db64 100644
>>> --- a/drivers/accel/rocket/rocket_drv.c
>>> +++ b/drivers/accel/rocket/rocket_drv.c
>>> @@ -3,8 +3,10 @@
>>>   #include <drm/drm_accel.h>
>>>   #include <drm/drm_drv.h>
>>> +#include <drm/drm_file.h>
>>>   #include <drm/drm_gem.h>
>>>   #include <drm/drm_ioctl.h>
>>> +#include <drm/drm_print.h>
>>>   #include <drm/rocket_accel.h>
>>>   #include <linux/clk.h>
>>>   #include <linux/err.h>
>>> @@ -68,6 +70,38 @@ rocket_iommu_domain_put(struct rocket_iommu_domain 
>>> *domain)
>>>       kref_put(&domain->kref, rocket_iommu_domain_destroy);
>>>   }
>>> +static struct rocket_engine_usage *
>>> +rocket_engine_usage_create(void)
>>> +{
>>> +    struct rocket_engine_usage *usage;
>>> +
>>> +    usage = kzalloc_obj(*usage);
>>> +    if (!usage)
>>> +        return NULL;
>>> +    kref_init(&usage->kref);
>>> +
>>> +    return usage;
>>> +}
>>> +
>>> +static void
>>> +rocket_engine_usage_destroy(struct kref *kref)
>>> +{
>>> +    kfree(container_of(kref, struct rocket_engine_usage, kref));
>>> +}
>>> +
>>> +struct rocket_engine_usage *
>>> +rocket_engine_usage_get(struct rocket_file_priv *rocket_priv)
>>> +{
>>> +    kref_get(&rocket_priv->engine_usage->kref);
>>> +    return rocket_priv->engine_usage;
>>> +}
>>> +
>>> +void
>>> +rocket_engine_usage_put(struct rocket_engine_usage *usage)
>>> +{
>>> +    kref_put(&usage->kref, rocket_engine_usage_destroy);
>>> +}
>>> +
>>>   static int
>>>   rocket_open(struct drm_device *dev, struct drm_file *file)
>>>   {
>>> @@ -86,10 +120,17 @@ rocket_open(struct drm_device *dev, struct 
>>> drm_file *file)
>>>       }
>>>       rocket_priv->rdev = rdev;
>>> +
>>> +    rocket_priv->engine_usage = rocket_engine_usage_create();
>>> +    if (!rocket_priv->engine_usage) {
>>> +        ret = -ENOMEM;
>>> +        goto err_free;
>>> +    }
>>
>> Glanced over this patch by chance and it very reminded me of 
>> drm_sched_entity_stats tracking. That object is reference counted by 
>> the entity so I think it would satisfy your requirements. We would 
>> only need to add an accessor like drm_sched_entity_get_runtime() and 
>> just call it from rocket. Thoughts?
>>
> 
> I believe we tried something similar in the past (commit 97804a133c68)

You mean df622729ddbf? But yes, I don't think I knew about that.

> and it ended up being reverted after this regression [1]. I would be
> great to give this idea another change (specially now that we have
> drm_sched_entity_stats), as it would also be useful for V3D.

It makes sense to me if Philipp and Danilo will agree so adding them cc.

It would just be adding u64 drm_sched_entity_get_runtime(entity). 
Nothing else would need to be exported and the implementation simply 
locks entity->stats and returns the runtime. As long as the caller knows 
they haven't destroyed the entity it is safe since entity holds a 
reference to the stats object.

If rocket and v3d can use it that's a reasonable starting point for 
adding common API. Three users would be even better than two though, 
going by the long standing DRM tradition. :)

Regards,

Tvrtko

> [1] https://lore.kernel.org/dri-devel/3e00d8a9- 
> b6c4-8202-4f2d-5a659c61d094@redhat.com/
> 
> Best regards,
> - Maíra


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

* Re: [PATCH v4] accel/rocket: Report NPU usage through fdinfo
  2026-11-05 11:04     ` Tvrtko Ursulin
@ 2026-11-05 11:07       ` Maíra Canal
  0 siblings, 0 replies; 7+ messages in thread
From: Maíra Canal @ 2026-11-05 11:07 UTC (permalink / raw)
  To: Tvrtko Ursulin, Sidong Yang, Tomeu Vizoso, Oded Gabbay
  Cc: Gyeyoung Baek, dri-devel, linux-doc, linux-kernel,
	Philipp Stanner, Danilo Krummrich

On 05/11/26 08:04, Tvrtko Ursulin wrote:
> 
> On 05/11/2026 10:43, Maíra Canal wrote:
>> Hi Tvrtko,
>>
>> On 05/11/26 06:22, Tvrtko Ursulin wrote:
>>>
>>> On 03/11/2026 15:53, Sidong Yang wrote:
>>>> There is no way to tell how much of the NPU a client uses. Implement 
>>>> the
>>>> DRM usage stats: account the time each job occupies a core and report
>>>> it per client as drm-engine-npu, along with drm_show_memory_stats() for
>>>> the BOs.
>>>>
>>>> The cores are identical, so they are reported as a single engine with
>>>> drm-engine-capacity-npu set to rdev->max_cores, the number of core
>>>> slots. The time is summed over all cores, with an atomic counter as the
>>>> cores complete jobs concurrently.
>>>>
>>>> Jobs can outlive the file that submitted them, so the counter is
>>>> refcounted and each job holds a reference. The time covers the whole
>>>> period a job owns a core, so it also includes handling the completion
>>>> interrupt and the gaps between the tasks of a multi-task job.
>>>>
>>>> Document the keys in the rocket driver documentation.
>>>>
>>>> Signed-off-by: Sidong Yang <sidong.yang@furiosa.ai>
>>>> ---
>>>> v4: Report a single drm-engine-npu key with drm-engine-capacity-npu,
>>>>      instead of drm-engine-npu0..2, as drm-usage-stats.rst specifies 
>>>> for
>>>>      a group of identical engines, and document the keys (Tomeu 
>>>> Vizoso).
>>>>      The subject no longer says per-core. Gyeyoung's tags are 
>>>> dropped as
>>>>      the accounting changed.
>>>>
>>>>      Still depends on commit 6eff1d69dae8 ("accel/rocket: search every
>>>>      core slot when a core is removed") for rdev->max_cores.
>>>>
>>>> v3: Add a rocket_engine_usage_create() helper for the counter
>>>>      allocation in rocket_open(), to pair with
>>>>      rocket_engine_usage_destroy() (Gyeyoung Baek).
>>>>
>>>> v2: Size the per-core counters by rdev->max_cores, the number of core
>>>>      slots, instead of the number of cores bound when the file is 
>>>> opened.
>>>>      Sashiko reported the out-of-bounds read and Gyeyoung Baek 
>>>> reproduced
>>>>      it with KASAN.
>>>>
>>>> Link to v3: https://lore.kernel.org/all/20261103104804.1887489-1- 
>>>> sidong.yang@furiosa.ai/
>>>> Link to v2: https://lore.kernel.org/all/20261101152723.1430312-1- 
>>>> sidong.yang@furiosa.ai/
>>>> Link to v1: https://lore.kernel.org/all/20261031083642.1076356-1- 
>>>> sidong.yang@furiosa.ai/
>>>>
>>>>   Documentation/accel/rocket/index.rst  | 28 +++++++++++
>>>>   Documentation/gpu/drm-usage-stats.rst |  1 +
>>>>   drivers/accel/rocket/rocket_drv.c     | 70 +++++++++++++++++++++++ 
>>>> +++-
>>>>   drivers/accel/rocket/rocket_drv.h     | 15 ++++++
>>>>   drivers/accel/rocket/rocket_job.c     |  7 +++
>>>>   drivers/accel/rocket/rocket_job.h     |  4 ++
>>>>   6 files changed, 123 insertions(+), 2 deletions(-)
>>>>
>>>> diff --git a/Documentation/accel/rocket/index.rst b/Documentation/ 
>>>> accel/rocket/index.rst
>>>> index 70f97bccf100..53c9aa7e2229 100644
>>>> --- a/Documentation/accel/rocket/index.rst
>>>> +++ b/Documentation/accel/rocket/index.rst
>>>> @@ -17,3 +17,31 @@ project.
>>>>   Hardware currently supported:
>>>>   * RK3588
>>>> +
>>>> +.. _rocket-usage-stats:
>>>> +
>>>> +Rocket DRM client usage stats implementation
>>>> +============================================
>>>> +
>>>> +The accel/rocket driver implements the DRM client usage stats 
>>>> specification as
>>>> +documented in :ref:`drm-client-usage-stats`.
>>>> +
>>>> +The NPU cores are reported as a single engine, npu, with a capacity 
>>>> equal to the
>>>> +number of cores. The time is summed over all cores, and covers the 
>>>> whole period
>>>> +a job occupies a core.
>>>> +
>>>> +Example of the output showing the implemented key value pairs:
>>>> +
>>>> +::
>>>> +
>>>> +        pos:    0
>>>> +        flags:    02400002
>>>> +        mnt_id:    33
>>>> +        ino:    749
>>>> +        drm-driver:    rocket
>>>> +        drm-client-id:    246
>>>> +        drm-engine-npu:    2296549300 ns
>>>> +        drm-engine-capacity-npu:    3
>>>> +        drm-total-memory:    24216 KiB
>>>> +        drm-shared-memory:    0
>>>> +        drm-active-memory:    1920 KiB
>>>> diff --git a/Documentation/gpu/drm-usage-stats.rst b/Documentation/ 
>>>> gpu/drm-usage-stats.rst
>>>> index 70b7cfcc194f..288764730d23 100644
>>>> --- a/Documentation/gpu/drm-usage-stats.rst
>>>> +++ b/Documentation/gpu/drm-usage-stats.rst
>>>> @@ -218,3 +218,4 @@ Driver specific implementations
>>>>   * :ref:`panthor-usage-stats`
>>>>   * :ref:`xe-usage-stats`
>>>>   * :ref:`amdxdna-usage-stats`
>>>> +* :ref:`rocket-usage-stats`
>>>> diff --git a/drivers/accel/rocket/rocket_drv.c b/drivers/accel/ 
>>>> rocket/ rocket_drv.c
>>>> index 2bcfe4ab3c68..e22e8623db64 100644
>>>> --- a/drivers/accel/rocket/rocket_drv.c
>>>> +++ b/drivers/accel/rocket/rocket_drv.c
>>>> @@ -3,8 +3,10 @@
>>>>   #include <drm/drm_accel.h>
>>>>   #include <drm/drm_drv.h>
>>>> +#include <drm/drm_file.h>
>>>>   #include <drm/drm_gem.h>
>>>>   #include <drm/drm_ioctl.h>
>>>> +#include <drm/drm_print.h>
>>>>   #include <drm/rocket_accel.h>
>>>>   #include <linux/clk.h>
>>>>   #include <linux/err.h>
>>>> @@ -68,6 +70,38 @@ rocket_iommu_domain_put(struct 
>>>> rocket_iommu_domain *domain)
>>>>       kref_put(&domain->kref, rocket_iommu_domain_destroy);
>>>>   }
>>>> +static struct rocket_engine_usage *
>>>> +rocket_engine_usage_create(void)
>>>> +{
>>>> +    struct rocket_engine_usage *usage;
>>>> +
>>>> +    usage = kzalloc_obj(*usage);
>>>> +    if (!usage)
>>>> +        return NULL;
>>>> +    kref_init(&usage->kref);
>>>> +
>>>> +    return usage;
>>>> +}
>>>> +
>>>> +static void
>>>> +rocket_engine_usage_destroy(struct kref *kref)
>>>> +{
>>>> +    kfree(container_of(kref, struct rocket_engine_usage, kref));
>>>> +}
>>>> +
>>>> +struct rocket_engine_usage *
>>>> +rocket_engine_usage_get(struct rocket_file_priv *rocket_priv)
>>>> +{
>>>> +    kref_get(&rocket_priv->engine_usage->kref);
>>>> +    return rocket_priv->engine_usage;
>>>> +}
>>>> +
>>>> +void
>>>> +rocket_engine_usage_put(struct rocket_engine_usage *usage)
>>>> +{
>>>> +    kref_put(&usage->kref, rocket_engine_usage_destroy);
>>>> +}
>>>> +
>>>>   static int
>>>>   rocket_open(struct drm_device *dev, struct drm_file *file)
>>>>   {
>>>> @@ -86,10 +120,17 @@ rocket_open(struct drm_device *dev, struct 
>>>> drm_file *file)
>>>>       }
>>>>       rocket_priv->rdev = rdev;
>>>> +
>>>> +    rocket_priv->engine_usage = rocket_engine_usage_create();
>>>> +    if (!rocket_priv->engine_usage) {
>>>> +        ret = -ENOMEM;
>>>> +        goto err_free;
>>>> +    }
>>>
>>> Glanced over this patch by chance and it very reminded me of 
>>> drm_sched_entity_stats tracking. That object is reference counted by 
>>> the entity so I think it would satisfy your requirements. We would 
>>> only need to add an accessor like drm_sched_entity_get_runtime() and 
>>> just call it from rocket. Thoughts?
>>>
>>
>> I believe we tried something similar in the past (commit 97804a133c68)
> 
> You mean df622729ddbf? But yes, I don't think I knew about that.

Yes, sorry for the copy/paste mistake.

> 
>> and it ended up being reverted after this regression [1]. I would be
>> great to give this idea another change (specially now that we have
>> drm_sched_entity_stats), as it would also be useful for V3D.
> 
> It makes sense to me if Philipp and Danilo will agree so adding them cc.
> 
> It would just be adding u64 drm_sched_entity_get_runtime(entity). 
> Nothing else would need to be exported and the implementation simply 
> locks entity->stats and returns the runtime. As long as the caller knows 
> they haven't destroyed the entity it is safe since entity holds a 
> reference to the stats object.
> 
> If rocket and v3d can use it that's a reasonable starting point for 
> adding common API. Three users would be even better than two though, 
> going by the long standing DRM tradition. :)

Considering commit 97804a133c68 (right commit this time), I believe that
Etnaviv could also benefit from it.

Best regards,
- Maíra

> 
> Regards,
> 
> Tvrtko
> 
>> [1] https://lore.kernel.org/dri-devel/3e00d8a9- 
>> b6c4-8202-4f2d-5a659c61d094@redhat.com/
>>
>> Best regards,
>> - Maíra
> 


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

end of thread, other threads:[~2026-11-05 11:08 UTC | newest]

Thread overview: 7+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2026-11-03 15:53 [PATCH v4] accel/rocket: Report NPU usage through fdinfo Sidong Yang
2026-11-05  3:22 ` Gyeyoung Baek
2026-11-05  6:58   ` Tomeu Vizoso
2026-11-05  9:22 ` Tvrtko Ursulin
2026-11-05 10:43   ` Maíra Canal
2026-11-05 11:04     ` Tvrtko Ursulin
2026-11-05 11:07       ` Maíra Canal

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

all inboxes | Powered by JetHome®