[Intel-gfx] [PATCH v5 04/20] drm/sched: Add dependency tracking

2021-08-05 Thread Daniel Vetter
Instead of just a callback we can just glue in the gem helpers that
panfrost, v3d and lima currently use. There's really not that many
ways to skin this cat.

v2/3: Rebased.

v4: Repaint this shed. The functions are now called _add_dependency()
and _add_implicit_dependency()

Reviewed-by: Boris Brezillon  (v3)
Reviewed-by: Steven Price  (v1)
Acked-by: Melissa Wen 
Signed-off-by: Daniel Vetter 
Cc: David Airlie 
Cc: Daniel Vetter 
Cc: Sumit Semwal 
Cc: "Christian König" 
Cc: Andrey Grodzovsky 
Cc: Lee Jones 
Cc: Nirmoy Das 
Cc: Boris Brezillon 
Cc: Luben Tuikov 
Cc: Alex Deucher 
Cc: linux-me...@vger.kernel.org
Cc: linaro-mm-...@lists.linaro.org
---
 drivers/gpu/drm/scheduler/sched_entity.c |  18 +++-
 drivers/gpu/drm/scheduler/sched_main.c   | 104 +++
 include/drm/gpu_scheduler.h  |  33 ++-
 3 files changed, 149 insertions(+), 6 deletions(-)

diff --git a/drivers/gpu/drm/scheduler/sched_entity.c 
b/drivers/gpu/drm/scheduler/sched_entity.c
index 89e3f6eaf519..381fbf462ea7 100644
--- a/drivers/gpu/drm/scheduler/sched_entity.c
+++ b/drivers/gpu/drm/scheduler/sched_entity.c
@@ -211,6 +211,19 @@ static void drm_sched_entity_kill_jobs_cb(struct dma_fence 
*f,
job->sched->ops->free_job(job);
 }
 
+static struct dma_fence *
+drm_sched_job_dependency(struct drm_sched_job *job,
+struct drm_sched_entity *entity)
+{
+   if (!xa_empty(&job->dependencies))
+   return xa_erase(&job->dependencies, job->last_dependency++);
+
+   if (job->sched->ops->dependency)
+   return job->sched->ops->dependency(job, entity);
+
+   return NULL;
+}
+
 /**
  * drm_sched_entity_kill_jobs - Make sure all remaining jobs are killed
  *
@@ -229,7 +242,7 @@ static void drm_sched_entity_kill_jobs(struct 
drm_sched_entity *entity)
struct drm_sched_fence *s_fence = job->s_fence;
 
/* Wait for all dependencies to avoid data corruptions */
-   while ((f = job->sched->ops->dependency(job, entity)))
+   while ((f = drm_sched_job_dependency(job, entity)))
dma_fence_wait(f, false);
 
drm_sched_fence_scheduled(s_fence);
@@ -419,7 +432,6 @@ static bool drm_sched_entity_add_dependency_cb(struct 
drm_sched_entity *entity)
  */
 struct drm_sched_job *drm_sched_entity_pop_job(struct drm_sched_entity *entity)
 {
-   struct drm_gpu_scheduler *sched = entity->rq->sched;
struct drm_sched_job *sched_job;
 
sched_job = to_drm_sched_job(spsc_queue_peek(&entity->job_queue));
@@ -427,7 +439,7 @@ struct drm_sched_job *drm_sched_entity_pop_job(struct 
drm_sched_entity *entity)
return NULL;
 
while ((entity->dependency =
-   sched->ops->dependency(sched_job, entity))) {
+   drm_sched_job_dependency(sched_job, entity))) {
trace_drm_sched_job_wait_dep(sched_job, entity->dependency);
 
if (drm_sched_entity_add_dependency_cb(entity))
diff --git a/drivers/gpu/drm/scheduler/sched_main.c 
b/drivers/gpu/drm/scheduler/sched_main.c
index 454cb6164bdc..f77456929139 100644
--- a/drivers/gpu/drm/scheduler/sched_main.c
+++ b/drivers/gpu/drm/scheduler/sched_main.c
@@ -603,6 +603,8 @@ int drm_sched_job_init(struct drm_sched_job *job,
 
INIT_LIST_HEAD(&job->list);
 
+   xa_init_flags(&job->dependencies, XA_FLAGS_ALLOC);
+
return 0;
 }
 EXPORT_SYMBOL(drm_sched_job_init);
@@ -637,6 +639,99 @@ void drm_sched_job_arm(struct drm_sched_job *job)
 }
 EXPORT_SYMBOL(drm_sched_job_arm);
 
