[PATCH] drm/panfrost: Show overall GPU usage stats through sysfs knob

Maíra Canal mcanal at igalia.com
Thu Apr 4 14:31:54 UTC 2024


On 4/4/24 11:00, Adrián Larumbe wrote:
> This changeset is heavily inspired by commit 509433d8146c ("drm/v3d: Expose
> the total GPU usage stats on sysfs"). The point is making broader GPU
> occupancy numbers available through the sysfs interface, so that for every
> job slot, its number of processed jobs and total processing time are
> displayed.

Shouldn't we make this sysfs interface a generic DRM interface?
Something that would be standard for all drivers and that we could
integrate into gputop in the future.

Best Regards,
- Maíra

> 
> Cc: Boris Brezillon <boris.brezillon at collabora.com>
> Cc: Christopher Healy <healych at amazon.com>
> Signed-off-by: Adrián Larumbe <adrian.larumbe at collabora.com>
> ---
>   drivers/gpu/drm/panfrost/panfrost_device.h |  5 +++
>   drivers/gpu/drm/panfrost/panfrost_drv.c    | 49 ++++++++++++++++++++--
>   drivers/gpu/drm/panfrost/panfrost_job.c    | 17 +++++++-
>   drivers/gpu/drm/panfrost/panfrost_job.h    |  3 ++
>   4 files changed, 68 insertions(+), 6 deletions(-)
> 
> diff --git a/drivers/gpu/drm/panfrost/panfrost_device.h b/drivers/gpu/drm/panfrost/panfrost_device.h
> index cffcb0ac7c11..1d343351c634 100644
> --- a/drivers/gpu/drm/panfrost/panfrost_device.h
> +++ b/drivers/gpu/drm/panfrost/panfrost_device.h
> @@ -169,6 +169,11 @@ struct panfrost_engine_usage {
>   	unsigned long long cycles[NUM_JOB_SLOTS];
>   };
>   
> +struct panfrost_slot_usage {
> +	u64 enabled_ns;
> +	u64 jobs_sent;
> +};
> +
>   struct panfrost_file_priv {
>   	struct panfrost_device *pfdev;
>   
> diff --git a/drivers/gpu/drm/panfrost/panfrost_drv.c b/drivers/gpu/drm/panfrost/panfrost_drv.c
> index ef9f6c0716d5..6afcde66270f 100644
> --- a/drivers/gpu/drm/panfrost/panfrost_drv.c
> +++ b/drivers/gpu/drm/panfrost/panfrost_drv.c
> @@ -8,6 +8,7 @@
>   #include <linux/pagemap.h>
>   #include <linux/platform_device.h>
>   #include <linux/pm_runtime.h>
> +#include <linux/sched/clock.h>
>   #include <drm/panfrost_drm.h>
>   #include <drm/drm_drv.h>
>   #include <drm/drm_ioctl.h>
> @@ -524,6 +525,10 @@ static const struct drm_ioctl_desc panfrost_drm_driver_ioctls[] = {
>   	PANFROST_IOCTL(MADVISE,		madvise,	DRM_RENDER_ALLOW),
>   };
>   
> +static const char * const engine_names[] = {
> +	"fragment", "vertex-tiler", "compute-only"
> +};
> +
>   static void panfrost_gpu_show_fdinfo(struct panfrost_device *pfdev,
>   				     struct panfrost_file_priv *panfrost_priv,
>   				     struct drm_printer *p)
> @@ -543,10 +548,6 @@ static void panfrost_gpu_show_fdinfo(struct panfrost_device *pfdev,
>   	 *   job spent on the GPU.
>   	 */
>   
> -	static const char * const engine_names[] = {
> -		"fragment", "vertex-tiler", "compute-only"
> -	};
> -
>   	BUILD_BUG_ON(ARRAY_SIZE(engine_names) != NUM_JOB_SLOTS);
>   
>   	for (i = 0; i < NUM_JOB_SLOTS - 1; i++) {
> @@ -716,8 +717,48 @@ static ssize_t profiling_store(struct device *dev,
>   
>   static DEVICE_ATTR_RW(profiling);
>   
> +static ssize_t
> +gpu_stats_show(struct device *dev, struct device_attribute *attr, char *buf)
> +{
> +	struct panfrost_device *pfdev = dev_get_drvdata(dev);
> +	struct panfrost_slot_usage stats;
> +	u64 timestamp = local_clock();
> +	ssize_t len = 0;
> +	unsigned int i;
> +
> +	BUILD_BUG_ON(ARRAY_SIZE(engine_names) != NUM_JOB_SLOTS);
> +
> +	len += sysfs_emit(buf, "queue        timestamp        jobs        runtime\n");
> +	len += sysfs_emit_at(buf, len, "-------------------------------------------------\n");
> +
> +	for (i = 0; i < NUM_JOB_SLOTS - 1; i++) {
> +
> +		stats = get_slot_stats(pfdev, i);
> +
> +		/*
> +		 * Each line will display the slot name, timestamp, the number
> +		 * of jobs handled by that engine and runtime, as shown below:
> +		 *
> +		 * queue        timestamp        jobs        runtime
> +		 * -------------------------------------------------
> +		 * fragment     12252943467507   638         1184747640
> +		 * vertex-tiler 12252943467507   636         121663838
> +		 *
> +		 */
> +		len += sysfs_emit_at(buf, len, "%-13s%-17llu%-12llu%llu\n",
> +				     engine_names[i],
> +				     timestamp,
> +				     stats.jobs_sent,
> +				     stats.enabled_ns);
> +	}
> +
> +	return len;
> +}
> +static DEVICE_ATTR_RO(gpu_stats);
> +
>   static struct attribute *panfrost_attrs[] = {
>   	&dev_attr_profiling.attr,
> +	&dev_attr_gpu_stats.attr,
>   	NULL,
>   };
>   
> diff --git a/drivers/gpu/drm/panfrost/panfrost_job.c b/drivers/gpu/drm/panfrost/panfrost_job.c
> index a61ef0af9a4e..4c779e6f4cb0 100644
> --- a/drivers/gpu/drm/panfrost/panfrost_job.c
> +++ b/drivers/gpu/drm/panfrost/panfrost_job.c
> @@ -31,6 +31,8 @@ struct panfrost_queue_state {
>   	struct drm_gpu_scheduler sched;
>   	u64 fence_context;
>   	u64 emit_seqno;
> +
> +	struct panfrost_slot_usage stats;
>   };
>   
>   struct panfrost_job_slot {
> @@ -160,15 +162,20 @@ panfrost_dequeue_job(struct panfrost_device *pfdev, int slot)
>   
>   	WARN_ON(!job);
>   	if (job->is_profiled) {
> +		u64 job_time = ktime_to_ns(ktime_sub(ktime_get(), job->start_time));
> +
>   		if (job->engine_usage) {
> -			job->engine_usage->elapsed_ns[slot] +=
> -				ktime_to_ns(ktime_sub(ktime_get(), job->start_time));
> +			job->engine_usage->elapsed_ns[slot] += job_time;
>   			job->engine_usage->cycles[slot] +=
>   				panfrost_cycle_counter_read(pfdev) - job->start_cycles;
>   		}
> +
>   		panfrost_cycle_counter_put(job->pfdev);
> +		pfdev->js->queue[slot].stats.enabled_ns += job_time;
>   	}
>   
> +	pfdev->js->queue[slot].stats.jobs_sent++;
> +
>   	pfdev->jobs[slot][0] = pfdev->jobs[slot][1];
>   	pfdev->jobs[slot][1] = NULL;
>   
> @@ -987,3 +994,9 @@ int panfrost_job_is_idle(struct panfrost_device *pfdev)
>   
>   	return true;
>   }
> +
> +struct panfrost_slot_usage
> +get_slot_stats(struct panfrost_device *pfdev, unsigned int slot)
> +{
> +	return pfdev->js->queue[slot].stats;
> +}
> diff --git a/drivers/gpu/drm/panfrost/panfrost_job.h b/drivers/gpu/drm/panfrost/panfrost_job.h
> index ec581b97852b..e9e2c9db0526 100644
> --- a/drivers/gpu/drm/panfrost/panfrost_job.h
> +++ b/drivers/gpu/drm/panfrost/panfrost_job.h
> @@ -50,4 +50,7 @@ void panfrost_job_enable_interrupts(struct panfrost_device *pfdev);
>   void panfrost_job_suspend_irq(struct panfrost_device *pfdev);
>   int panfrost_job_is_idle(struct panfrost_device *pfdev);
>   
> +struct panfrost_slot_usage
> +get_slot_stats(struct panfrost_device *pfdev, unsigned int slot);
> +
>   #endif
> 
> base-commit: 45c734fdd43db14444025910b4c59dd2b8be714a
> prerequisite-patch-id: 06ac397dd381984bfbff2a7661320c4f05470635


More information about the dri-devel mailing list