public inbox for amd-gfx@lists.freedesktop.org
 help / color / mirror / Atom feed
From: "Christian König" <ckoenig.leichtzumerken-Re5JQEeQqe8AvxtiuMwx3w@public.gmane.org>
To: Andrey Grodzovsky
	<andrey.grodzovsky-5C7GfCeVMHo@public.gmane.org>,
	dri-devel-PD4FTy7X32lNgt0PjOBp9y5qC8QIuHrW@public.gmane.org,
	amd-gfx-PD4FTy7X32lNgt0PjOBp9y5qC8QIuHrW@public.gmane.org,
	eric-WhKQ6XTQaPysTnJN9+BGXg@public.gmane.org,
	etnaviv-PD4FTy7X32lNgt0PjOBp9y5qC8QIuHrW@public.gmane.org
Cc: Monk.Liu-5C7GfCeVMHo@public.gmane.org
Subject: Re: [PATCH 1/2] drm/sched: Refactor ring mirror list handling.
Date: Thu, 6 Dec 2018 19:33:53 +0100	[thread overview]
Message-ID: <ebd8c8bf-cd6d-b04f-b682-6cac4723ec40@gmail.com> (raw)
In-Reply-To: <1544118074-24910-1-git-send-email-andrey.grodzovsky-5C7GfCeVMHo@public.gmane.org>

Am 06.12.18 um 18:41 schrieb Andrey Grodzovsky:
> Decauple sched threads stop and start and ring mirror
> list handling from the policy of what to do about the
> guilty jobs.
> When stoppping the sched thread and detaching sched fences
> from non signaled HW fenes wait for all signaled HW fences
> to complete before rerunning the jobs.
>
> Suggested-by: Christian Koenig <Christian.Koenig@amd.com>
> Signed-off-by: Andrey Grodzovsky <andrey.grodzovsky@amd.com>

Just briefly skimmed over this, but it looks exactly like what I had in 
mind.

Need to give that a more detailed thought tomorrow,
Christian.

