[PATCH 6/8] drm: merge normal syncobj to timeline syncobj

Chunming Zhou david1.zhou at amd.com
Fri Aug 24 12:12:08 UTC 2018


normal syncobj can be unified to timeline syncobj.
The thingking is:
a. singal op always append to sinal list tail.
b. wait op always wait on last sinal point.

the driver indeed be simplified more.

Signed-off-by: Chunming Zhou <david1.zhou at amd.com>
---
 drivers/gpu/drm/drm_syncobj.c | 113 ++++++++++++++++------------------
 1 file changed, 52 insertions(+), 61 deletions(-)

diff --git a/drivers/gpu/drm/drm_syncobj.c b/drivers/gpu/drm/drm_syncobj.c
index e0d89a84359f..ff0b1fdfd9a8 100644
--- a/drivers/gpu/drm/drm_syncobj.c
+++ b/drivers/gpu/drm/drm_syncobj.c
@@ -56,6 +56,9 @@
 #include "drm_internal.h"
 #include <drm/drm_syncobj.h>
 
+/* merge normal syncobj to timeline syncobj, the point interval is 1 */
+#define DRM_SYNCOBJ_NORMAL_POINT 1
+
 struct drm_syncobj_stub_fence {
 	struct dma_fence base;
 	spinlock_t lock;
@@ -333,32 +336,17 @@ void drm_syncobj_replace_fence(struct drm_syncobj *syncobj,
 			       u64 point,
 			       struct dma_fence *fence)
 {
-	struct dma_fence *old_fence;
-	struct drm_syncobj_cb *cur, *tmp;
-
 	if (syncobj->type == DRM_SYNCOBJ_TYPE_TIMELINE) {
 		drm_syncobj_timeline_create_signal_pt(syncobj, fence, point);
 		return;
+	} else if (syncobj->type == DRM_SYNCOBJ_TYPE_NORMAL) {
+		u64 pt_value = syncobj->syncobj_timeline.signal_point +
+			DRM_SYNCOBJ_NORMAL_POINT;
+		drm_syncobj_timeline_create_signal_pt(syncobj, fence, pt_value);
+		return;
+	} else {
+		DRM_ERROR("the syncobj type isn't support\n");
 	}
-	if (fence)
-		dma_fence_get(fence);
-
-	spin_lock(&syncobj->lock);
-
-	old_fence = rcu_dereference_protected(syncobj->fence,
-					      lockdep_is_held(&syncobj->lock));
-	rcu_assign_pointer(syncobj->fence, fence);
-
-	if (fence != old_fence) {
-		list_for_each_entry_safe(cur, tmp, &syncobj->cb_list, node) {
-			list_del_init(&cur->node);
-			cur->func(syncobj, cur);
-		}
-	}
-
-	spin_unlock(&syncobj->lock);
-
-	dma_fence_put(old_fence);
 }
 EXPORT_SYMBOL(drm_syncobj_replace_fence);
 
@@ -452,7 +440,7 @@ drm_syncobj_timeline_create_wait_pt(struct drm_syncobj *syncobj, u64 point)
 }
 
 static struct dma_fence *
