Эх сурвалжийг харах

disp: msm: sde: signal dma-fence and handle callbacks from sde driver

Signal the retire/release fences from within the sde driver instead of
calling the dma-fence api. This allows the driver to set the desired
timestamp for the fences. Replicate the dma-fence api functionality to
set the signaled and timestamp flags and handle the registered callbacks.

Change-Id: I951b599fc92d6d054847f24f0acb04aee27bdefb
Signed-off-by: Veera Sundaram Sankaran <[email protected]>
Veera Sundaram Sankaran 4 жил өмнө
parent
commit
835f8513dc
1 өөрчлөгдсөн 30 нэмэгдсэн , 4 устгасан
  1. 30 4
      msm/sde/sde_fence.c

+ 30 - 4
msm/sde/sde_fence.c

@@ -1,6 +1,6 @@
 // SPDX-License-Identifier: GPL-2.0-only
 /*
- * Copyright (c) 2016-2020, The Linux Foundation. All rights reserved.
+ * Copyright (c) 2016-2021, The Linux Foundation. All rights reserved.
  */
 
 #define pr_fmt(fmt)	"[drm:%s:%d] " fmt, __func__, __LINE__
@@ -12,6 +12,30 @@
 
 #define TIMELINE_VAL_LENGTH		128
 
+int _dma_fence_signal_timestamp_locked(struct dma_fence *fence, ktime_t ts)
+{
+	struct dma_fence_cb *cur, *tmp;
+	struct list_head cb_list;
+
+	lockdep_assert_held(fence->lock);
+
+	if (unlikely(test_and_set_bit(DMA_FENCE_FLAG_SIGNALED_BIT, &fence->flags)))
+		return -EINVAL;
+
+	/* Stash the cb_list before replacing it with the timestamp */
+	list_replace(&fence->cb_list, &cb_list);
+
+	fence->timestamp = ts;
+	set_bit(DMA_FENCE_FLAG_TIMESTAMP_BIT, &fence->flags);
+
+	list_for_each_entry_safe(cur, tmp, &cb_list, node) {
+		INIT_LIST_HEAD(&cur->node);
+		cur->func(fence, cur);
+	}
+
+	return 0;
+}
+
 void *sde_sync_get(uint64_t fd)
 {
 	/* force signed compare, fdget accepts an int argument */
@@ -289,7 +313,7 @@ void sde_fence_prepare(struct sde_fence_context *ctx)
 	}
 }
 
-static void _sde_fence_trigger(struct sde_fence_context *ctx, bool error)
+static void _sde_fence_trigger(struct sde_fence_context *ctx, bool error, ktime_t ts)
 {
 	unsigned long flags;
 	struct sde_fence *fc, *next;
@@ -307,7 +331,9 @@ static void _sde_fence_trigger(struct sde_fence_context *ctx, bool error)
 		spin_lock_irqsave(&ctx->lock, flags);
 		if (error)
 			dma_fence_set_error(&fc->base, -EBUSY);
-		is_signaled = dma_fence_is_signaled_locked(&fc->base);
+		is_signaled = sde_fence_signaled(&fc->base);
+		if (is_signaled)
+			_dma_fence_signal_timestamp_locked(&fc->base, ts);
 		spin_unlock_irqrestore(&ctx->lock, flags);
 
 		if (is_signaled) {
@@ -397,7 +423,7 @@ void sde_fence_signal(struct sde_fence_context *ctx, ktime_t ts,
 	SDE_EVT32(ctx->drm_id, ctx->done_count, ctx->commit_count,
 			ktime_to_us(ts));
 
-	_sde_fence_trigger(ctx, (fence_event == SDE_FENCE_SIGNAL_ERROR));
+	_sde_fence_trigger(ctx, (fence_event == SDE_FENCE_SIGNAL_ERROR), ts);
 }
 
 void sde_fence_timeline_status(struct sde_fence_context *ctx,