diff mbox series

[5/8] drm/panthor: Factor out syncobj handling

Message ID 20240828172605.19176-6-mihail.atanassov@arm.com (mailing list archive)
State New, archived
Headers show
Series drm/panthor: Add user submission | expand

Commit Message

Mihail Atanassov Aug. 28, 2024, 5:26 p.m. UTC
From: Ketil Johnsen <ketil.johnsen@arm.com>

The code is needed both for the existing kernel submission path and for
implementing cross-group sync (XGS) queues which link between
drm_syncobj and the HW syncobj primitives.

Signed-off-by: Ketil Johnsen <ketil.johnsen@arm.com>
Signed-off-by: Mihail Atanassov <mihail.atanassov@arm.com>
---
 drivers/gpu/drm/panthor/Makefile          |   3 +-
 drivers/gpu/drm/panthor/panthor_sched.c   | 154 +++++---------------
 drivers/gpu/drm/panthor/panthor_syncobj.c | 167 ++++++++++++++++++++++
 drivers/gpu/drm/panthor/panthor_syncobj.h |  27 ++++
 4 files changed, 234 insertions(+), 117 deletions(-)
 create mode 100644 drivers/gpu/drm/panthor/panthor_syncobj.c
 create mode 100644 drivers/gpu/drm/panthor/panthor_syncobj.h
diff mbox series

Patch

diff --git a/drivers/gpu/drm/panthor/Makefile b/drivers/gpu/drm/panthor/Makefile
index 15294719b09c..0af27f33bfe2 100644
--- a/drivers/gpu/drm/panthor/Makefile
+++ b/drivers/gpu/drm/panthor/Makefile
@@ -9,6 +9,7 @@  panthor-y := \
 	panthor_gpu.o \
 	panthor_heap.o \
 	panthor_mmu.o \
-	panthor_sched.o
+	panthor_sched.o \
+	panthor_syncobj.o
 
 obj-$(CONFIG_DRM_PANTHOR) += panthor.o
diff --git a/drivers/gpu/drm/panthor/panthor_sched.c b/drivers/gpu/drm/panthor/panthor_sched.c
index 3b56526a4b97..f272aeee8a8f 100644
--- a/drivers/gpu/drm/panthor/panthor_sched.c
+++ b/drivers/gpu/drm/panthor/panthor_sched.c
@@ -31,6 +31,7 @@ 
 #include "panthor_mmu.h"
 #include "panthor_regs.h"
 #include "panthor_sched.h"
+#include "panthor_syncobj.h"
 
 /**
  * DOC: Scheduler
@@ -318,39 +319,6 @@  struct panthor_scheduler {
 	} reset;
 };
 
-/**
- * struct panthor_syncobj_32b - 32-bit FW synchronization object
- */
-struct panthor_syncobj_32b {
-	/** @seqno: Sequence number. */
-	u32 seqno;
-
-	/**
-	 * @status: Status.
-	 *
-	 * Not zero on failure.
-	 */
-	u32 status;
-};
-
-/**
- * struct panthor_syncobj_64b - 64-bit FW synchronization object
- */
-struct panthor_syncobj_64b {
-	/** @seqno: Sequence number. */
-	u64 seqno;
-
-	/**
-	 * @status: Status.
-	 *
-	 * Not zero on failure.
-	 */
-	u32 status;
-
-	/** @pad: MBZ. */
-	u32 pad;
-};
-
 /**
  * struct panthor_queue - Execution queue
  */
@@ -445,17 +413,8 @@  struct panthor_queue {
 		/** @sync64: True if this is a 64-bit sync object. */
 		bool sync64;
 
-		/** @bo: Buffer object holding the synchronization object. */
-		struct drm_gem_object *obj;
-
-		/** @offset: Offset of the synchronization object inside @bo. */
-		u64 offset;
-
-		/**
-		 * @kmap: Kernel mapping of the buffer object holding the
-		 * synchronization object.
-		 */
-		void *kmap;
+		/** @syncobj: Wrapper for the syncobj in memory */
+		struct panthor_syncobj *syncobj;
 	} syncwait;
 
 	/** @fence_ctx: Fence context fields. */