-drm_syncobj_timeline_point_get(struct drm_syncobj *syncobj, u64 point, u64 flag)
+drm_syncobj_timeline_point_get(struct drm_syncobj *syncobj, u64 point, u64 flags)
 {
 	struct drm_syncobj_wait_pt *wait_pt;
 
@@ -481,13 +469,15 @@ drm_syncobj_timeline_point_get(struct drm_syncobj *syncobj, u64 point, u64 flag)
 	}
 	if (wait_pt) {
 		struct dma_fence *fence;
-		int ret =
-			wait_event_interruptible_timeout(syncobj->syncobj_timeline.wq,
-				wait_pt->value <= syncobj->syncobj_timeline.signal_point,
-				msecs_to_jiffies(10000)); /* wait 10s */
-
-		if (ret <= 0)
-			return NULL;
+		int ret = 0;
+
+		if (flags & DRM_SYNCOBJ_WAIT_FLAGS_WAIT_FOR_SUBMIT) {
+			ret = wait_event_interruptible_timeout(syncobj->syncobj_timeline.wq,
+							       wait_pt->value <= syncobj->syncobj_timeline.signal_point,
+							       msecs_to_jiffies(10000)); /* wait 10s */
+			if (ret <= 0)
+				return NULL;
+		}
 		rcu_read_lock();
 		fence = dma_fence_get_rcu(&wait_pt->base.base);
 		rcu_read_unlock();
@@ -510,23 +500,26 @@ drm_syncobj_timeline_point_get(struct drm_syncobj *syncobj, u64 point, u64 flag)
  * contains a reference to the fence, which must be released by calling
  * dma_fence_put().
  */
-int drm_syncobj_find_fence(struct drm_file *file_private,
-			   u32 handle, u64 point,
-			   struct dma_fence **fence)
+static int drm_syncobj_search_fence(struct drm_syncobj *syncobj, u64 point,
+				    u64 flags, struct dma_fence **fence)
 {
-	struct drm_syncobj *syncobj = drm_syncobj_find(file_private, handle);
 	int ret = 0;
 
 	if (!syncobj)
 		return -ENOENT;
 
 	if (syncobj->type == DRM_SYNCOBJ_TYPE_NORMAL) {
+		u64 tail_pt_value = syncobj->syncobj_timeline.signal_point;
+
+		if (tail_pt_value == 0)
+			tail_pt_value += DRM_SYNCOBJ_NORMAL_POINT;
 		/* NORMAL syncobj doesn't care point value */
 		WARN_ON(point != 0);
-		*fence = drm_syncobj_fence_get(syncobj);
+		*fence = drm_syncobj_timeline_point_get(syncobj, tail_pt_value,
+							flags);
 	} else if (syncobj->type == DRM_SYNCOBJ_TYPE_TIMELINE) {
 		*fence = drm_syncobj_timeline_point_get(syncobj, point,
-							DRM_SYNCOBJ_WAIT_FLAGS_WAIT_FOR_SUBMIT);
+							flags);
 	} else {
 		DRM_ERROR("Don't support this type syncobj\n");
 		*fence = NULL;
@@ -537,6 +530,15 @@ int drm_syncobj_find_fence(struct drm_file *file_private,
 	drm_syncobj_put(syncobj);
 	return ret;
 }
+int drm_syncobj_find_fence(struct drm_file *file_private,
+			   u32 handle, u64 point,
+			   struct dma_fence **fence) {
+	struct drm_syncobj *syncobj = drm_syncobj_find(file_private, handle);
+
+	return drm_syncobj_search_fence(syncobj, point,
+					DRM_SYNCOBJ_WAIT_FLAGS_WAIT_FOR_SUBMIT,
+					fence);
+}
 EXPORT_SYMBOL(drm_syncobj_find_fence);
 
 static void drm_syncobj_timeline_fini(struct drm_syncobj *syncobj,
@@ -578,7 +580,6 @@ void drm_syncobj_free(struct kref *kref)
 	struct drm_syncobj *syncobj = container_of(kref,
 						   struct drm_syncobj,
 						   refcount);
-	drm_syncobj_replace_fence(syncobj, 0, NULL);
 	drm_syncobj_timeline_fini(syncobj, &syncobj->syncobj_timeline);
 	kfree(syncobj);
 }
@@ -1031,14 +1032,11 @@ static signed long drm_syncobj_array_wait_timeout(struct drm_syncobj **syncobjs,
 	signaled_count = 0;
 	for (i = 0; i < count; ++i) {
 		entries[i].task = current;
-		entries[i].fence = drm_syncobj_fence_get(syncobjs[i]);
+		ret = drm_syncobj_search_fence(syncobjs[i], 0, 0,
+					       &entries[i].fence);
 		if (!entries[i].fence) {
-			if (flags & DRM_SYNCOBJ_WAIT_FLAGS_WAIT_FOR_SUBMIT) {
-				continue;
-			} else {
-				ret = -EINVAL;
-				goto cleanup_entries;
-			}
+			ret = -EINVAL;
+			goto cleanup_entries;
 		}
 
 		if (dma_fence_is_signaled(entries[i].fence)) {
@@ -1066,15 +1064,6 @@ static signed long drm_syncobj_array_wait_timeout(struct drm_syncobj **syncobjs,
 	 * fallthough and try a 0 timeout wait!
 	 */
 
-	if (flags & DRM_SYNCOBJ_WAIT_FLAGS_WAIT_FOR_SUBMIT) {
-		for (i = 0; i < count; ++i) {
-			drm_syncobj_fence_get_or_add_callback(syncobjs[i],
-							      &entries[i].fence,
-							      &entries[i].syncobj_cb,
-							      syncobj_wait_syncobj_func);
-		}
-	}
-
 	do {
 		set_current_state(TASK_INTERRUPTIBLE);
 
@@ -1122,13 +1111,10 @@ static signed long drm_syncobj_array_wait_timeout(struct drm_syncobj **syncobjs,
 
 cleanup_entries:
 	for (i = 0; i < count; ++i) {
-		if (entries[i].syncobj_cb.func)
-			drm_syncobj_remove_callback(syncobjs[i],
-						    &entries[i].syncobj_cb);
+		dma_fence_put(entries[i].fence);
 		if (entries[i].fence_cb.func)
 			dma_fence_remove_callback(entries[i].fence,
 						  &entries[i].fence_cb);
-		dma_fence_put(entries[i].fence);
 	}
 	kfree(entries);
 
@@ -1303,12 +1289,17 @@ drm_syncobj_reset_ioctl(struct drm_device *dev, void *data,
 	if (ret < 0)
 		return ret;
 
-	for (i = 0; i < args->count_handles; i++)
-		drm_syncobj_replace_fence(syncobjs[i], 0, NULL);
-
+	for (i = 0; i < args->count_handles; i++) {
+		if (syncobjs[i]->type == DRM_SYNCOBJ_TYPE_TIMELINE) {
+			DRM_ERROR("timeline syncobj cannot reset!\n");
+			ret = -EINVAL;
+			goto out;
+		}
+	}
+out:
 	drm_syncobj_array_free(syncobjs, args->count_handles);
 
-	return 0;
+	return ret;
 }
 
 int
-- 
2.17.1



More information about the dri-devel mailing list