Unnecessary, we know that the scheduler is already awake because it is 
processing this function.

[ml] WHAT ??? this wake_up operate on job_scheduled, like the one at the bottom of sched_main(), It is 
used to wake up the thread waiting in "sched_entity_fini" on this 
"sched->job_scheduled", I don't understand why not necessary
Ah! You not wake up the scheduler, but the waiter for the scheduler. In this case the order is incorrect, but let's focus on your other idea.

The simple way I can think of to remove the @skip param for run_job is that we introduce 
a new member "skip" in sched_job, and remove fake_signal() function,
So we always set "skip" in sched_job before run_job(), and in run_job() we skip 
the real ib_schedule if found job->skip == true,
Cool idea. How about setting the fence error code? Then we test if the error code is already set and skip calling run_job() altogether when it is.

my current approach won't do begin_job(), won't link job in mirror list, 
etc....  but above approach actually go through all steps
This is just for error recovery and doesn't need to be very efficient, but I see what you mean.

I think we should just keep one straight handling as much as possible and not to many corner cases. So your idea to skip the job when a flag is set sounds really good to me.

Regards,
Christian.

Am 26.10.2017 um 14:04 schrieb Liu, Monk:
The simple way I can think of to remove the @skip param for run_job is that we introduce 
a new member "skip" in sched_job, and remove fake_signal() function,
So we always set "skip" in sched_job before run_job(), and in run_job() we skip 
the real ib_schedule if found job->skip == true,

That way the skipping logic can be unified, but that satisfies the efficiency 
because:

my current approach won't do begin_job(), won't link job in mirror list, 
etc....  but above approach actually go through all steps

what do you think

BR Monk

-----Original Message-----
From: Liu, Monk
Sent: 2017年10月26日 19:07
To: Koenig, Christian <christian.koe...@amd.com>; amd-gfx@lists.freedesktop.org
Subject: RE: [PATCH 1/7] amd/scheduler:imple job skip feature(v2)

+       dma_fence_set_error(&s_fence->finished, -ECANCELED);
+
+       /* fake signaling the scheduled fence */
+       atomic_inc(&sched->hw_rq_count);
+       amd_sched_fence_scheduled(s_fence);
+       wake_up(&sched->job_scheduled);
Unnecessary, we know that the scheduler is already awake because it is 
processing this function.

[ml] WHAT ??? this wake_up operate on job_scheduled, like the one at the bottom of sched_main(), It is 
used to wake up the thread waiting in "sched_entity_fini" on this 
"sched->job_scheduled", I don't understand why not necessary


+                       guilty_context = s_job->s_fence->scheduled.context;
+               }
+ skip = (found_guilty && s_job->s_fence->scheduled.context ==
+guilty_context);
                spin_unlock(&sched->job_list_lock);
-               fence = sched->ops->run_job(s_job);
+               fence = sched->ops->run_job(s_job, skip);
As far as I can see you can use amd_sched_job_fake_signal() here as well, no 
need for the extra skip parameter to run_job().

[ML] no you still didn't get my point, in sched_main() we use fake_signal() because the 
job hadn't been linked in mirror list, so "job_finish()"
Cannot be invoked for those jobs,

But for job_recovery(), it go through mirror list and only focus on jobs from that list, 
thus all jobs must be handled by "job_finis()" callback,
So we need let those jobs go through the run_job() again, only except that it 
didn't need to submit to ring really , that way the job_finish() callback
Can handle that job safely and seemless

BR Monk

-----Original Message-----
From: Christian König [mailto:ckoenig.leichtzumer...@gmail.com]
Sent: 2017年10月26日 18:52
To: Liu, Monk <monk....@amd.com>; amd-gfx@lists.freedesktop.org
Subject: Re: [PATCH 1/7] amd/scheduler:imple job skip feature(v2)

Am 26.10.2017 um 12:30 schrieb Monk Liu:
jobs are skipped under two cases
1)when the entity behind this job marked guilty, the job poped from
this entity's queue will be dropped in sched_main loop.

2)in job_recovery(), skip the scheduling job if its karma detected
above limit, and also skipped as well for other jobs sharing the same
fence context. this approach is becuase job_recovery() cannot access
job->entity due to entity may already dead.

v2:
some logic fix

with this feature we can introduce new gpu recover feature.

Change-Id: I268b1c752c94e6ecd4ea78c87eb226ea3f52908a
Signed-off-by: Monk Liu <monk....@amd.com>
---
   drivers/gpu/drm/amd/amdgpu/amdgpu_job.c       |  9 +++--
   drivers/gpu/drm/amd/scheduler/gpu_scheduler.c | 54 
