[Intel-gfx] [PATCH] drm/syncobj: flatten dma_fence_chains on transfer
Lionel Landwerlin
lionel.g.landwerlin at intel.com
Wed May 25 09:26:14 UTC 2022
On 25/05/2022 11:24, Christian König wrote:
> Am 25.05.22 um 08:47 schrieb Lionel Landwerlin:
>> On 09/02/2022 20:26, Christian König wrote:
>>> It is illegal to add a dma_fence_chain as timeline point. Flatten out
>>> the fences into a dma_fence_array instead.
>>>
>>> Signed-off-by: Christian König <christian.koenig at amd.com>
>>> ---
>>> drivers/gpu/drm/drm_syncobj.c | 61
>>> ++++++++++++++++++++++++++++++++---
>>> 1 file changed, 56 insertions(+), 5 deletions(-)
>>>
>>> diff --git a/drivers/gpu/drm/drm_syncobj.c
>>> b/drivers/gpu/drm/drm_syncobj.c
>>> index c313a5b4549c..7e48dcd1bee4 100644
>>> --- a/drivers/gpu/drm/drm_syncobj.c
>>> +++ b/drivers/gpu/drm/drm_syncobj.c
>>> @@ -853,12 +853,57 @@ drm_syncobj_fd_to_handle_ioctl(struct
>>> drm_device *dev, void *data,
>>> &args->handle);
>>> }
>>> +
>>> +/*
>>> + * Try to flatten a dma_fence_chain into a dma_fence_array so that
>>> it can be
>>> + * added as timeline fence to a chain again.
>>> + */
>>> +static int drm_syncobj_flatten_chain(struct dma_fence **f)
>>> +{
>>> + struct dma_fence_chain *chain = to_dma_fence_chain(*f);
>>> + struct dma_fence *tmp, **fences;
>>> + struct dma_fence_array *array;
>>> + unsigned int count;
>>> +
>>> + if (!chain)
>>> + return 0;
>>> +
>>> + count = 0;
>>> + dma_fence_chain_for_each(tmp, &chain->base)
>>> + ++count;
>>> +
>>> + fences = kmalloc_array(count, sizeof(*fences), GFP_KERNEL);
>>> + if (!fences)
>>> + return -ENOMEM;
>>> +
>>> + count = 0;
>>> + dma_fence_chain_for_each(tmp, &chain->base)
>>> + fences[count++] = dma_fence_get(tmp);
>>> +
>>> + array = dma_fence_array_create(count, fences,
>>> + dma_fence_context_alloc(1),
>>
>>
>> Hi Christian,
>>
>>
>> Sorry for the late answer to this.
>>
>>
>> It appears this commit is trying to remove the warnings added by
>> "dma-buf: Warn about dma_fence_chain container rules"
>
> Yes, correct. We are now enforcing some rules with warnings and this
> here bubbled up.
>
>>
>> But the context allocation you added just above is breaking some
>> tests. In particular igt at syncobj_timeline@transfer-timeline-point
>>
>> That test transfer points into the timeline at point 3 and expects
>> that we'll still on the previous points to complete.
>
> Hui what? I don't understand the problem you are seeing here. What
> exactly is the test doing?
>
>>
>> In my opinion we should be reusing the previous context number if
>> there is one and only allocate if we don't have a point.
>
> Scratching my head what you mean with that. The functionality
> transfers a synchronization fence from one timeline to another.
>
> So as far as I can see the new point should be part of the timeline of
> the syncobj we are transferring to.
>
>> If the application wants to not depend on previous points for wait
>> operations, it can reset the syncobj prior to adding a new point.
>
> Well we should never lose synchronization. So what happens is that
> when we do the transfer all the fences of the source are flattened out
> into an array. And that array is then added as new point into the
> destination timeline.
In this case would be broken :
syncobjA <- signal point 1
syncobjA <- import syncobjB point 1 into syncobjA point 2
syncobjA <- query returns 0
-Lionel
>
> Where exactly is the problem?
>
> Regards,
> Christian.
>
>>
>>
>>
>> Cheers,
>>
>>
>> -Lionel
>>
>>
>>
>>> + 1, false);
>>> + if (!array)
>>> + goto free_fences;
>>> +
>>> + dma_fence_put(*f);
>>> + *f = &array->base;
>>> + return 0;
>>> +
>>> +free_fences:
>>> + while (count--)
>>> + dma_fence_put(fences[count]);
>>> +
>>> + kfree(fences);
>>> + return -ENOMEM;
>>> +}
>>> +
>>> static int drm_syncobj_transfer_to_timeline(struct drm_file
>>> *file_private,
>>> struct drm_syncobj_transfer *args)
>>> {
>>> struct drm_syncobj *timeline_syncobj = NULL;
>>> - struct dma_fence *fence;
>>> struct dma_fence_chain *chain;
>>> + struct dma_fence *fence;
>>> int ret;
>>> timeline_syncobj = drm_syncobj_find(file_private,
>>> args->dst_handle);
>>> @@ -869,16 +914,22 @@ static int
>>> drm_syncobj_transfer_to_timeline(struct drm_file *file_private,
>>> args->src_point, args->flags,
>>> &fence);
>>> if (ret)
>>> - goto err;
>>> + goto err_put_timeline;
>>> +
>>> + ret = drm_syncobj_flatten_chain(&fence);
>>> + if (ret)
>>> + goto err_free_fence;
>>> +
>>> chain = dma_fence_chain_alloc();
>>> if (!chain) {
>>> ret = -ENOMEM;
>>> - goto err1;
>>> + goto err_free_fence;
>>> }
>>> +
>>> drm_syncobj_add_point(timeline_syncobj, chain, fence,
>>> args->dst_point);
>>> -err1:
>>> +err_free_fence:
>>> dma_fence_put(fence);
>>> -err:
>>> +err_put_timeline:
>>> drm_syncobj_put(timeline_syncobj);
>>> return ret;
>>
>>
>
More information about the Intel-gfx
mailing list