[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