+/**
+ * drm_sched_job_add_dependency - adds the fence as a job dependency
+ * @job: scheduler job to add the dependencies to
+ * @fence: the dma_fence to add to the list of dependencies.
+ *
+ * Note that @fence is consumed in both the success and error cases.
+ *
+ * Returns:
+ * 0 on success, or an error on failing to expand the array.
+ */
+int drm_sched_job_add_dependency(struct drm_sched_job *job,
+struct dma_fence *fence)
+{
+   struct dma_fence *entry;
+   unsigned long index;
+   u32 id = 0;
+   int ret;
+
+   if (!fence)
+   return 0;
+
+   /* Deduplicate if we already depend on a fence from the same context.
+* This lets the size of the array of deps scale with the number of
+* engines involved, rather than the number of BOs.
+*/
+   xa_for_each(&job->dependencies, index, entry) {
+   if (entry->context != fence->context)
+   continue;
+
+   if (dma_fence_is_later(fence, entry)) {
+   dma_fence_put(entry);
+   xa_store(&job->dependencies, index, fence, GFP_KERNEL);
+   } else {
+   dma_fence_put(fence);
+   }
+   return 0;
+   }
+
+   ret = xa_alloc(&job->dependencies, &id, fence, xa_limit_32b, 
GFP_KERNEL);
+   if (ret != 0)
+ 

Re: [Intel-gfx] [PATCH v5 04/20] drm/sched: Add dependency tracking

2021-08-05 Thread Christian König

Am 05.08.21 um 12:46 schrieb Daniel Vetter:

Instead of just a callback we can just glue in the gem helpers that
panfrost, v3d and lima currently use. There's really not that many
ways to skin this cat.

v2/3: Rebased.

v4: Repaint this shed. The functions are now called _add_dependency()
and _add_implicit_dependency()

Reviewed-by: Boris Brezillon  (v3)
Reviewed-by: Steven Price  (v1)
Acked-by: Melissa Wen 
Signed-off-by: Daniel Vetter 


Reviewed-by: Christian König 


Cc: David Airlie 
Cc: Daniel Vetter 
Cc: Sumit Semwal 
Cc: "Christian König" 
Cc: Andrey Grodzovsky 
Cc: Lee Jones 
Cc: Nirmoy Das 
Cc: Boris Brezillon 
Cc: Luben Tuikov 
Cc: Alex Deucher 
Cc: linux-me...@vger.kernel.org
Cc: linaro-mm-...@lists.linaro.org
---
  drivers/gpu/drm/scheduler/sched_entity.c |  18 +++-
  drivers/gpu/drm/scheduler/sched_main.c   | 104 +++
  include/drm/gpu_scheduler.h  |  33 ++-
  3 files changed, 149 insertions(+), 6 deletions(-)

diff --git a/drivers/gpu/drm/scheduler/sched_entity.c 
b/drivers/gpu/drm/scheduler/sched_entity.c
index 89e3f6eaf519..381fbf462ea7 100644
--- a/drivers/gpu/drm/scheduler/sched_entity.c
+++ b/drivers/gpu/drm/scheduler/sched_entity.c
@@ -211,6 +211,19 @@ static void drm_sched_entity_kill_jobs_cb(struct dma_fence 
*f,
job->sched->ops->free_job(job);
  }
  
+static struct dma_fence *

+drm_sched_job_dependency(struct drm_sched_job *job,
+struct drm_sched_entity *entity)
+{
+   if (!xa_empty(&job->dependencies))
+   return xa_erase(&job->dependencies, job->last_dependency++);
+
+   if (job->sched->ops->dependency)
+   return job->sched->ops->dependency(job, entity);
+
+   return NULL;
+}
+
  /**
   * drm_sched_entity_kill_jobs - Make sure all remaining jobs are killed
   *
@@ -229,7 +242,7 @@ static void drm_sched_entity_kill_jobs(struct 
drm_sched_entity *entity)
struct drm_sched_fence *s_fence = job->s_fence;
  
  		/* Wait for all dependencies to avoid data corruptions */

-   while ((f = job->sched->ops->dependency(job, entity)))
+   while ((f = drm_sched_job_dependency(job, entity)))
dma_fence_wait(f, false);
  
  		drm_sched_fence_scheduled(s_fence);

@@ -419,7 +432,6 @@ static bool drm_sched_entity_add_dependency_cb(struct 
drm_sched_entity *entity)
   */
  struct drm_sched_job *drm_sched_entity_pop_job(struct drm_sched_entity 
*entity)
  {
-   struct drm_gpu_scheduler *sched = entity->rq->sched;
struct drm_sched_job *sched_job;
  
  	sched_job = to_drm_sched_job(spsc_queue_peek(&entity->job_queue));

@@ -427,7 +439,7 @@ struct drm_sched_job *drm_sched_entity_pop_job(struct 
drm_sched_entity *entity)
return NULL;
  
  	while ((entity->dependency =

-   sched->ops->dependency(sched_job, entity))) {
+   drm_sched_job_dependency(sched_job, entity))) {
trace_drm_sched_job_wait_dep(sched_job, entity->dependency);
  
  		if (drm_sched_entity_add_dependency_cb(entity))

diff --git a/drivers/gpu/drm/scheduler/sched_main.c 
b/drivers/gpu/drm/scheduler/sched_main.c
index 454cb6164bdc..f77456929139 100644
--- a/drivers/gpu/drm/scheduler/sched_main.c
+++ b/drivers/gpu/drm/scheduler/sched_main.c
@@ -603,6 +603,8 @@ int drm_sched_job_init(struct drm_sched_job *job,
  
  	INIT_LIST_HEAD(&job->list);
  
+	xa_init_flags(&job->dependencies, XA_FLAGS_ALLOC);

+
return 0;
  }
  EXPORT_SYMBOL(drm_sched_job_init);
@@ -637,6 +639,99 @@ void drm_sched_job_arm(struct drm_sched_job *job)
  }
  EXPORT_SYMBOL(drm_sched_job_arm);
  
+/**

+ * drm_sched_job_add_dependency - adds the fence as a job dependency
+ * @job: scheduler job to add the dependencies to
+ * @fence: the dma_fence to add to the list of dependencies.
+ *
+ * Note that @fence is consumed in both the success and error cases.
+ *
+ * Returns:
+ * 0 on success, or an error on failing to expand the array.
+ */
+int drm_sched_job_add_dependency(struct drm_sched_job *job,
+struct dma_fence *fence)
+{
+   struct dma_fence *entry;
+   unsigned long index;
+   u32 id = 0;
+   int ret;
+
+   if (!fence)
+   return 0;
+
+   /* Deduplicate if we already depend on a fence from the same context.
+* This lets the size of the array of deps scale with the number of
+* engines involved, rather than the number of BOs.
+*/
+   xa_for_each(&job->dependencies, index, entry) {
+   if (entry->context != fence->context)
+   continue;
+
+   if (dma_fence_is_later(fence, entry)) {
+   dma_fence_put(entry);
+   xa_store(&job->dependencies, index, fence, GFP_KERNEL);
+   } else {
+   dma_fence_put(fence);
+   }
+   return 0;
+   }
+
+   ret = xa_alloc(&job->dependencies, &id, fen