[PATCH] dma-buf: fix timeout handling in dma_resv_wait_timeout
Christian König
ckoenig.leichtzumerken at gmail.com
Wed Jan 29 10:56:37 UTC 2025
Am 28.01.25 um 15:41 schrieb Lucas Stach:
> Am Dienstag, dem 28.01.2025 um 15:28 +0100 schrieb Christian König:
>> Am 28.01.25 um 11:48 schrieb Lucas Stach:
>>> Hi Christian,
>>>
>>> Am Dienstag, dem 28.01.2025 um 11:08 +0100 schrieb Christian König:
>>>> Even the kerneldoc says that with a zero timeout the function should not
>>>> wait for anything, but still return 1 to indicate that the fences are
>>>> signaled now.
>>>>
>>>> Unfortunately that isn't what was implemented, instead of only returning
>>>> 1 we also waited for at least one jiffies.
>>>>
>>>> Fix that by adjusting the handling to what the function is actually
>>>> documented to do.
>>>>
>>>> Reported-by: Marek Olšák <marek.olsak at amd.com>
>>>> Reported-by: Lucas Stach <l.stach at pengutronix.de>
>>>> Signed-off-by: Christian König <christian.koenig at amd.com>
>>>> Cc: <stable at vger.kernel.org>
>>>> ---
>>>> drivers/dma-buf/dma-resv.c | 11 ++++++-----
>>>> 1 file changed, 6 insertions(+), 5 deletions(-)
>>>>
>>>> diff --git a/drivers/dma-buf/dma-resv.c b/drivers/dma-buf/dma-resv.c
>>>> index 5f8d010516f0..ae92d9d2394d 100644
>>>> --- a/drivers/dma-buf/dma-resv.c
>>>> +++ b/drivers/dma-buf/dma-resv.c
>>>> @@ -684,11 +684,12 @@ long dma_resv_wait_timeout(struct dma_resv *obj, enum dma_resv_usage usage,
>>>> dma_resv_iter_begin(&cursor, obj, usage);
>>>> dma_resv_for_each_fence_unlocked(&cursor, fence) {
>>>>
>>>> - ret = dma_fence_wait_timeout(fence, intr, ret);
>>>> - if (ret <= 0) {
>>>> - dma_resv_iter_end(&cursor);
>>>> - return ret;
>>>> - }
>>>> + ret = dma_fence_wait_timeout(fence, intr, timeout);
>>>> + if (ret <= 0)
>>>> + break;
>>>> +
>>>> + /* Even for zero timeout the return value is 1 */
>>>> + timeout = min(timeout, ret);
>>> This min construct and the comment confused me a bit at first. I think
>>> it would be easier to read as
>>>
>>> /* With a zero timeout dma_fence_wait_timeout makes up a
>>> * positive return value for already signaled fences.
>>> */
>>> if (timeout)
>>> timeout = ret;
>> Good point, going to change that.
>>
>>> Also please change the initialization of ret on top of the function to
>>> ret = 1 so it has the right value when no fences are present. Now that
>>> you use the timeout variable for the fence wait, there is no point in
>>> initializing ret to the timeout.
>> When no fences are present returning 1 would be incorrect if the timeout
>> value was non zero.
>>
>> Only when the timeout value is zero we should return 1 to indicate that
>> there is nothing to wait for.
>>
> Uh, yea didn't think about this.
>
> Honestly, making up this positive return value requires one to think
> really hard about those code paths. This would all be much cleaner and
> the chaining of multiple waits, like in the function changed here,
> would be much more natural when a 0 return would also be treated as a
> ordinary successful wait and timeouts would be signaled with ETIMEDOUT.
> But that's a large change with lots of callsites to audit, maybe for
> another day.
Yeah, I've suggested that before as well.
But the wait_event_timeout* interfaces follows the same convention:
https://elixir.bootlin.com/linux/v6.12.11/source/include/linux/wait.h#L393
So we used with that for some reason. My educated guess is that it made
migration easier because drivers were using wait_event_timeout* before
dma_resv/dma_fence was invented.
Regards,
Christian.
>
> Regards,
> Lucas
More information about the dri-devel
mailing list