* [PATCH 1/2] drm/amdgpu: use a dummy owner for sysfs triggered cleaner shaders v2
@ 2025-04-02 14:02 Christian König
2025-04-02 14:02 ` [PATCH 2/2] drm/amdgpu: cleanup amdgpu_vm_flush v2 Christian König
2025-04-03 3:15 ` [PATCH 1/2] drm/amdgpu: use a dummy owner for sysfs triggered cleaner shaders v2 SRINIVASAN SHANMUGAM
0 siblings, 2 replies; 6+ messages in thread
From: Christian König @ 2025-04-02 14:02 UTC (permalink / raw)
To: srinivasan.shanmugam, amd-gfx
Otherwise triggering sysfs multiple times without other submissions in
between only runs the shader once.
v2: add some comment
Signed-off-by: Christian König <christian.koenig@amd.com>
---
drivers/gpu/drm/amd/amdgpu/amdgpu_gfx.c | 14 +++++++++++---
1 file changed, 11 insertions(+), 3 deletions(-)
diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_gfx.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_gfx.c
index f64675b2ab75..9a24be43e035 100644
--- a/drivers/gpu/drm/amd/amdgpu/amdgpu_gfx.c
+++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_gfx.c
@@ -1439,9 +1439,11 @@ static int amdgpu_gfx_run_cleaner_shader_job(struct amdgpu_ring *ring)
struct amdgpu_device *adev = ring->adev;
struct drm_gpu_scheduler *sched = &ring->sched;
struct drm_sched_entity entity;
+ static atomic_t counter;
struct dma_fence *f;
struct amdgpu_job *job;
struct amdgpu_ib *ib;
+ void * owner;
int i, r;
/* Initialize the scheduler entity */
@@ -1452,9 +1454,15 @@ static int amdgpu_gfx_run_cleaner_shader_job(struct amdgpu_ring *ring)
goto err;
}
- r = amdgpu_job_alloc_with_ib(ring->adev, &entity, NULL,
- 64, 0,
- &job);
+ /*
+ * Use some unique dummy value as the owner to make sure we execute
+ * the cleaner shader on each submission. The value just need to change
+ * for each submission and is otherwise meaningless.
+ */
+ owner = (unsigned long)atomic_inc_return(&counter),
+
+ r = amdgpu_job_alloc_with_ib(ring->adev, &entity, owner,
+ 64, 0, &job);
if (r)
goto err;
--
2.34.1
^ permalink raw reply related [flat|nested] 6+ messages in thread
* [PATCH 2/2] drm/amdgpu: cleanup amdgpu_vm_flush v2
2025-04-02 14:02 [PATCH 1/2] drm/amdgpu: use a dummy owner for sysfs triggered cleaner shaders v2 Christian König
@ 2025-04-02 14:02 ` Christian König
2025-04-04 5:15 ` SRINIVASAN SHANMUGAM
2025-04-03 3:15 ` [PATCH 1/2] drm/amdgpu: use a dummy owner for sysfs triggered cleaner shaders v2 SRINIVASAN SHANMUGAM
1 sibling, 1 reply; 6+ messages in thread
From: Christian König @ 2025-04-02 14:02 UTC (permalink / raw)
To: srinivasan.shanmugam, amd-gfx
This reverts commit c2cc3648ba517a6c270500b5447d5a1efdad5936. Turned out
that this has some negative consequences for some workloads. Instead check
if the cleaner shader should run directly.
While at it remove amdgpu_vm_need_pipeline_sync(), we also check again
if the VMID has seen a GPU reset since last use and the gds switch
setiing can be handled more simply as well.
Also remove some duplicate checks and re-order and document the code.
v2: restructure the while function
Signed-off-by: Christian König <christian.koenig@amd.com>
---
drivers/gpu/drm/amd/amdgpu/amdgpu_ib.c | 3 +-
drivers/gpu/drm/amd/amdgpu/amdgpu_vm.c | 89 +++++++++-----------------
drivers/gpu/drm/amd/amdgpu/amdgpu_vm.h | 5 +-
3 files changed, 34 insertions(+), 63 deletions(-)
diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_ib.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_ib.c
index 802743efa3b3..ff2ca984279a 100644
--- a/drivers/gpu/drm/amd/amdgpu/amdgpu_ib.c
+++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_ib.c
@@ -191,8 +191,7 @@ int amdgpu_ib_schedule(struct amdgpu_ring *ring, unsigned int num_ibs,
need_ctx_switch = ring->current_ctx != fence_ctx;
if (ring->funcs->emit_pipeline_sync && job &&
((tmp = amdgpu_sync_get_fence(&job->explicit_sync)) ||
- need_ctx_switch || amdgpu_vm_need_pipeline_sync(ring, job))) {
-
+ (amdgpu_sriov_vf(adev) && need_ctx_switch))) {
need_pipe_sync = true;
if (tmp)
diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_vm.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_vm.c
index b5ddfcbbc9fc..d7a4cb07defc 100644
--- a/drivers/gpu/drm/amd/amdgpu/amdgpu_vm.c
+++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_vm.c
@@ -596,37 +596,6 @@ void amdgpu_vm_check_compute_bug(struct amdgpu_device *adev)
}
}
-/**
- * amdgpu_vm_need_pipeline_sync - Check if pipe sync is needed for job.
- *
- * @ring: ring on which the job will be submitted
- * @job: job to submit
- *
- * Returns:
- * True if sync is needed.
- */
-bool amdgpu_vm_need_pipeline_sync(struct amdgpu_ring *ring,
- struct amdgpu_job *job)
-{
- struct amdgpu_device *adev = ring->adev;
- unsigned vmhub = ring->vm_hub;
- struct amdgpu_vmid_mgr *id_mgr = &adev->vm_manager.id_mgr[vmhub];
-
- if (job->vmid == 0)
- return false;
-
- if (job->vm_needs_flush || ring->has_compute_vm_bug)
- return true;
-
- if (ring->funcs->emit_gds_switch && job->gds_switch_needed)
- return true;
-
- if (amdgpu_vmid_had_gpu_reset(adev, &id_mgr->ids[job->vmid]))
- return true;
-
- return false;
-}
-
/**
* amdgpu_vm_flush - hardware flush the vm
*
@@ -647,29 +616,31 @@ int amdgpu_vm_flush(struct amdgpu_ring *ring, struct amdgpu_job *job,
unsigned vmhub = ring->vm_hub;
struct amdgpu_vmid_mgr *id_mgr = &adev->vm_manager.id_mgr[vmhub];
struct amdgpu_vmid *id = &id_mgr->ids[job->vmid];
- bool spm_update_needed = job->spm_update_needed;
- bool gds_switch_needed = ring->funcs->emit_gds_switch &&
- job->gds_switch_needed;
- bool vm_flush_needed = job->vm_needs_flush;
- bool cleaner_shader_needed = false;
- bool pasid_mapping_needed = false;
- struct dma_fence *fence = NULL;
+ bool gds_switch_needed, vm_flush_needed, spm_update_needed,
+ cleaner_shader_needed, pasid_mapping_needed;
+ struct dma_fence *fence;
unsigned int patch;
int r;
+ /* First of all figure out what needs to be done */
if (amdgpu_vmid_had_gpu_reset(adev, id)) {
+ need_pipe_sync = true;
gds_switch_needed = true;
vm_flush_needed = true;
pasid_mapping_needed = true;
spm_update_needed = true;
+ } else {
+ gds_switch_needed = job->gds_switch_needed;
+ vm_flush_needed = job->vm_needs_flush;
+ mutex_lock(&id_mgr->lock);
+ if (id->pasid != job->pasid || !id->pasid_mapping ||
+ !dma_fence_is_signaled(id->pasid_mapping))
+ pasid_mapping_needed = true;
+ mutex_unlock(&id_mgr->lock);
+ spm_update_needed = job->spm_update_needed;
+ need_pipe_sync |= vm_flush_needed && ring->has_compute_vm_bug;
}
- mutex_lock(&id_mgr->lock);
- if (id->pasid != job->pasid || !id->pasid_mapping ||
- !dma_fence_is_signaled(id->pasid_mapping))
- pasid_mapping_needed = true;
- mutex_unlock(&id_mgr->lock);
-
gds_switch_needed &= !!ring->funcs->emit_gds_switch;
vm_flush_needed &= !!ring->funcs->emit_vm_flush &&
job->vm_pd_addr != AMDGPU_BO_INVALID_OFFSET;
@@ -684,12 +655,13 @@ int amdgpu_vm_flush(struct amdgpu_ring *ring, struct amdgpu_job *job,
!cleaner_shader_needed)
return 0;
+ /* Then aktually prepare the submission frame */
amdgpu_ring_ib_begin(ring);
if (ring->funcs->init_cond_exec)
patch = amdgpu_ring_init_cond_exec(ring,
ring->cond_exe_gpu_addr);
- if (need_pipe_sync)
+ if (need_pipe_sync || cleaner_shader_needed || gds_switch_needed)
amdgpu_ring_emit_pipeline_sync(ring);
if (cleaner_shader_needed)
@@ -706,20 +678,31 @@ int amdgpu_vm_flush(struct amdgpu_ring *ring, struct amdgpu_job *job,
if (spm_update_needed && adev->gfx.rlc.funcs->update_spm_vmid)
adev->gfx.rlc.funcs->update_spm_vmid(adev, ring, job->vmid);
- if (ring->funcs->emit_gds_switch &&
- gds_switch_needed) {
+ if (gds_switch_needed)
amdgpu_ring_emit_gds_switch(ring, job->vmid, job->gds_base,
job->gds_size, job->gws_base,
job->gws_size, job->oa_base,
job->oa_size);
- }
if (vm_flush_needed || pasid_mapping_needed || cleaner_shader_needed) {
r = amdgpu_fence_emit(ring, &fence, NULL, 0);
if (r)
return r;
+ } else {
+ fence = NULL;
+ }
+
+ amdgpu_ring_patch_cond_exec(ring, patch);
+
+ /* the double SWITCH_BUFFER here *cannot* be skipped by COND_EXEC */
+ if (ring->funcs->emit_switch_buffer) {
+ amdgpu_ring_emit_switch_buffer(ring);
+ amdgpu_ring_emit_switch_buffer(ring);
}
+ amdgpu_ring_ib_end(ring);
+
+ /* And finally remember what the ring has executed */
if (vm_flush_needed) {
mutex_lock(&id_mgr->lock);
dma_fence_put(id->last_flush);
@@ -749,16 +732,6 @@ int amdgpu_vm_flush(struct amdgpu_ring *ring, struct amdgpu_job *job,
mutex_unlock(&adev->enforce_isolation_mutex);
}
dma_fence_put(fence);
-
- amdgpu_ring_patch_cond_exec(ring, patch);
-
- /* the double SWITCH_BUFFER here *cannot* be skipped by COND_EXEC */
- if (ring->funcs->emit_switch_buffer) {
- amdgpu_ring_emit_switch_buffer(ring);
- amdgpu_ring_emit_switch_buffer(ring);
- }
-
- amdgpu_ring_ib_end(ring);
return 0;
}
diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_vm.h b/drivers/gpu/drm/amd/amdgpu/amdgpu_vm.h
index daa2f9b33620..e9ecdb96bafa 100644
--- a/drivers/gpu/drm/amd/amdgpu/amdgpu_vm.h
+++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_vm.h
@@ -493,7 +493,8 @@ int amdgpu_vm_validate(struct amdgpu_device *adev, struct amdgpu_vm *vm,
struct ww_acquire_ctx *ticket,
int (*callback)(void *p, struct amdgpu_bo *bo),
void *param);
-int amdgpu_vm_flush(struct amdgpu_ring *ring, struct amdgpu_job *job, bool need_pipe_sync);
+int amdgpu_vm_flush(struct amdgpu_ring *ring, struct amdgpu_job *job,
+ bool need_pipe_sync);
int amdgpu_vm_update_pdes(struct amdgpu_device *adev,
struct amdgpu_vm *vm, bool immediate);
int amdgpu_vm_clear_freed(struct amdgpu_device *adev,
@@ -550,8 +551,6 @@ void amdgpu_vm_adjust_size(struct amdgpu_device *adev, uint32_t min_vm_size,
uint32_t fragment_size_default, unsigned max_level,
unsigned max_bits);
int amdgpu_vm_ioctl(struct drm_device *dev, void *data, struct drm_file *filp);
-bool amdgpu_vm_need_pipeline_sync(struct amdgpu_ring *ring,
- struct amdgpu_job *job);
void amdgpu_vm_check_compute_bug(struct amdgpu_device *adev);
struct amdgpu_task_info *
--
2.34.1
^ permalink raw reply related [flat|nested] 6+ messages in thread
* Re: [PATCH 1/2] drm/amdgpu: use a dummy owner for sysfs triggered cleaner shaders v2
2025-04-02 14:02 [PATCH 1/2] drm/amdgpu: use a dummy owner for sysfs triggered cleaner shaders v2 Christian König
2025-04-02 14:02 ` [PATCH 2/2] drm/amdgpu: cleanup amdgpu_vm_flush v2 Christian König
@ 2025-04-03 3:15 ` SRINIVASAN SHANMUGAM
2025-04-03 9:10 ` Christian König
1 sibling, 1 reply; 6+ messages in thread
From: SRINIVASAN SHANMUGAM @ 2025-04-03 3:15 UTC (permalink / raw)
To: Christian König, amd-gfx
On 4/2/2025 7:32 PM, Christian König wrote:
> Otherwise triggering sysfs multiple times without other submissions in
> between only runs the shader once.
>
> v2: add some comment
>
> Signed-off-by: Christian König <christian.koenig@amd.com>
> ---
> drivers/gpu/drm/amd/amdgpu/amdgpu_gfx.c | 14 +++++++++++---
> 1 file changed, 11 insertions(+), 3 deletions(-)
>
> diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_gfx.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_gfx.c
> index f64675b2ab75..9a24be43e035 100644
> --- a/drivers/gpu/drm/amd/amdgpu/amdgpu_gfx.c
> +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_gfx.c
> @@ -1439,9 +1439,11 @@ static int amdgpu_gfx_run_cleaner_shader_job(struct amdgpu_ring *ring)
> struct amdgpu_device *adev = ring->adev;
> struct drm_gpu_scheduler *sched = &ring->sched;
> struct drm_sched_entity entity;
> + static atomic_t counter;
> struct dma_fence *f;
> struct amdgpu_job *job;
> struct amdgpu_ib *ib;
> + void * owner;
> int i, r;
>
> /* Initialize the scheduler entity */
> @@ -1452,9 +1454,15 @@ static int amdgpu_gfx_run_cleaner_shader_job(struct amdgpu_ring *ring)
> goto err;
> }
>
> - r = amdgpu_job_alloc_with_ib(ring->adev, &entity, NULL,
> - 64, 0,
> - &job);
> + /*
> + * Use some unique dummy value as the owner to make sure we execute
> + * the cleaner shader on each submission. The value just need to change
> + * for each submission and is otherwise meaningless.
> + */
> + owner = (unsigned long)atomic_inc_return(&counter),
Should this "atomic_inc_return()" needs to be casted to (void*), as it
is return type is int?
Regards,
Srini
> +
> + r = amdgpu_job_alloc_with_ib(ring->adev, &entity, owner,
> + 64, 0, &job);
> if (r)
> goto err;
>
^ permalink raw reply [flat|nested] 6+ messages in thread
* Re: [PATCH 1/2] drm/amdgpu: use a dummy owner for sysfs triggered cleaner shaders v2
2025-04-03 3:15 ` [PATCH 1/2] drm/amdgpu: use a dummy owner for sysfs triggered cleaner shaders v2 SRINIVASAN SHANMUGAM
@ 2025-04-03 9:10 ` Christian König
2025-04-03 13:56 ` SRINIVASAN SHANMUGAM
0 siblings, 1 reply; 6+ messages in thread
From: Christian König @ 2025-04-03 9:10 UTC (permalink / raw)
To: SRINIVASAN SHANMUGAM, amd-gfx
Am 03.04.25 um 05:15 schrieb SRINIVASAN SHANMUGAM:
>
> On 4/2/2025 7:32 PM, Christian König wrote:
>> Otherwise triggering sysfs multiple times without other submissions in
>> between only runs the shader once.
>>
>> v2: add some comment
>>
>> Signed-off-by: Christian König <christian.koenig@amd.com>
>> ---
>> drivers/gpu/drm/amd/amdgpu/amdgpu_gfx.c | 14 +++++++++++---
>> 1 file changed, 11 insertions(+), 3 deletions(-)
>>
>> diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_gfx.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_gfx.c
>> index f64675b2ab75..9a24be43e035 100644
>> --- a/drivers/gpu/drm/amd/amdgpu/amdgpu_gfx.c
>> +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_gfx.c
>> @@ -1439,9 +1439,11 @@ static int amdgpu_gfx_run_cleaner_shader_job(struct amdgpu_ring *ring)
>> struct amdgpu_device *adev = ring->adev;
>> struct drm_gpu_scheduler *sched = &ring->sched;
>> struct drm_sched_entity entity;
>> + static atomic_t counter;
>> struct dma_fence *f;
>> struct amdgpu_job *job;
>> struct amdgpu_ib *ib;
>> + void * owner;
>> int i, r;
>> /* Initialize the scheduler entity */
>> @@ -1452,9 +1454,15 @@ static int amdgpu_gfx_run_cleaner_shader_job(struct amdgpu_ring *ring)
>> goto err;
>> }
>> - r = amdgpu_job_alloc_with_ib(ring->adev, &entity, NULL,
>> - 64, 0,
>> - &job);
>> + /*
>> + * Use some unique dummy value as the owner to make sure we execute
>> + * the cleaner shader on each submission. The value just need to change
>> + * for each submission and is otherwise meaningless.
>> + */
>> + owner = (unsigned long)atomic_inc_return(&counter),
>
> Should this "atomic_inc_return()" needs to be casted to (void*), as it is return type is int?
No, I had that in the first version of the patch but it's actually sufficient to cast it to a long (which has the same number of bits as void*).
Regards,
Christian.
>
> Regards,
> Srini
>
>> +
>> + r = amdgpu_job_alloc_with_ib(ring->adev, &entity, owner,
>> + 64, 0, &job);
>> if (r)
>> goto err;
>>
^ permalink raw reply [flat|nested] 6+ messages in thread
* Re: [PATCH 1/2] drm/amdgpu: use a dummy owner for sysfs triggered cleaner shaders v2
2025-04-03 9:10 ` Christian König
@ 2025-04-03 13:56 ` SRINIVASAN SHANMUGAM
0 siblings, 0 replies; 6+ messages in thread
From: SRINIVASAN SHANMUGAM @ 2025-04-03 13:56 UTC (permalink / raw)
To: Christian König, amd-gfx
On 4/3/2025 2:40 PM, Christian König wrote:
> Am 03.04.25 um 05:15 schrieb SRINIVASAN SHANMUGAM:
>> On 4/2/2025 7:32 PM, Christian König wrote:
>>> Otherwise triggering sysfs multiple times without other submissions in
>>> between only runs the shader once.
>>>
>>> v2: add some comment
>>>
>>> Signed-off-by: Christian König <christian.koenig@amd.com>
>>> ---
>>> drivers/gpu/drm/amd/amdgpu/amdgpu_gfx.c | 14 +++++++++++---
>>> 1 file changed, 11 insertions(+), 3 deletions(-)
>>>
>>> diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_gfx.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_gfx.c
>>> index f64675b2ab75..9a24be43e035 100644
>>> --- a/drivers/gpu/drm/amd/amdgpu/amdgpu_gfx.c
>>> +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_gfx.c
>>> @@ -1439,9 +1439,11 @@ static int amdgpu_gfx_run_cleaner_shader_job(struct amdgpu_ring *ring)
>>> struct amdgpu_device *adev = ring->adev;
>>> struct drm_gpu_scheduler *sched = &ring->sched;
>>> struct drm_sched_entity entity;
>>> + static atomic_t counter;
>>> struct dma_fence *f;
>>> struct amdgpu_job *job;
>>> struct amdgpu_ib *ib;
>>> + void * owner;
>>> int i, r;
>>> /* Initialize the scheduler entity */
>>> @@ -1452,9 +1454,15 @@ static int amdgpu_gfx_run_cleaner_shader_job(struct amdgpu_ring *ring)
>>> goto err;
>>> }
>>> - r = amdgpu_job_alloc_with_ib(ring->adev, &entity, NULL,
>>> - 64, 0,
>>> - &job);
>>> + /*
>>> + * Use some unique dummy value as the owner to make sure we execute
>>> + * the cleaner shader on each submission. The value just need to change
>>> + * for each submission and is otherwise meaningless.
>>> + */
>>> + owner = (unsigned long)atomic_inc_return(&counter),
>> Should this "atomic_inc_return()" needs to be casted to (void*), as it is return type is int?
> No, I had that in the first version of the patch but it's actually sufficient to cast it to a long (which has the same number of bits as void*).
Thus, the use of a static atomic counter allows the driver to pass a
unique identifier (owner) to each job that triggers the cleaner shader.
This approach is crucial because it avoids the potential problem of
running the shader multiple times without other submissions in between
(since each run requires this unique submission context).
With that casting fixed, this patch is:
Reviewed-by: Srinivasan Shanmugam <srinivasan.shanmugam@amd.com>
>
> Regards,
> Christian.
>
>> Regards,
>> Srini
>>
>>> +
>>> + r = amdgpu_job_alloc_with_ib(ring->adev, &entity, owner,
>>> + 64, 0, &job);
>>> if (r)
>>> goto err;
>>>
^ permalink raw reply [flat|nested] 6+ messages in thread
* Re: [PATCH 2/2] drm/amdgpu: cleanup amdgpu_vm_flush v2
2025-04-02 14:02 ` [PATCH 2/2] drm/amdgpu: cleanup amdgpu_vm_flush v2 Christian König
@ 2025-04-04 5:15 ` SRINIVASAN SHANMUGAM
0 siblings, 0 replies; 6+ messages in thread
From: SRINIVASAN SHANMUGAM @ 2025-04-04 5:15 UTC (permalink / raw)
To: Christian König, amd-gfx
On 4/2/2025 7:32 PM, Christian König wrote:
> This reverts commit c2cc3648ba517a6c270500b5447d5a1efdad5936. Turned out
> that this has some negative consequences for some workloads. Instead check
> if the cleaner shader should run directly.
>
> While at it remove amdgpu_vm_need_pipeline_sync(), we also check again
> if the VMID has seen a GPU reset since last use and the gds switch
> setiing can be handled more simply as well.
>
> Also remove some duplicate checks and re-order and document the code.
>
> v2: restructure the while function
>
> Signed-off-by: Christian König <christian.koenig@amd.com>
> ---
> drivers/gpu/drm/amd/amdgpu/amdgpu_ib.c | 3 +-
> drivers/gpu/drm/amd/amdgpu/amdgpu_vm.c | 89 +++++++++-----------------
> drivers/gpu/drm/amd/amdgpu/amdgpu_vm.h | 5 +-
> 3 files changed, 34 insertions(+), 63 deletions(-)
>
> diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_ib.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_ib.c
> index 802743efa3b3..ff2ca984279a 100644
> --- a/drivers/gpu/drm/amd/amdgpu/amdgpu_ib.c
> +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_ib.c
> @@ -191,8 +191,7 @@ int amdgpu_ib_schedule(struct amdgpu_ring *ring, unsigned int num_ibs,
> need_ctx_switch = ring->current_ctx != fence_ctx;
> if (ring->funcs->emit_pipeline_sync && job &&
> ((tmp = amdgpu_sync_get_fence(&job->explicit_sync)) ||
> - need_ctx_switch || amdgpu_vm_need_pipeline_sync(ring, job))) {
> -
> + (amdgpu_sriov_vf(adev) && need_ctx_switch))) {
> need_pipe_sync = true;
So based on this, Pipeline Sync (ie., wait for GPU to become idle) is
needed only for SRIOV cases, like when SRIOV want to preempt ring
buffers and switch to another ring buffers, might require
synchronization to avoid clashes between virtual devices.
>
> if (tmp)
> diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_vm.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_vm.c
> index b5ddfcbbc9fc..d7a4cb07defc 100644
> --- a/drivers/gpu/drm/amd/amdgpu/amdgpu_vm.c
> +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_vm.c
> @@ -596,37 +596,6 @@ void amdgpu_vm_check_compute_bug(struct amdgpu_device *adev)
> }
> }
>
> -/**
> - * amdgpu_vm_need_pipeline_sync - Check if pipe sync is needed for job.
> - *
> - * @ring: ring on which the job will be submitted
> - * @job: job to submit
> - *
> - * Returns:
> - * True if sync is needed.
> - */
> -bool amdgpu_vm_need_pipeline_sync(struct amdgpu_ring *ring,
> - struct amdgpu_job *job)
> -{
> - struct amdgpu_device *adev = ring->adev;
> - unsigned vmhub = ring->vm_hub;
> - struct amdgpu_vmid_mgr *id_mgr = &adev->vm_manager.id_mgr[vmhub];
> -
> - if (job->vmid == 0)
> - return false;
> -
> - if (job->vm_needs_flush || ring->has_compute_vm_bug)
> - return true;
> -
> - if (ring->funcs->emit_gds_switch && job->gds_switch_needed)
> - return true;
> -
> - if (amdgpu_vmid_had_gpu_reset(adev, &id_mgr->ids[job->vmid]))
> - return true;
> -
> - return false;
> -}
> -
> /**
> * amdgpu_vm_flush - hardware flush the vm
> *
> @@ -647,29 +616,31 @@ int amdgpu_vm_flush(struct amdgpu_ring *ring, struct amdgpu_job *job,
> unsigned vmhub = ring->vm_hub;
> struct amdgpu_vmid_mgr *id_mgr = &adev->vm_manager.id_mgr[vmhub];
> struct amdgpu_vmid *id = &id_mgr->ids[job->vmid];
> - bool spm_update_needed = job->spm_update_needed;
> - bool gds_switch_needed = ring->funcs->emit_gds_switch &&
> - job->gds_switch_needed;
> - bool vm_flush_needed = job->vm_needs_flush;
> - bool cleaner_shader_needed = false;
> - bool pasid_mapping_needed = false;
> - struct dma_fence *fence = NULL;
> + bool gds_switch_needed, vm_flush_needed, spm_update_needed,
> + cleaner_shader_needed, pasid_mapping_needed;
> + struct dma_fence *fence;
> unsigned int patch;
> int r;
>
> + /* First of all figure out what needs to be done */
> if (amdgpu_vmid_had_gpu_reset(adev, id)) {
> + need_pipe_sync = true;
> gds_switch_needed = true;
> vm_flush_needed = true;
> pasid_mapping_needed = true;
> spm_update_needed = true;
> + } else {
> + gds_switch_needed = job->gds_switch_needed;
*[1]:* Should we need to check along with "ring->funcs->emit_gds_switch"
ie., "ring->funcs->emit_gds_switch && job->gds_switch_needed;"
> + vm_flush_needed = job->vm_needs_flush;
> + mutex_lock(&id_mgr->lock);
> + if (id->pasid != job->pasid || !id->pasid_mapping ||
> + !dma_fence_is_signaled(id->pasid_mapping))
> + pasid_mapping_needed = true;
> + mutex_unlock(&id_mgr->lock);
> + spm_update_needed = job->spm_update_needed;
> + need_pipe_sync |= vm_flush_needed && ring->has_compute_vm_bug;
*[2]:* Just to double check, based on the old code, Pipeline Sync was
emitted, ie., whenever job needed vm_flush and that was OR'ed with
"Compute rings had the issues on gfx8 , where pipeline sync was added
before we switch the compute jobs", but despite of this compute ring
issues, we might still need vm_flush -> for a job switching that is
using same vmid as previous one, am I correct please? ie., should we
need to retain something like this, same as old code ie.,
"vm_flush_needed || ring->has_compute_vm_bug;" ?
> }
>
> - mutex_lock(&id_mgr->lock);
> - if (id->pasid != job->pasid || !id->pasid_mapping ||
> - !dma_fence_is_signaled(id->pasid_mapping))
> - pasid_mapping_needed = true;
> - mutex_unlock(&id_mgr->lock);
> -
> gds_switch_needed &= !!ring->funcs->emit_gds_switch;
> vm_flush_needed &= !!ring->funcs->emit_vm_flush &&
> job->vm_pd_addr != AMDGPU_BO_INVALID_OFFSET;
> @@ -684,12 +655,13 @@ int amdgpu_vm_flush(struct amdgpu_ring *ring, struct amdgpu_job *job,
> !cleaner_shader_needed)
> return 0;
>
> + /* Then aktually prepare the submission frame */
*[3]:* Could you pls correct the typo?
> amdgpu_ring_ib_begin(ring);
> if (ring->funcs->init_cond_exec)
> patch = amdgpu_ring_init_cond_exec(ring,
> ring->cond_exe_gpu_addr);
>
> - if (need_pipe_sync)
> + if (need_pipe_sync || cleaner_shader_needed || gds_switch_needed)
So with this checks, whenever cleaner shader or GDS (Global Data Store)
Switches need to be emitted, we expect GPU to be in idle state , by
emitting Pipeline Sync.
> amdgpu_ring_emit_pipeline_sync(ring);
>
> if (cleaner_shader_needed)
> @@ -706,20 +678,31 @@ int amdgpu_vm_flush(struct amdgpu_ring *ring, struct amdgpu_job *job,
> if (spm_update_needed && adev->gfx.rlc.funcs->update_spm_vmid)
> adev->gfx.rlc.funcs->update_spm_vmid(adev, ring, job->vmid);
>
> - if (ring->funcs->emit_gds_switch &&
> - gds_switch_needed) {
> + if (gds_switch_needed)
> amdgpu_ring_emit_gds_switch(ring, job->vmid, job->gds_base,
> job->gds_size, job->gws_base,
> job->gws_size, job->oa_base,
> job->oa_size);
> - }
>
> if (vm_flush_needed || pasid_mapping_needed || cleaner_shader_needed) {
> r = amdgpu_fence_emit(ring, &fence, NULL, 0);
> if (r)
> return r;
> + } else {
> + fence = NULL;
> + }
> +
> + amdgpu_ring_patch_cond_exec(ring, patch);
> +
> + /* the double SWITCH_BUFFER here *cannot* be skipped by COND_EXEC */
> + if (ring->funcs->emit_switch_buffer) {
> + amdgpu_ring_emit_switch_buffer(ring);
> + amdgpu_ring_emit_switch_buffer(ring);
> }
>
> + amdgpu_ring_ib_end(ring);
> +
By moving this here, we ensure that previous jobs that those are
dependent on current job are managed & complete, fully synchronized
before any patching or switching buffers logic's are applied. In gang
submissions, this is crucial. Ensuring synchronization before context
changes prevents one job from interfering with another, thus enforcing
isolation effectively.
> + /* And finally remember what the ring has executed */
> if (vm_flush_needed) {
> mutex_lock(&id_mgr->lock);
> dma_fence_put(id->last_flush);
> @@ -749,16 +732,6 @@ int amdgpu_vm_flush(struct amdgpu_ring *ring, struct amdgpu_job *job,
> mutex_unlock(&adev->enforce_isolation_mutex);
> }
> dma_fence_put(fence);
> -
> - amdgpu_ring_patch_cond_exec(ring, patch);
> -
> - /* the double SWITCH_BUFFER here *cannot* be skipped by COND_EXEC */
> - if (ring->funcs->emit_switch_buffer) {
> - amdgpu_ring_emit_switch_buffer(ring);
> - amdgpu_ring_emit_switch_buffer(ring);
> - }
> -
> - amdgpu_ring_ib_end(ring);
> return 0;
> }
>
> diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_vm.h b/drivers/gpu/drm/amd/amdgpu/amdgpu_vm.h
> index daa2f9b33620..e9ecdb96bafa 100644
> --- a/drivers/gpu/drm/amd/amdgpu/amdgpu_vm.h
> +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_vm.h
> @@ -493,7 +493,8 @@ int amdgpu_vm_validate(struct amdgpu_device *adev, struct amdgpu_vm *vm,
> struct ww_acquire_ctx *ticket,
> int (*callback)(void *p, struct amdgpu_bo *bo),
> void *param);
> -int amdgpu_vm_flush(struct amdgpu_ring *ring, struct amdgpu_job *job, bool need_pipe_sync);
> +int amdgpu_vm_flush(struct amdgpu_ring *ring, struct amdgpu_job *job,
> + bool need_pipe_sync);
> int amdgpu_vm_update_pdes(struct amdgpu_device *adev,
> struct amdgpu_vm *vm, bool immediate);
> int amdgpu_vm_clear_freed(struct amdgpu_device *adev,
> @@ -550,8 +551,6 @@ void amdgpu_vm_adjust_size(struct amdgpu_device *adev, uint32_t min_vm_size,
> uint32_t fragment_size_default, unsigned max_level,
> unsigned max_bits);
> int amdgpu_vm_ioctl(struct drm_device *dev, void *data, struct drm_file *filp);
> -bool amdgpu_vm_need_pipeline_sync(struct amdgpu_ring *ring,
> - struct amdgpu_job *job);
> void amdgpu_vm_check_compute_bug(struct amdgpu_device *adev);
>
> struct amdgpu_task_info *
Requesting for feedback's that is marked as *[1]* , *[2]* & *[3]*
addressed , with this, the patch is:
Reviewed-by: Srinivasan Shanmugam <srinivasan.shanmugam@amd.com>
^ permalink raw reply [flat|nested] 6+ messages in thread
end of thread, other threads:[~2025-04-04 5:15 UTC | newest]
Thread overview: 6+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2025-04-02 14:02 [PATCH 1/2] drm/amdgpu: use a dummy owner for sysfs triggered cleaner shaders v2 Christian König
2025-04-02 14:02 ` [PATCH 2/2] drm/amdgpu: cleanup amdgpu_vm_flush v2 Christian König
2025-04-04 5:15 ` SRINIVASAN SHANMUGAM
2025-04-03 3:15 ` [PATCH 1/2] drm/amdgpu: use a dummy owner for sysfs triggered cleaner shaders v2 SRINIVASAN SHANMUGAM
2025-04-03 9:10 ` Christian König
2025-04-03 13:56 ` SRINIVASAN SHANMUGAM
This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.