@@ -794,53 +753,6 @@  struct panthor_job {
 	struct dma_fence *done_fence;
 };
 
-static void
-panthor_queue_put_syncwait_obj(struct panthor_queue *queue)
-{
-	if (queue->syncwait.kmap) {
-		struct iosys_map map = IOSYS_MAP_INIT_VADDR(queue->syncwait.kmap);
-
-		drm_gem_vunmap_unlocked(queue->syncwait.obj, &map);
-		queue->syncwait.kmap = NULL;
-	}
-
-	drm_gem_object_put(queue->syncwait.obj);
-	queue->syncwait.obj = NULL;
-}
-
-static void *
-panthor_queue_get_syncwait_obj(struct panthor_group *group, struct panthor_queue *queue)
-{
-	struct panthor_device *ptdev = group->ptdev;
-	struct panthor_gem_object *bo;
-	struct iosys_map map;
-	int ret;
-
-	if (queue->syncwait.kmap)
-		return queue->syncwait.kmap + queue->syncwait.offset;
-
-	bo = panthor_vm_get_bo_for_va(group->vm,
-				      queue->syncwait.gpu_va,
-				      &queue->syncwait.offset);
-	if (drm_WARN_ON(&ptdev->base, IS_ERR_OR_NULL(bo)))
-		goto err_put_syncwait_obj;
-
-	queue->syncwait.obj = &bo->base.base;
-	ret = drm_gem_vmap_unlocked(queue->syncwait.obj, &map);
-	if (drm_WARN_ON(&ptdev->base, ret))
-		goto err_put_syncwait_obj;
-
-	queue->syncwait.kmap = map.vaddr;
-	if (drm_WARN_ON(&ptdev->base, !queue->syncwait.kmap))
-		goto err_put_syncwait_obj;
-
-	return queue->syncwait.kmap + queue->syncwait.offset;
-
-err_put_syncwait_obj:
-	panthor_queue_put_syncwait_obj(queue);
-	return NULL;
-}
-
 static void group_free_queue(struct panthor_group *group, struct panthor_queue *queue)
 {
 	if (IS_ERR_OR_NULL(queue))
@@ -852,7 +764,7 @@  static void group_free_queue(struct panthor_group *group, struct panthor_queue *
 	if (queue->scheduler.ops)
 		drm_sched_fini(&queue->scheduler);
 
-	panthor_queue_put_syncwait_obj(queue);
+	panthor_syncobj_release(queue->syncwait.syncobj);
 
 	if (queue->ringbuf_offset)
 		drm_vma_node_revoke(&queue->ringbuf->obj->vma_node, group->pfile->drm_file);
@@ -2065,7 +1977,6 @@  group_term_post_processing(struct panthor_group *group)
 	cookie = dma_fence_begin_signalling();
 	for (i = 0; i < group->queue_count; i++) {
 		struct panthor_queue *queue = group->queues[i];
-		struct panthor_syncobj_64b *syncobj;
 		int err;
 
 		if (group->fatal_queues & BIT(i))
@@ -2086,12 +1997,13 @@  group_term_post_processing(struct panthor_group *group)
 		}
 		spin_unlock(&queue->fence_ctx.lock);
 
-		if (!group->user_submit) {
+		if (!group->user_submit)
 			/* Manually update the syncobj seqno to unblock waiters. */
-			syncobj = group->syncobjs->kmap + (i * sizeof(*syncobj));
-			syncobj->status = ~0;
-			syncobj->seqno = atomic64_read(&queue->fence_ctx.seqno);
-		}
+			panthor_syncobj_ptr64_signal_with_error(
+				group->syncobjs->kmap + (i * PANTHOR_SYNCOBJ64_SIZE),
+				atomic64_read(&queue->fence_ctx.seqno),
+				~0);
+
 		sched_queue_work(group->ptdev->scheduler, sync_upd);
 	}
 	dma_fence_end_signalling(cookie);
@@ -2461,28 +2373,32 @@  static void tick_work(struct work_struct *work)
 static int panthor_queue_eval_syncwait(struct panthor_group *group, u8 queue_idx)
 {
 	struct panthor_queue *queue = group->queues[queue_idx];
-	union {
-		struct panthor_syncobj_64b sync64;
-		struct panthor_syncobj_32b sync32;
-	} *syncobj;
+	struct panthor_syncobj *syncobj;
 	bool result;
 	u64 value;
 
-	syncobj = panthor_queue_get_syncwait_obj(group, queue);
-	if (!syncobj)
-		return -EINVAL;
+	if (!queue->syncwait.syncobj) {
+		syncobj = panthor_syncobj_create(group->ptdev,
+						 group->vm,
+						 queue->syncwait.gpu_va,
+						 queue->syncwait.sync64);
+		if (IS_ERR_OR_NULL(syncobj))
+			return PTR_ERR(syncobj);
 
-	value = queue->syncwait.sync64 ?
-		syncobj->sync64.seqno :
-		syncobj->sync32.seqno;
+		queue->syncwait.syncobj = syncobj;
+	}
+
+	value = panthor_syncobj_get_value(queue->syncwait.syncobj);
 
 	if (queue->syncwait.gt)
 		result = value > queue->syncwait.ref;
 	else
 		result = value <= queue->syncwait.ref;
 
-	if (result)
-		panthor_queue_put_syncwait_obj(queue);
+	if (result) {
+		panthor_syncobj_release(queue->syncwait.syncobj);
+		queue->syncwait.syncobj = NULL;
+	}
 
 	return result;
 }
@@ -2887,16 +2803,22 @@  static void group_sync_upd_work(struct work_struct *work)
 	cookie = dma_fence_begin_signalling();
 	for (queue_idx = 0; queue_idx < group->queue_count; queue_idx++) {
 		struct panthor_queue *queue = group->queues[queue_idx];
-		struct panthor_syncobj_64b *syncobj;
+		void *syncobj;
 
 		if (!queue)
 			continue;
 
-		syncobj = group->syncobjs->kmap + (queue_idx * sizeof(*syncobj));
+		syncobj = group->syncobjs->kmap + (queue_idx * PANTHOR_SYNCOBJ64_SIZE);
 
 		spin_lock(&queue->fence_ctx.lock);
 		list_for_each_entry_safe(job, job_tmp, &queue->fence_ctx.in_flight_jobs, node) {
-			if (syncobj->seqno < job->done_fence->seqno)
+			u64 value;
+
+			if (!job->call_info.size)
+				continue;
+
+			value = panthor_syncobj_ptr64_get_value(syncobj);
+			if (value < job->done_fence->seqno)
 				break;
 
 			list_move_tail(&job->node, &done_jobs);
@@ -2928,7 +2850,7 @@  queue_run_job(struct drm_sched_job *sched_job)
 		       ptdev->csif_info.unpreserved_cs_reg_count;
 	u64 val_reg = addr_reg + 2;
 	u64 sync_addr = panthor_kernel_bo_gpuva(group->syncobjs) +
-			job->queue_idx * sizeof(struct panthor_syncobj_64b);
+			job->queue_idx * PANTHOR_SYNCOBJ64_SIZE;
 	u32 waitall_mask = GENMASK(sched->sb_slot_count - 1, 0);
 	struct dma_fence *done_fence;
 	int ret;
@@ -3289,7 +3211,7 @@  int panthor_group_create(struct panthor_file *pfile,
 	if (!group->user_submit) {
 		group->syncobjs = panthor_kernel_bo_create(ptdev, group->vm,
 							   group_args->queues.count *
-							   sizeof(struct panthor_syncobj_64b),
+							   PANTHOR_SYNCOBJ64_SIZE,
 							   DRM_PANTHOR_BO_NO_MMAP,
 							   DRM_PANTHOR_VM_BIND_OP_MAP_NOEXEC |
 							   DRM_PANTHOR_VM_BIND_OP_MAP_UNCACHED,
@@ -3304,7 +3226,7 @@  int panthor_group_create(struct panthor_file *pfile,
 			goto err_put_group;
 
 		memset(group->syncobjs->kmap, 0,
-		       group_args->queues.count * sizeof(struct panthor_syncobj_64b));
+		       group_args->queues.count * PANTHOR_SYNCOBJ64_SIZE);
 	}
 
 	for (i = 0; i < group_args->queues.count; i++) {
diff --git a/drivers/gpu/drm/panthor/panthor_syncobj.c b/drivers/gpu/drm/panthor/panthor_syncobj.c
new file mode 100644
index 000000000000..337f75bfa648
--- /dev/null
+++ b/drivers/gpu/drm/panthor/panthor_syncobj.c
@@ -0,0 +1,167 @@ 
+// SPDX-License-Identifier: GPL-2.0 or MIT
+/* Copyright 2024 ARM Limited. All rights reserved. */
+
+#include <linux/iosys-map.h>
+
+#include "panthor_device.h"
+#include "panthor_gem.h"
+#include "panthor_mmu.h"
+#include "panthor_syncobj.h"
+
+/**
+ * struct panthor_syncobj_32b - 32-bit FW synchronization object
+ */
+struct panthor_syncobj_32b {
+	/** @value: Value field. */
+	u32 value;
+
+	/**
+	 * @error: Error status.
+	 *
+	 * Not zero on failure.
+	 */
+	u32 error;
+};
+
+/**
+ * struct panthor_syncobj_64b - 64-bit FW synchronization object
+ */
+struct panthor_syncobj_64b {
+	/** @value: Value field. */
+	u64 value;
+
+	/**
+	 * @error: Error status.
+	 *
+	 * Not zero on failure.
+	 */
+	u32 error;
+
+	/** @pad: MBZ. */
+	u32 pad;
+};
+
+struct panthor_syncobj {
+	/** @bo: Buffer object holding the synchronization object. */
+	struct drm_gem_object *bo;
+
+	/** @offset: Offset of the synchronization object inside @bo. */
+	u64 offset;
+
+	/**
+	 * @kmap: Kernel mapping of the buffer object holding the
+	 * synchronization object.
+	 */
+	void *kmap;
+
+	/** @ptr: CPU ptr to synchronization object */
+	union {
+		struct panthor_syncobj_64b sync64;
+		struct panthor_syncobj_32b sync32;
+	} *ptr;
+
+	/** @sync64: true for 64-bit synchronization object, otherwise 32-bit */
+	bool sync64;
+};
+
+
+
+struct panthor_syncobj *panthor_syncobj_create(struct panthor_device *ptdev,
+					       struct panthor_vm *vm, u64 gpu_va,
+					       bool sync64)
+{
+	struct panthor_gem_object *bo;
+	struct iosys_map map;
+	struct panthor_syncobj *syncobj;
+	int err;
+
+	syncobj = kzalloc(sizeof(*syncobj), GFP_KERNEL);
+	if (!syncobj) {
+		err = -ENOMEM;
+		goto err;
+	}
+
+	bo = panthor_vm_get_bo_for_va(vm, gpu_va, &syncobj->offset);
+	if (drm_WARN_ON(&ptdev->base, IS_ERR_OR_NULL(bo))) {
+		err = -EINVAL;
+		goto err_free_syncobj;
+	}
+
+	syncobj->bo = &bo->base.base;
+
+	err = drm_gem_vmap_unlocked(syncobj->bo, &map);
+	if (drm_WARN_ON(&ptdev->base, err))
+		goto err_put_gem_object;
+
+	syncobj->kmap = map.vaddr;
+	syncobj->ptr = syncobj->kmap + syncobj->offset;
+	syncobj->sync64 = sync64;
+
+	return syncobj;
+
+err_put_gem_object:
+	drm_gem_object_put(syncobj->bo);
+err_free_syncobj:
+	kfree(syncobj);
+err:
+	return ERR_PTR(err);
+}
+
+void panthor_syncobj_release(struct panthor_syncobj *syncobj)
+{
+	if (syncobj) {
+		struct iosys_map map = IOSYS_MAP_INIT_VADDR(syncobj->kmap);
+
+		drm_gem_vunmap_unlocked(syncobj->bo, &map);
+		drm_gem_object_put(syncobj->bo);
+		kfree(syncobj);
+	}
+}
+
+u64 panthor_syncobj_get_value(struct panthor_syncobj *syncobj)
+{
+	return syncobj->sync64 ?
+		syncobj->ptr->sync64.value :
+		syncobj->ptr->sync32.value;
+}
+
+u32 panthor_syncobj_get_error(struct panthor_syncobj *syncobj)
+{
+	return syncobj->sync64 ?
+		syncobj->ptr->sync64.error :
+		syncobj->ptr->sync32.error;
+}
+
+void panthor_syncobj_signal(struct panthor_syncobj *syncobj, u64 value)
+{
+	if (syncobj->sync64)
+		syncobj->ptr->sync64.value = value;
+	else
+		syncobj->ptr->sync32.value = (u32)value;
+}
+
+void panthor_syncobj_signal_with_error(struct panthor_syncobj *syncobj, u64 value, u32 error)
+{
+	if (syncobj->sync64) {
+		syncobj->ptr->sync64.value = value;
+		syncobj->ptr->sync64.error = error;
+	} else {
+		syncobj->ptr->sync32.value = (u32)value;
+		syncobj->ptr->sync32.error = error;
+	}
+}
+
+u64 panthor_syncobj_ptr64_get_value(void *syncobj_ptr)
+{
+	struct panthor_syncobj_64b *syncobj = syncobj_ptr;
+
+	return syncobj->value;
+}
+
+void panthor_syncobj_ptr64_signal_with_error(void *syncobj_ptr, u64 value, u32 error)
+{
+	struct panthor_syncobj_64b *syncobj = syncobj_ptr;
+
+	syncobj->value = value;
+	syncobj->error = error;
+}
diff --git a/drivers/gpu/drm/panthor/panthor_syncobj.h b/drivers/gpu/drm/panthor/panthor_syncobj.h
new file mode 100644
index 000000000000..018cfc87cdaa
--- /dev/null
+++ b/drivers/gpu/drm/panthor/panthor_syncobj.h
@@ -0,0 +1,27 @@ 
+/* SPDX-License-Identifier: GPL-2.0 or MIT */
+/* Copyright 2024 ARM Limited. All rights reserved. */
+
+#ifndef __PANTHOR_SYNCOBJ_H__
+#define __PANTHOR_SYNCOBJ_H__
+
+#define PANTHOR_SYNCOBJ32_SIZE 8
+#define PANTHOR_SYNCOBJ64_SIZE 16
+
+struct panthor_syncobj;
+struct panthor_vm;
+
+struct panthor_syncobj *panthor_syncobj_create(struct panthor_device *ptdev,
+					       struct panthor_vm *vm, u64 gpu_va,
+					       bool sync64);
+void panthor_syncobj_release(struct panthor_syncobj *syncobj);
+
+u64 panthor_syncobj_get_value(struct panthor_syncobj *syncobj);
+u32 panthor_syncobj_get_error(struct panthor_syncobj *syncobj);
+
+void panthor_syncobj_signal(struct panthor_syncobj *syncobj, u64 value);
+void panthor_syncobj_signal_with_error(struct panthor_syncobj *syncobj, u64 value, u32 error);
+
+u64 panthor_syncobj_ptr64_get_value(void *syncobj_ptr);
+void panthor_syncobj_ptr64_signal_with_error(void *syncobj_ptr, u64 value, u32 error);
+
+#endif