drm/syncobj: add new drm_syncobj_add_point interface v4
authorChristian König <ckoenig.leichtzumerken@gmail.com>
Mon, 1 Apr 2019 09:50:56 +0000 (17:50 +0800)
committerChristian König <christian.koenig@amd.com>
Mon, 1 Apr 2019 10:05:53 +0000 (12:05 +0200)
Use the dma_fence_chain object to create a timeline of fence objects
instead of just replacing the existing fence.

v2: rebase and cleanup
v3: fix garbage collection parameters
v4: add unorder point check, print a warn calltrace

Signed-off-by: Christian König <christian.koenig@amd.com>
Reviewed-by: Lionel Landwerlin <lionel.g.landwerlin@intel.com>
Link: https://patchwork.freedesktop.org/patch/295780/?series=58813&rev=1
drivers/gpu/drm/drm_syncobj.c
include/drm/drm_syncobj.h

index 5329e66598c63dda8d4cccb5163064438ae9af25..dbe4a1c75fbc54214b83605ae29235e9b5a5618e 100644 (file)
@@ -122,6 +122,46 @@ static void drm_syncobj_remove_wait(struct drm_syncobj *syncobj,
        spin_unlock(&syncobj->lock);
 }
 
+/**
+ * drm_syncobj_add_point - add new timeline point to the syncobj
+ * @syncobj: sync object to add timeline point do
+ * @chain: chain node to use to add the point
+ * @fence: fence to encapsulate in the chain node
+ * @point: sequence number to use for the point
+ *
+ * Add the chain node as new timeline point to the syncobj.
+ */
+void drm_syncobj_add_point(struct drm_syncobj *syncobj,
+                          struct dma_fence_chain *chain,
+                          struct dma_fence *fence,
+                          uint64_t point)
+{
+       struct syncobj_wait_entry *cur, *tmp;
+       struct dma_fence *prev;
+
+       dma_fence_get(fence);
+
+       spin_lock(&syncobj->lock);
+
+       prev = drm_syncobj_fence_get(syncobj);
+       /* You are adding an unorder point to timeline, which could cause payload returned from query_ioctl is 0! */
+       if (prev && prev->seqno >= point)
+               DRM_ERROR("You are adding an unorder point to timeline!\n");
+       dma_fence_chain_init(chain, prev, fence, point);
+       rcu_assign_pointer(syncobj->fence, &chain->base);
+
+       list_for_each_entry_safe(cur, tmp, &syncobj->cb_list, node) {
+               list_del_init(&cur->node);
+               syncobj_wait_syncobj_func(syncobj, cur);
+       }
+       spin_unlock(&syncobj->lock);
+
+       /* Walk the chain once to trigger garbage collection */
+       dma_fence_chain_for_each(fence, prev);
+       dma_fence_put(prev);
+}
+EXPORT_SYMBOL(drm_syncobj_add_point);
+
 /**
  * drm_syncobj_replace_fence - replace fence in a sync object.
  * @syncobj: Sync object to replace fence in
index 0311c9fdbd2f2107ba39cf40dd64a0f97641b416..6cf7243a1dc5e1ed53f99cf6dafda44a76b55ab8 100644 (file)
@@ -27,6 +27,7 @@
 #define __DRM_SYNCOBJ_H__
 
 #include <linux/dma-fence.h>
+#include <linux/dma-fence-chain.h>
 
 struct drm_file;
 
@@ -112,6 +113,10 @@ drm_syncobj_fence_get(struct drm_syncobj *syncobj)
 
 struct drm_syncobj *drm_syncobj_find(struct drm_file *file_private,
                                     u32 handle);
+void drm_syncobj_add_point(struct drm_syncobj *syncobj,
+                          struct dma_fence_chain *chain,
+                          struct dma_fence *fence,
+                          uint64_t point);
 void drm_syncobj_replace_fence(struct drm_syncobj *syncobj,
                               struct dma_fence *fence);
 int drm_syncobj_find_fence(struct drm_file *file_private,