++++++++++++++++++++-------
   drivers/gpu/drm/amd/scheduler/gpu_scheduler.h |  2 +-
   3 files changed, 47 insertions(+), 18 deletions(-)

diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_job.c
b/drivers/gpu/drm/amd/amdgpu/amdgpu_job.c
index a58e3c5..f08fde9 100644
--- a/drivers/gpu/drm/amd/amdgpu/amdgpu_job.c
+++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_job.c
@@ -177,7 +177,7 @@ static struct dma_fence *amdgpu_job_dependency(struct 
amd_sched_job *sched_job)
        return fence;
   }
-static struct dma_fence *amdgpu_job_run(struct amd_sched_job
*sched_job)
+static struct dma_fence *amdgpu_job_run(struct amd_sched_job
+*sched_job, bool skip)
   {
        struct dma_fence *fence = NULL;
        struct amdgpu_device *adev;
@@ -194,10 +194,11 @@ static struct dma_fence *amdgpu_job_run(struct 
amd_sched_job *sched_job)
        BUG_ON(amdgpu_sync_peek_fence(&job->sync, NULL));
trace_amdgpu_sched_run_job(job);
-       /* skip ib schedule when vram is lost */
-       if (job->vram_lost_counter != atomic_read(&adev->vram_lost_counter)) {
+
+       if (skip || job->vram_lost_counter != 
atomic_read(&adev->vram_lost_counter)) {
+               /* skip ib schedule if looks needed, and set error */
                dma_fence_set_error(&job->base.s_fence->finished, -ECANCELED);
-               DRM_ERROR("Skip scheduling IBs!\n");
+               DRM_INFO("Skip scheduling IBs!\n");
        } else {
                r = amdgpu_ib_schedule(job->ring, job->num_ibs, job->ibs, job,
                                       &fence);
diff --git a/drivers/gpu/drm/amd/scheduler/gpu_scheduler.c
b/drivers/gpu/drm/amd/scheduler/gpu_scheduler.c
index 9cbeade..995661e 100644
--- a/drivers/gpu/drm/amd/scheduler/gpu_scheduler.c
+++ b/drivers/gpu/drm/amd/scheduler/gpu_scheduler.c
@@ -330,6 +330,28 @@ static bool amd_sched_entity_add_dependency_cb(struct 
amd_sched_entity *entity)
        return false;
   }
+static void amd_sched_job_fake_signal(struct amd_sched_job *job) {
+       struct amd_sched_fence *s_fence = job->s_fence;
+       struct amd_gpu_scheduler *sched = job->sched;
+       struct amd_sched_entity *entity = job->s_entity;
+
+       dma_fence_set_error(&s_fence->finished, -ECANCELED);
+
+       /* fake signaling the scheduled fence */
+       atomic_inc(&sched->hw_rq_count);
+       amd_sched_fence_scheduled(s_fence);
+       wake_up(&sched->job_scheduled);
Unnecessary, we know that the scheduler is already awake because it is 
processing this function.

+
+       /* fake signaling the finished fence */
+       job->s_entity = NULL;
+       spsc_queue_pop(&entity->job_queue);
That code isn't up to date any more, Andrey removed job->s_entity yesterday.

Please rebase on amd-staging-drm-next before resending.

+
+       amd_sched_process_job(NULL, &s_fence->cb);
+       dma_fence_put(&s_fence->finished);
+       sched->ops->free_job(job);
+}
+
   static struct amd_sched_job *
   amd_sched_entity_pop_job(struct amd_sched_entity *entity)
   {
@@ -344,6 +366,11 @@ amd_sched_entity_pop_job(struct amd_sched_entity *entity)
                if (amd_sched_entity_add_dependency_cb(entity))
                        return NULL;
+ if (entity->guilty && atomic_read(entity->guilty)) {
+               amd_sched_job_fake_signal(sched_job);
+               return NULL;
+       }
+
Better move this after spsc_queue_pop below and remove the extra spsc_queue_pop 
from amd_sched_job_fake_signal.

        sched_job->s_entity = NULL;
        spsc_queue_pop(&entity->job_queue);
        return sched_job;
@@ -441,13 +468,6 @@ static void amd_sched_job_timedout(struct work_struct 
*work)
        job->sched->ops->timedout_job(job);
   }
-static void amd_sched_set_guilty(struct amd_sched_job *s_job) -{
-       if (atomic_inc_return(&s_job->karma) > s_job->sched->hang_limit)
-               if (s_job->s_entity->guilty)
-                       atomic_set(s_job->s_entity->guilty, 1);
-}
-
   void amd_sched_hw_job_reset(struct amd_gpu_scheduler *sched, struct 
amd_sched_job *bad)
   {
        struct amd_sched_job *s_job;
@@ -466,7 +486,7 @@ void amd_sched_hw_job_reset(struct amd_gpu_scheduler 
*sched, struct amd_sched_jo
        }
        spin_unlock(&sched->job_list_lock);
- if (bad) {
+       if (bad && atomic_inc_return(&bad->karma) > bad->sched->hang_limit)
+{
                bool found = false;
for (i = AMD_SCHED_PRIORITY_MIN; i < AMD_SCHED_PRIORITY_MAX; i++ )
{ @@ -476,7 +496,8 @@ void amd_sched_hw_job_reset(struct amd_gpu_scheduler 
*sched, struct amd_sched_jo
                        list_for_each_entry_safe(entity, tmp, &rq->entities, 
list) {
                                if (bad->s_fence->scheduled.context == 
entity->fence_context) {
                                        found = true;
-                                       amd_sched_set_guilty(bad);
+                                       if (entity->guilty)
+                                               atomic_set(entity->guilty, 1);
                                        break;
                                }
                        }
@@ -499,6 +520,7 @@ void amd_sched_job_kickout(struct amd_sched_job *s_job)
   void amd_sched_job_recovery(struct amd_gpu_scheduler *sched)
   {
        struct amd_sched_job *s_job, *tmp;
+       bool found_guilty = false;
        int r;
spin_lock(&sched->job_list_lock);
@@ -510,9 +532,17 @@ void amd_sched_job_recovery(struct amd_gpu_scheduler 
*sched)
        list_for_each_entry_safe(s_job, tmp, &sched->ring_mirror_list, node) {
                struct amd_sched_fence *s_fence = s_job->s_fence;
                struct dma_fence *fence;
+               bool skip;
+               uint64_t guilty_context;
+
+               if (!found_guilty && atomic_read(&s_job->karma) > 
sched->hang_limit) {
+                       found_guilty = true;
+                       guilty_context = s_job->s_fence->scheduled.context;
+               }
+ skip = (found_guilty && s_job->s_fence->scheduled.context ==
+guilty_context);
                spin_unlock(&sched->job_list_lock);
-               fence = sched->ops->run_job(s_job);
+               fence = sched->ops->run_job(s_job, skip);
As far as I can see you can use amd_sched_job_fake_signal() here as well, no 
need for the extra skip parameter to run_job().

Regards,
Christian.

                atomic_inc(&sched->hw_rq_count);
                if (fence) {
                        s_fence->parent = dma_fence_get(fence); @@ -525,7 
+555,6 @@ void
amd_sched_job_recovery(struct amd_gpu_scheduler *sched)
                                          r);
                        dma_fence_put(fence);
                } else {
-                       DRM_ERROR("Failed to run job!\n");
                        amd_sched_process_job(NULL, &s_fence->cb);
                }
                spin_lock(&sched->job_list_lock);
@@ -650,7 +679,7 @@ static int amd_sched_main(void *param)
                atomic_inc(&sched->hw_rq_count);
                amd_sched_job_begin(sched_job);
- fence = sched->ops->run_job(sched_job);
+               fence = sched->ops->run_job(sched_job, false);
                amd_sched_fence_scheduled(s_fence);
if (fence) {
@@ -664,7 +693,6 @@ static int amd_sched_main(void *param)
                                          r);
                        dma_fence_put(fence);
                } else {
-                       DRM_ERROR("Failed to run job!\n");
                        amd_sched_process_job(NULL, &s_fence->cb);
                }
diff --git a/drivers/gpu/drm/amd/scheduler/gpu_scheduler.h
b/drivers/gpu/drm/amd/scheduler/gpu_scheduler.h
index f9e3a83..a8e5a7d 100644
--- a/drivers/gpu/drm/amd/scheduler/gpu_scheduler.h
+++ b/drivers/gpu/drm/amd/scheduler/gpu_scheduler.h
@@ -126,7 +126,7 @@ static inline bool amd_sched_invalidate_job(struct 
amd_sched_job *s_job, int thr
   */
   struct amd_sched_backend_ops {
        struct dma_fence *(*dependency)(struct amd_sched_job *sched_job);
-       struct dma_fence *(*run_job)(struct amd_sched_job *sched_job);
+       struct dma_fence *(*run_job)(struct amd_sched_job *sched_job, bool
+skip);
        void (*timedout_job)(struct amd_sched_job *sched_job);
        void (*free_job)(struct amd_sched_job *sched_job);
   };


_______________________________________________
amd-gfx mailing list
amd-gfx@lists.freedesktop.org
https://lists.freedesktop.org/mailman/listinfo/amd-gfx

Reply via email to