Skip to content

Commit b83ce9c

Browse files
dma-buf: add dma_fence_timestamp helper
When a fence signals there is a very small race window where the timestamp isn't updated yet. sync_file solves this by busy waiting for the timestamp to appear, but on other ocassions didn't handled this correctly. Provide a dma_fence_timestamp() helper function for this and use it in all appropriate cases. Another alternative would be to grab the spinlock when that happens. v2 by teddy: add a wait parameter to wait for the timestamp to show up, in case the accurate timestamp is needed and/or the timestamp is not based on ktime (e.g. hw timestamp) v3 chk: drop the parameter again for unified handling Signed-off-by: Yunxiang Li <[email protected]> Signed-off-by: Christian König <[email protected]> Fixes: 1774baa ("drm/scheduler: Change scheduled fence track v2") Reviewed-by: Alex Deucher <[email protected]> CC: [email protected] Link: https://patchwork.freedesktop.org/patch/msgid/[email protected]
1 parent d59e75e commit b83ce9c

File tree

4 files changed

+27
-16
lines changed

4 files changed

+27
-16
lines changed

drivers/dma-buf/dma-fence-unwrap.c

Lines changed: 4 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -76,16 +76,11 @@ struct dma_fence *__dma_fence_unwrap_merge(unsigned int num_fences,
7676
dma_fence_unwrap_for_each(tmp, &iter[i], fences[i]) {
7777
if (!dma_fence_is_signaled(tmp)) {
7878
++count;
79-
} else if (test_bit(DMA_FENCE_FLAG_TIMESTAMP_BIT,
80-
&tmp->flags)) {
81-
if (ktime_after(tmp->timestamp, timestamp))
82-
timestamp = tmp->timestamp;
8379
} else {
84-
/*
85-
* Use the current time if the fence is
86-
* currently signaling.
87-
*/
88-
timestamp = ktime_get();
80+
ktime_t t = dma_fence_timestamp(tmp);
81+
82+
if (ktime_after(t, timestamp))
83+
timestamp = t;
8984
}
9085
}
9186
}

drivers/dma-buf/sync_file.c

Lines changed: 3 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -268,13 +268,10 @@ static int sync_fill_fence_info(struct dma_fence *fence,
268268
sizeof(info->driver_name));
269269

270270
info->status = dma_fence_get_status(fence);
271-
while (test_bit(DMA_FENCE_FLAG_SIGNALED_BIT, &fence->flags) &&
272-
!test_bit(DMA_FENCE_FLAG_TIMESTAMP_BIT, &fence->flags))
273-
cpu_relax();
274271
info->timestamp_ns =
275-
test_bit(DMA_FENCE_FLAG_TIMESTAMP_BIT, &fence->flags) ?
276-
ktime_to_ns(fence->timestamp) :
277-
ktime_set(0, 0);
272+
dma_fence_is_signaled(fence) ?
273+
ktime_to_ns(dma_fence_timestamp(fence)) :
274+
ktime_set(0, 0);
278275

279276
return info->status;
280277
}

drivers/gpu/drm/scheduler/sched_main.c

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -929,7 +929,7 @@ drm_sched_get_cleanup_job(struct drm_gpu_scheduler *sched)
929929

930930
if (next) {
931931
next->s_fence->scheduled.timestamp =
932-
job->s_fence->finished.timestamp;
932+
dma_fence_timestamp(&job->s_fence->finished);
933933
/* start TO timer for next job */
934934
drm_sched_start_timeout(sched);
935935
}

include/linux/dma-fence.h

Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -568,6 +568,25 @@ static inline void dma_fence_set_error(struct dma_fence *fence,
568568
fence->error = error;
569569
}
570570

571+
/**
572+
* dma_fence_timestamp - helper to get the completion timestamp of a fence
573+
* @fence: fence to get the timestamp from.
574+
*
575+
* After a fence is signaled the timestamp is updated with the signaling time,
576+
* but setting the timestamp can race with tasks waiting for the signaling. This
577+
* helper busy waits for the correct timestamp to appear.
578+
*/
579+
static inline ktime_t dma_fence_timestamp(struct dma_fence *fence)
580+
{
581+
if (WARN_ON(!test_bit(DMA_FENCE_FLAG_SIGNALED_BIT, &fence->flags)))
582+
return ktime_get();
583+
584+
while (!test_bit(DMA_FENCE_FLAG_TIMESTAMP_BIT, &fence->flags))
585+
cpu_relax();
586+
587+
return fence->timestamp;
588+
}
589+
571590
signed long dma_fence_wait_timeout(struct dma_fence *,
572591
bool intr, signed long timeout);
573592
signed long dma_fence_wait_any_timeout(struct dma_fence **fences,

0 commit comments

Comments
 (0)