On 1/22/26 09:56, Tvrtko Ursulin wrote:
>
> On 12/01/2026 13:32, Christian König wrote:
>> On 1/12/26 11:22, Tvrtko Ursulin wrote:
>>> Currently there are two flavours of the context reference count
>>> destructor:
>>>
>>> - amdgpu_ctx_do_release(), used from kref_put from places where the code
>>> thinks context may have been used, or is in active use, and;
>>> - amdgpu_ctx_fini(), used when code is sure context entities have already
>>> been idled.
>>>
>>> Since amdgpu_ctx_do_release() calls amdgpu_ctx_fini() after having idled
>>> and destroyed the scheduler entities, we can consolidate the two into a
>>> single function.
>>>
>>> Functional difference is that now drm_sched_entity_destroy() is called on
>>> context manager shutdown (file close), where previously it was
>>> drm_sched_entity_fini(). But the former is a superset of the latter, and
>>> during file close the flush method is also called, which calls
>>> drm_sched_entity_flush(), which is also called by
>>> drm_sched_entity_destroy(). And as it is safe to attempt to flush a never
>>> used entity, or flush it twice, there is actually no functional change.
>>>
>>> Signed-off-by: Tvrtko Ursulin <[email protected]>
>>> Suggested-by: Christian König <[email protected]>
>>
>> Reviewed-by: Christian König <[email protected]>
>>
>> Looks like this was the last patch to review. I will pick up the set and try
>> to push it to amd-staging-drm-next.
>
> Gentle reminder if we could try to validate the series via
> amd-staging-drm-next.
I pushed the first 7 patches from this series to amd-staging-drm-next and our
CI systems seem to be happy with them.
But starting with patch #8 I either had rebase conflicts or the CI system seem
to reject something here.
Can you rebase on top of amd-staging-drm-next and test a bit more? If you are
confident that the patches work I can throw them into the CI system once more.
Regards,
Christian.
>
> Also, what could I do on my end to get more confidence some edge case is not
> broken? Run the IGT tests? Is there an useful testlist which can be used with
> the IGT runner or that is not used on the AMD side?
>
> Regards,
>
> Tvrtko
>
>>> ---
>>> v2:
>>> * Use separate variable for drm_dev_enter for readability.
>>>
>>> v3:
>>> * Keep amdgpu_ctx_fini_entity as a separate function.
>>> ---
>>> drivers/gpu/drm/amd/amdgpu/amdgpu_ctx.c | 54 ++++---------------------
>>> drivers/gpu/drm/amd/amdgpu/amdgpu_ctx.h | 9 ++++-
>>> 2 files changed, 15 insertions(+), 48 deletions(-)
>>>
>>> diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_ctx.c
>>> b/drivers/gpu/drm/amd/amdgpu/amdgpu_ctx.c
>>> index 325833ed2571..cc69ad0f03d5 100644
>>> --- a/drivers/gpu/drm/amd/amdgpu/amdgpu_ctx.c
>>> +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_ctx.c
>>> @@ -284,6 +284,8 @@ static ktime_t amdgpu_ctx_fini_entity(struct
>>> amdgpu_device *adev,
>>> if (!entity)
>>> return res;
>>> + drm_sched_entity_destroy(&entity->entity);
>>> +
>>> for (i = 0; i < amdgpu_sched_jobs; ++i) {
>>> res = ktime_add(res, amdgpu_ctx_fence_time(entity->fences[i]));
>>> dma_fence_put(entity->fences[i]);
>>> @@ -409,7 +411,7 @@ static int amdgpu_ctx_set_stable_pstate(struct
>>> amdgpu_ctx *ctx,
>>> return r;
>>> }
>>> -static void amdgpu_ctx_fini(struct kref *ref)
>>> +void amdgpu_ctx_fini(struct kref *ref)
>>> {
>>> struct amdgpu_ctx *ctx = container_of(ref, struct amdgpu_ctx,
>>> refcount);
>>> struct amdgpu_ctx_mgr *mgr = ctx->mgr;
>>> @@ -508,24 +510,6 @@ static int amdgpu_ctx_alloc(struct amdgpu_device *adev,
>>> return r;
>>> }
>>> -static void amdgpu_ctx_do_release(struct kref *ref)
>>> -{
>>> - struct amdgpu_ctx *ctx;
>>> - u32 i, j;
>>> -
>>> - ctx = container_of(ref, struct amdgpu_ctx, refcount);
>>> - for (i = 0; i < AMDGPU_HW_IP_NUM; ++i) {
>>> - for (j = 0; j < amdgpu_ctx_num_entities[i]; ++j) {
>>> - if (!ctx->entities[i][j])
>>> - continue;
>>> -
>>> - drm_sched_entity_destroy(&ctx->entities[i][j]->entity);
>>> - }
>>> - }
>>> -
>>> - amdgpu_ctx_fini(ref);
>>> -}
>>> -
>>> static int amdgpu_ctx_free(struct amdgpu_fpriv *fpriv, uint32_t id)
>>> {
>>> struct amdgpu_ctx_mgr *mgr = &fpriv->ctx_mgr;
>>> @@ -533,8 +517,7 @@ static int amdgpu_ctx_free(struct amdgpu_fpriv *fpriv,
>>> uint32_t id)
>>> mutex_lock(&mgr->lock);
>>> ctx = idr_remove(&mgr->ctx_handles, id);
>>> - if (ctx)
>>> - kref_put(&ctx->refcount, amdgpu_ctx_do_release);
>>> + amdgpu_ctx_put(ctx);
>>> mutex_unlock(&mgr->lock);
>>> return ctx ? 0 : -EINVAL;
>>> }
>>> @@ -750,15 +733,6 @@ struct amdgpu_ctx *amdgpu_ctx_get(struct amdgpu_fpriv
>>> *fpriv, uint32_t id)
>>> return ctx;
>>> }
>>> -int amdgpu_ctx_put(struct amdgpu_ctx *ctx)
>>> -{
>>> - if (ctx == NULL)
>>> - return -EINVAL;
>>> -
>>> - kref_put(&ctx->refcount, amdgpu_ctx_do_release);
>>> - return 0;
>>> -}
>>> -
>>> uint64_t amdgpu_ctx_add_fence(struct amdgpu_ctx *ctx,
>>> struct drm_sched_entity *entity,
>>> struct dma_fence *fence)
>>> @@ -927,29 +901,15 @@ long amdgpu_ctx_mgr_entity_flush(struct
>>> amdgpu_ctx_mgr *mgr, long timeout)
>>> static void amdgpu_ctx_mgr_entity_fini(struct amdgpu_ctx_mgr *mgr)
>>> {
>>> struct amdgpu_ctx *ctx;
>>> - struct idr *idp;
>>> - uint32_t id, i, j;
>>> + uint32_t id;
>>> - idp = &mgr->ctx_handles;
>>> -
>>> - idr_for_each_entry(idp, ctx, id) {
>>> + idr_for_each_entry(&mgr->ctx_handles, ctx, id) {
>>> if (kref_read(&ctx->refcount) != 1) {
>>> DRM_ERROR("ctx %p is still alive\n", ctx);
>>> continue;
>>> }
>>> - for (i = 0; i < AMDGPU_HW_IP_NUM; ++i) {
>>> - for (j = 0; j < amdgpu_ctx_num_entities[i]; ++j) {
>>> - struct drm_sched_entity *entity;
>>> -
>>> - if (!ctx->entities[i][j])
>>> - continue;
>>> -
>>> - entity = &ctx->entities[i][j]->entity;
>>> - drm_sched_entity_fini(entity);
>>> - }
>>> - }
>>> - kref_put(&ctx->refcount, amdgpu_ctx_fini);
>>> + amdgpu_ctx_put(ctx);
>>> }
>>> }
>>> diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_ctx.h
>>> b/drivers/gpu/drm/amd/amdgpu/amdgpu_ctx.h
>>> index cf8d700a22fe..b1fa7fe74569 100644
>>> --- a/drivers/gpu/drm/amd/amdgpu/amdgpu_ctx.h
>>> +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_ctx.h
>>> @@ -70,7 +70,14 @@ struct amdgpu_ctx_mgr {
>>> extern const unsigned int amdgpu_ctx_num_entities[AMDGPU_HW_IP_NUM];
>>> struct amdgpu_ctx *amdgpu_ctx_get(struct amdgpu_fpriv *fpriv, uint32_t
>>> id);
>>> -int amdgpu_ctx_put(struct amdgpu_ctx *ctx);
>>> +
>>> +void amdgpu_ctx_fini(struct kref *kref);
>>> +
>>> +static inline void amdgpu_ctx_put(struct amdgpu_ctx *ctx)
>>> +{
>>> + if (ctx)
>>> + kref_put(&ctx->refcount, amdgpu_ctx_fini);
>>> +}
>>> int amdgpu_ctx_get_entity(struct amdgpu_ctx *ctx, u32 hw_ip, u32
>>> instance,
>>> u32 ring, struct drm_sched_entity **entity);
>>
>