> ---
>   drivers/gpu/drm/amd/amdgpu/amdgpu_device.c | 17 +++---
>   drivers/gpu/drm/etnaviv/etnaviv_sched.c    |  8 +--
>   drivers/gpu/drm/scheduler/sched_main.c     | 86 +++++++++++++++++++-----------
>   drivers/gpu/drm/v3d/v3d_sched.c            | 11 ++--
>   include/drm/gpu_scheduler.h                | 10 ++--
>   5 files changed, 83 insertions(+), 49 deletions(-)
>
> diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_device.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_device.c
> index ef36cc5..42111d5 100644
> --- a/drivers/gpu/drm/amd/amdgpu/amdgpu_device.c
> +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_device.c
> @@ -3292,17 +3292,16 @@ static int amdgpu_device_pre_asic_reset(struct amdgpu_device *adev,
>   	/* block all schedulers and reset given job's ring */
>   	for (i = 0; i < AMDGPU_MAX_RINGS; ++i) {
>   		struct amdgpu_ring *ring = adev->rings[i];
> +		bool park_only = job && job->base.sched != &ring->sched;
>   
>   		if (!ring || !ring->sched.thread)
>   			continue;
>   
> -		kthread_park(ring->sched.thread);
> +		drm_sched_stop(&ring->sched, job ? &job->base : NULL, park_only);
>   
> -		if (job && job->base.sched != &ring->sched)
> +		if (park_only)
>   			continue;
>   
> -		drm_sched_hw_job_reset(&ring->sched, job ? &job->base : NULL);
> -
>   		/* after all hw jobs are reset, hw fence is meaningless, so force_completion */
>   		amdgpu_fence_driver_force_completion(ring);
>   	}
> @@ -3445,6 +3444,7 @@ static void amdgpu_device_post_asic_reset(struct amdgpu_device *adev,
>   					  struct amdgpu_job *job)
>   {
>   	int i;
> +	bool unpark_only;
>   
>   	for (i = 0; i < AMDGPU_MAX_RINGS; ++i) {
>   		struct amdgpu_ring *ring = adev->rings[i];
> @@ -3456,10 +3456,13 @@ static void amdgpu_device_post_asic_reset(struct amdgpu_device *adev,
>   		 * or all rings (in the case @job is NULL)
>   		 * after above amdgpu_reset accomplished
>   		 */
> -		if ((!job || job->base.sched == &ring->sched) && !adev->asic_reset_res)
> -			drm_sched_job_recovery(&ring->sched);
> +		unpark_only = (job && job->base.sched != &ring->sched) ||
> +			       adev->asic_reset_res;
> +
> +		if (!unpark_only)
> +			drm_sched_resubmit_jobs(&ring->sched);
>   
> -		kthread_unpark(ring->sched.thread);
> +		drm_sched_start(&ring->sched, unpark_only);
>   	}
>   
>   	if (!amdgpu_device_has_dc_support(adev)) {
> diff --git a/drivers/gpu/drm/etnaviv/etnaviv_sched.c b/drivers/gpu/drm/etnaviv/etnaviv_sched.c
> index 49a6763..fab3b51 100644
> --- a/drivers/gpu/drm/etnaviv/etnaviv_sched.c
> +++ b/drivers/gpu/drm/etnaviv/etnaviv_sched.c
> @@ -109,16 +109,16 @@ static void etnaviv_sched_timedout_job(struct drm_sched_job *sched_job)
>   	}
>   
>   	/* block scheduler */
> -	kthread_park(gpu->sched.thread);
> -	drm_sched_hw_job_reset(&gpu->sched, sched_job);
> +	drm_sched_stop(&gpu->sched, sched_job, false);
>   
>   	/* get the GPU back into the init state */
>   	etnaviv_core_dump(gpu);
>   	etnaviv_gpu_recover_hang(gpu);
>   
> +	drm_sched_resubmit_jobs(&gpu->sched);
> +
>   	/* restart scheduler after GPU is usable again */
> -	drm_sched_job_recovery(&gpu->sched);
> -	kthread_unpark(gpu->sched.thread);
> +	drm_sched_start(&gpu->sched);
>   }
>   
>   static void etnaviv_sched_free_job(struct drm_sched_job *sched_job)
> diff --git a/drivers/gpu/drm/scheduler/sched_main.c b/drivers/gpu/drm/scheduler/sched_main.c
> index dbb6906..8fb7f86 100644
> --- a/drivers/gpu/drm/scheduler/sched_main.c
> +++ b/drivers/gpu/drm/scheduler/sched_main.c
> @@ -60,8 +60,6 @@
>   
>   static void drm_sched_process_job(struct dma_fence *f, struct dma_fence_cb *cb);
>   
> -static void drm_sched_expel_job_unlocked(struct drm_sched_job *s_job);
> -
>   /**
>    * drm_sched_rq_init - initialize a given run queue struct
>    *
> @@ -342,13 +340,21 @@ static void drm_sched_job_timedout(struct work_struct *work)
>    * @bad: bad scheduler job
>    *
>    */
> -void drm_sched_hw_job_reset(struct drm_gpu_scheduler *sched, struct drm_sched_job *bad)
> +void drm_sched_stop(struct drm_gpu_scheduler *sched, struct drm_sched_job *bad,
> +		    bool park_only)
>   {
>   	struct drm_sched_job *s_job;
>   	struct drm_sched_entity *entity, *tmp;
>   	unsigned long flags;
> +	struct list_head wait_list;
>   	int i;
>   
> +	kthread_park(sched->thread);
> +	if (park_only)
> +		return;
> +
> +	INIT_LIST_HEAD(&wait_list);
> +
>   	spin_lock_irqsave(&sched->job_list_lock, flags);
>   	list_for_each_entry_reverse(s_job, &sched->ring_mirror_list, node) {
>   		if (s_job->s_fence->parent &&
> @@ -358,9 +364,24 @@ void drm_sched_hw_job_reset(struct drm_gpu_scheduler *sched, struct drm_sched_jo
>   			s_job->s_fence->parent = NULL;
>   			atomic_dec(&sched->hw_rq_count);
>   		}
> +		else {
> +			/* TODO Is it get/put neccessey here ? */
> +			dma_fence_get(&s_job->s_fence->finished);
> +			list_add(&s_job->finish_node, &wait_list);
> +		}
>   	}
>   	spin_unlock_irqrestore(&sched->job_list_lock, flags);
>   
> +	/*
> +	 * Verify all the signaled jobs in mirror list are removed from the ring
> +	 * We rely on the fact that any finish_work in progress will wait for this
> +	 * handler to complete before releasing all of the jobs we iterate.
> +	 */
> +	list_for_each_entry(s_job, &wait_list, finish_node) {
> +		dma_fence_wait(&s_job->s_fence->finished, false);
> +		dma_fence_put(&s_job->s_fence->finished);
> +	}
> +
>   	if (bad && bad->s_priority != DRM_SCHED_PRIORITY_KERNEL) {
>   		atomic_inc(&bad->karma);
>   		/* don't increase @bad's karma if it's from KERNEL RQ,
> @@ -385,7 +406,7 @@ void drm_sched_hw_job_reset(struct drm_gpu_scheduler *sched, struct drm_sched_jo
>   		}
>   	}
>   }
> -EXPORT_SYMBOL(drm_sched_hw_job_reset);
> +EXPORT_SYMBOL(drm_sched_stop);
>   
>   /**
>    * drm_sched_job_recovery - recover jobs after a reset
> @@ -393,14 +414,17 @@ EXPORT_SYMBOL(drm_sched_hw_job_reset);
>    * @sched: scheduler instance
>    *
>    */
> -void drm_sched_job_recovery(struct drm_gpu_scheduler *sched)
> +void drm_sched_start(struct drm_gpu_scheduler *sched, bool unpark_only)
>   {
>   	struct drm_sched_job *s_job, *tmp;
>   	bool found_guilty = false;
>   	unsigned long flags;
>   	int r;
>   
> -	spin_lock_irqsave(&sched->job_list_lock, flags);
> +	if (unpark_only)
> +		goto unpark;
> +
> +	spin_lock_irqsave(&sched->job_list_lock, flags);	
>   	list_for_each_entry_safe(s_job, tmp, &sched->ring_mirror_list, node) {
>   		struct drm_sched_fence *s_fence = s_job->s_fence;
>   		struct dma_fence *fence;
> @@ -414,12 +438,9 @@ void drm_sched_job_recovery(struct drm_gpu_scheduler *sched)
>   		if (found_guilty && s_job->s_fence->scheduled.context == guilty_context)
>   			dma_fence_set_error(&s_fence->finished, -ECANCELED);
>   
> -		spin_unlock_irqrestore(&sched->job_list_lock, flags);
> -		fence = sched->ops->run_job(s_job);
> -		atomic_inc(&sched->hw_rq_count);
>   
> +		fence = s_job->s_fence->parent;
>   		if (fence) {
> -			s_fence->parent = dma_fence_get(fence);
>   			r = dma_fence_add_callback(fence, &s_fence->cb,
>   						   drm_sched_process_job);
>   			if (r == -ENOENT)
> @@ -427,18 +448,35 @@ void drm_sched_job_recovery(struct drm_gpu_scheduler *sched)
>   			else if (r)
>   				DRM_ERROR("fence add callback failed (%d)\n",
>   					  r);
> -			dma_fence_put(fence);
> -		} else {
> -			if (s_fence->finished.error < 0)
> -				drm_sched_expel_job_unlocked(s_job);
> +		} else
>   			drm_sched_process_job(NULL, &s_fence->cb);
> -		}
> -		spin_lock_irqsave(&sched->job_list_lock, flags);
>   	}
> +
>   	drm_sched_start_timeout(sched);
>   	spin_unlock_irqrestore(&sched->job_list_lock, flags);
> +
> +unpark:
> +	kthread_unpark(sched->thread);
>   }
> -EXPORT_SYMBOL(drm_sched_job_recovery);
> +EXPORT_SYMBOL(drm_sched_start);
> +
> +/**
> + * drm_sched_resubmit_jobs - helper to relunch job from mirror ring list
> + *
> + * @sched: scheduler instance
> + *
> + */
> +void drm_sched_resubmit_jobs(struct drm_gpu_scheduler *sched)
> +{
> +	struct drm_sched_job *s_job, *tmp;
> +
> +	/*TODO DO we need spinlock here ? */
> +	list_for_each_entry_safe(s_job, tmp, &sched->ring_mirror_list, node) {
> +		s_job->s_fence->parent = sched->ops->run_job(s_job);
> +		atomic_inc(&sched->hw_rq_count);
> +	}
> +}
> +EXPORT_SYMBOL(drm_sched_resubmit_jobs);
>   
>   /**
>    * drm_sched_job_init - init a scheduler job
> @@ -634,26 +672,14 @@ static int drm_sched_main(void *param)
>   				DRM_ERROR("fence add callback failed (%d)\n",
>   					  r);
>   			dma_fence_put(fence);
> -		} else {
> -			if (s_fence->finished.error < 0)
> -				drm_sched_expel_job_unlocked(sched_job);
> +		} else
>   			drm_sched_process_job(NULL, &s_fence->cb);
> -		}
>   
>   		wake_up(&sched->job_scheduled);
>   	}
>   	return 0;
>   }
>   
> -static void drm_sched_expel_job_unlocked(struct drm_sched_job *s_job)
> -{
> -	struct drm_gpu_scheduler *sched = s_job->sched;
> -
> -	spin_lock(&sched->job_list_lock);
> -	list_del_init(&s_job->node);
> -	spin_unlock(&sched->job_list_lock);
> -}
> -
>   /**
>    * drm_sched_init - Init a gpu scheduler instance
>    *
> diff --git a/drivers/gpu/drm/v3d/v3d_sched.c b/drivers/gpu/drm/v3d/v3d_sched.c
> index 445b2ef..f99346a 100644
> --- a/drivers/gpu/drm/v3d/v3d_sched.c
> +++ b/drivers/gpu/drm/v3d/v3d_sched.c
> @@ -178,18 +178,19 @@ v3d_job_timedout(struct drm_sched_job *sched_job)
>   	for (q = 0; q < V3D_MAX_QUEUES; q++) {
>   		struct drm_gpu_scheduler *sched = &v3d->queue[q].sched;
>   
> -		kthread_park(sched->thread);
> -		drm_sched_hw_job_reset(sched, (sched_job->sched == sched ?
> -					       sched_job : NULL));
> +		drm_sched_stop(sched, (sched_job->sched == sched ?
> +					       sched_job : NULL), false);
>   	}
>   
>   	/* get the GPU back into the init state */
>   	v3d_reset(v3d);
>   
> +	for (q = 0; q < V3D_MAX_QUEUES; q++)
> +		drm_sched_resubmit_jobs(sched_job->sched);
> +
>   	/* Unblock schedulers and restart their jobs. */
>   	for (q = 0; q < V3D_MAX_QUEUES; q++) {
> -		drm_sched_job_recovery(&v3d->queue[q].sched);
> -		kthread_unpark(v3d->queue[q].sched.thread);
> +		drm_sched_start(&v3d->queue[q].sched, false);
>   	}
>   
>   	mutex_unlock(&v3d->reset_lock);
> diff --git a/include/drm/gpu_scheduler.h b/include/drm/gpu_scheduler.h
> index 47e1979..c94b592 100644
> --- a/include/drm/gpu_scheduler.h
> +++ b/include/drm/gpu_scheduler.h
> @@ -175,6 +175,7 @@ struct drm_sched_fence *to_drm_sched_fence(struct dma_fence *f);
>    *               finished to remove the job from the
>    *               @drm_gpu_scheduler.ring_mirror_list.
>    * @node: used to append this struct to the @drm_gpu_scheduler.ring_mirror_list.
> + * @finish_node: used in a list to wait on before resetting the scheduler
>    * @id: a unique id assigned to each job scheduled on the scheduler.
>    * @karma: increment on every hang caused by this job. If this exceeds the hang
>    *         limit of the scheduler then the job is marked guilty and will not
> @@ -193,6 +194,7 @@ struct drm_sched_job {
>   	struct dma_fence_cb		finish_cb;
>   	struct work_struct		finish_work;
>   	struct list_head		node;
> +	struct list_head		finish_node;
>   	uint64_t			id;
>   	atomic_t			karma;
>   	enum drm_sched_priority		s_priority;
> @@ -298,9 +300,11 @@ int drm_sched_job_init(struct drm_sched_job *job,
>   		       void *owner);
>   void drm_sched_job_cleanup(struct drm_sched_job *job);
>   void drm_sched_wakeup(struct drm_gpu_scheduler *sched);
> -void drm_sched_hw_job_reset(struct drm_gpu_scheduler *sched,
> -			    struct drm_sched_job *job);
> -void drm_sched_job_recovery(struct drm_gpu_scheduler *sched);
> +void drm_sched_stop(struct drm_gpu_scheduler *sched,
> +		    struct drm_sched_job *job,
> +		    bool park_only);
> +void drm_sched_start(struct drm_gpu_scheduler *sched, bool unpark_only);
> +void drm_sched_resubmit_jobs(struct drm_gpu_scheduler *sched);
>   bool drm_sched_dependency_optimized(struct dma_fence* fence,
>   				    struct drm_sched_entity *entity);
>   void drm_sched_fault(struct drm_gpu_scheduler *sched);

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

  parent reply	other threads:[~2018-12-06 18:33 UTC|newest]

Thread overview: 9+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2018-12-06 17:41 [PATCH 1/2] drm/sched: Refactor ring mirror list handling Andrey Grodzovsky
2018-12-06 17:41 ` [PATCH 2/2] drm/sched: Rework HW fence processing Andrey Grodzovsky
2018-12-06 18:12   ` Grodzovsky, Andrey
2018-12-07  3:18   ` Zhou, David(ChunMing)
2018-12-07  8:19     ` Christian König
2018-12-07 15:22       ` Grodzovsky, Andrey
2018-12-07 15:26         ` Koenig, Christian
     [not found] ` <1544118074-24910-1-git-send-email-andrey.grodzovsky-5C7GfCeVMHo@public.gmane.org>
2018-12-06 18:33   ` Christian König [this message]
     [not found]     ` <ebd8c8bf-cd6d-b04f-b682-6cac4723ec40-Re5JQEeQqe8AvxtiuMwx3w@public.gmane.org>
2018-12-06 21:27       ` [PATCH 1/2] drm/sched: Refactor ring mirror list handling Grodzovsky, Andrey

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=ebd8c8bf-cd6d-b04f-b682-6cac4723ec40@gmail.com \
    --to=ckoenig.leichtzumerken-re5jqeeqqe8avxtiumwx3w@public.gmane.org \
    --cc=Monk.Liu-5C7GfCeVMHo@public.gmane.org \
    --cc=amd-gfx-PD4FTy7X32lNgt0PjOBp9y5qC8QIuHrW@public.gmane.org \
    --cc=andrey.grodzovsky-5C7GfCeVMHo@public.gmane.org \
    --cc=christian.koenig-5C7GfCeVMHo@public.gmane.org \
    --cc=dri-devel-PD4FTy7X32lNgt0PjOBp9y5qC8QIuHrW@public.gmane.org \
    --cc=eric-WhKQ6XTQaPysTnJN9+BGXg@public.gmane.org \
    --cc=etnaviv-PD4FTy7X32lNgt0PjOBp9y5qC8QIuHrW@public.gmane.org \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox