diff mbox series

dma-buf: keep the signaling time of merged fences v3

Message ID 20230630120041.109216-1-christian.koenig@amd.com (mailing list archive)
State New, archived
Headers show
Series dma-buf: keep the signaling time of merged fences v3 | expand

Commit Message

Christian König June 30, 2023, noon UTC
Some Android CTS is testing if the signaling time keeps consistent
during merges.

v2: use the current time if the fence is still in the signaling path and
the timestamp not yet available.
v3: improve comment, fix one more case to use the correct timestamp

Signed-off-by: Christian König <christian.koenig@amd.com>
---
 drivers/dma-buf/dma-fence-unwrap.c | 26 ++++++++++++++++++++++----
 drivers/dma-buf/dma-fence.c        |  5 +++--
 drivers/gpu/drm/drm_syncobj.c      |  2 +-
 include/linux/dma-fence.h          |  2 +-
 4 files changed, 27 insertions(+), 8 deletions(-)

Comments

Luben Tuikov June 30, 2023, 5:19 p.m. UTC | #1
On 2023-06-30 08:00, Christian König wrote:
> Some Android CTS is testing if the signaling time keeps consistent
> during merges.
> 
> v2: use the current time if the fence is still in the signaling path and
> the timestamp not yet available.
> v3: improve comment, fix one more case to use the correct timestamp
> 
> Signed-off-by: Christian König <christian.koenig@amd.com>
> ---
>  drivers/dma-buf/dma-fence-unwrap.c | 26 ++++++++++++++++++++++----
>  drivers/dma-buf/dma-fence.c        |  5 +++--
>  drivers/gpu/drm/drm_syncobj.c      |  2 +-
>  include/linux/dma-fence.h          |  2 +-
>  4 files changed, 27 insertions(+), 8 deletions(-)
> 
> diff --git a/drivers/dma-buf/dma-fence-unwrap.c b/drivers/dma-buf/dma-fence-unwrap.c
> index 7002bca792ff..c625bb2b5d56 100644
> --- a/drivers/dma-buf/dma-fence-unwrap.c
> +++ b/drivers/dma-buf/dma-fence-unwrap.c
> @@ -66,18 +66,36 @@ struct dma_fence *__dma_fence_unwrap_merge(unsigned int num_fences,
>  {
>  	struct dma_fence_array *result;
>  	struct dma_fence *tmp, **array;
> +	ktime_t timestamp;
>  	unsigned int i;
>  	size_t count;
>  
>  	count = 0;
> +	timestamp = ns_to_ktime(0);
>  	for (i = 0; i < num_fences; ++i) {
> -		dma_fence_unwrap_for_each(tmp, &iter[i], fences[i])
> -			if (!dma_fence_is_signaled(tmp))
> +		dma_fence_unwrap_for_each(tmp, &iter[i], fences[i]) {
> +			if (!dma_fence_is_signaled(tmp)) {
>  				++count;
> +			} else if (test_bit(DMA_FENCE_FLAG_TIMESTAMP_BIT,
> +					    &tmp->flags)) {
> +				if (ktime_after(tmp->timestamp, timestamp))
> +					timestamp = tmp->timestamp;
> +			} else {
> +				/*
> +				 * Use the current time if the fence is
> +				 * currently signaling.
> +				 */
> +				timestamp = ktime_get();
> +			}
> +		}
>  	}
>  
> +	/*
> +	 * If we couldn't find a pending fence just return a private signaled
> +	 * fence with the timestamp of the last signaled one.
> +	 */
>  	if (count == 0)
> -		return dma_fence_get_stub();
> +		return dma_fence_allocate_private_stub(timestamp);
>  

Hi Christian,

Thank you for clarifying the justification of this patch in the patch description,
and adding the comment before "if (count == 0)"--it's clearer now.

Reviewed-by: Luben Tuikov <luben.tuikov@amd.com>

Thanks again for sending a v3 of this patch--it does make it clearer now. Feel
free to push this patch in.

---
Silly question perhaps:
	Could we not have returned an existing (signalled) fence with
the wanted timestamp (when count == 0), as opposed to allocating a stub? Maybe
allocation should be avoided?
Christian König July 3, 2023, 11:49 a.m. UTC | #2
Am 30.06.23 um 19:19 schrieb Luben Tuikov:
> On 2023-06-30 08:00, Christian König wrote:
> [SNIP]
> ---
> Silly question perhaps:
> 	Could we not have returned an existing (signalled) fence with
> the wanted timestamp (when count == 0), as opposed to allocating a stub? Maybe
> allocation should be avoided?

No a silly, but a very good question.

Answer is yes, that's what we have done previously. Problem with that 
approach is that each fence reference prevents the driver who originally 
issued this fence from being able to unload.

That's especially ugly in cases of hotplug because you have to keep a 
zombie driver instance around for potentially quite some time.

Regards,
Christian.
diff mbox series

Patch

diff --git a/drivers/dma-buf/dma-fence-unwrap.c b/drivers/dma-buf/dma-fence-unwrap.c
index 7002bca792ff..c625bb2b5d56 100644
--- a/drivers/dma-buf/dma-fence-unwrap.c
+++ b/drivers/dma-buf/dma-fence-unwrap.c
@@ -66,18 +66,36 @@  struct dma_fence *__dma_fence_unwrap_merge(unsigned int num_fences,
 {
 	struct dma_fence_array *result;
 	struct dma_fence *tmp, **array;
+	ktime_t timestamp;
 	unsigned int i;
 	size_t count;
 
 	count = 0;
+	timestamp = ns_to_ktime(0);
 	for (i = 0; i < num_fences; ++i) {
-		dma_fence_unwrap_for_each(tmp, &iter[i], fences[i])
-			if (!dma_fence_is_signaled(tmp))
+		dma_fence_unwrap_for_each(tmp, &iter[i], fences[i]) {
+			if (!dma_fence_is_signaled(tmp)) {
 				++count;
+			} else if (test_bit(DMA_FENCE_FLAG_TIMESTAMP_BIT,
+					    &tmp->flags)) {
+				if (ktime_after(tmp->timestamp, timestamp))
+					timestamp = tmp->timestamp;
+			} else {
+				/*
+				 * Use the current time if the fence is
+				 * currently signaling.
+				 */
+				timestamp = ktime_get();
+			}
+		}
 	}
 
+	/*
+	 * If we couldn't find a pending fence just return a private signaled
+	 * fence with the timestamp of the last signaled one.
+	 */
 	if (count == 0)
-		return dma_fence_get_stub();
+		return dma_fence_allocate_private_stub(timestamp);
 
 	array = kmalloc_array(count, sizeof(*array), GFP_KERNEL);
 	if (!array)
@@ -138,7 +156,7 @@  struct dma_fence *__dma_fence_unwrap_merge(unsigned int num_fences,
 	} while (tmp);
 
 	if (count == 0) {
-		tmp = dma_fence_get_stub();
+		tmp = dma_fence_allocate_private_stub(ktime_get());
 		goto return_tmp;
 	}
 
diff --git a/drivers/dma-buf/dma-fence.c b/drivers/dma-buf/dma-fence.c
index f177c56269bb..ad076f208760 100644
--- a/drivers/dma-buf/dma-fence.c
+++ b/drivers/dma-buf/dma-fence.c
@@ -150,10 +150,11 @@  EXPORT_SYMBOL(dma_fence_get_stub);
 
 /**
  * dma_fence_allocate_private_stub - return a private, signaled fence
+ * @timestamp: timestamp when the fence was signaled
  *
  * Return a newly allocated and signaled stub fence.
  */
-struct dma_fence *dma_fence_allocate_private_stub(void)
+struct dma_fence *dma_fence_allocate_private_stub(ktime_t timestamp)
 {
 	struct dma_fence *fence;
 
@@ -169,7 +170,7 @@  struct dma_fence *dma_fence_allocate_private_stub(void)
 	set_bit(DMA_FENCE_FLAG_ENABLE_SIGNAL_BIT,
 		&fence->flags);
 
-	dma_fence_signal(fence);
+	dma_fence_signal_timestamp(fence, timestamp);
 
 	return fence;
 }
diff --git a/drivers/gpu/drm/drm_syncobj.c b/drivers/gpu/drm/drm_syncobj.c
index 0c2be8360525..04589a35eb09 100644
--- a/drivers/gpu/drm/drm_syncobj.c
+++ b/drivers/gpu/drm/drm_syncobj.c
@@ -353,7 +353,7 @@  EXPORT_SYMBOL(drm_syncobj_replace_fence);
  */
 static int drm_syncobj_assign_null_handle(struct drm_syncobj *syncobj)
 {
-	struct dma_fence *fence = dma_fence_allocate_private_stub();
+	struct dma_fence *fence = dma_fence_allocate_private_stub(ktime_get());
 
 	if (IS_ERR(fence))
 		return PTR_ERR(fence);
diff --git a/include/linux/dma-fence.h b/include/linux/dma-fence.h
index d54b595a0fe0..0d678e9a7b24 100644
--- a/include/linux/dma-fence.h
+++ b/include/linux/dma-fence.h
@@ -606,7 +606,7 @@  static inline signed long dma_fence_wait(struct dma_fence *fence, bool intr)
 void dma_fence_set_deadline(struct dma_fence *fence, ktime_t deadline);
 
 struct dma_fence *dma_fence_get_stub(void);
-struct dma_fence *dma_fence_allocate_private_stub(void);
+struct dma_fence *dma_fence_allocate_private_stub(ktime_t timestamp);
 u64 dma_fence_context_alloc(unsigned num);
 
 extern const struct dma_fence_ops dma_fence_array_ops;