@@ -185,8 +185,10 @@ int fence_add_callback(struct fence *fence, struct fence_cb *cb,
if (WARN_ON(!fence || !func))
return -EINVAL;
- if (test_bit(FENCE_FLAG_SIGNALED_BIT, &fence->flags))
+ if (test_bit(FENCE_FLAG_SIGNALED_BIT, &fence->flags)) {
+ LIST_INIT_HEAD(&cb->node);
return -ENOENT;
+ }
spin_lock_irqsave(fence->lock, flags);
@@ -202,7 +204,8 @@ int fence_add_callback(struct fence *fence, struct fence_cb *cb,
if (!ret) {
cb->func = func;
list_add_tail(&cb->node, &fence->cb_list);
- }
+ } else
+ LIST_INIT_HEAD(&cb->node);
spin_unlock_irqrestore(fence->lock, flags);
return ret;
@@ -74,6 +74,16 @@ static void sync_timeline_free(struct kref *kref)
kfree(obj);
}
+static void sync_timeline_get(struct sync_timeline *obj)
+{
+ kref_get(&obj->kref);
+}
+
+static void sync_timeline_put(struct sync_timeline *obj)
+{
+ kref_put(&obj->kref, sync_timeline_free);
+}
+
void sync_timeline_destroy(struct sync_timeline *obj)
{
obj->destroyed = true;
@@ -83,8 +93,8 @@ void sync_timeline_destroy(struct sync_timeline *obj)
* that their parent is going away.
*/
- if (!kref_put(&obj->kref, sync_timeline_free))
- sync_timeline_signal(obj);
+ sync_timeline_signal(obj);
+ sync_timeline_put(obj);
}
EXPORT_SYMBOL(sync_timeline_destroy);
@@ -98,12 +108,8 @@ void sync_timeline_signal(struct sync_timeline *obj)
spin_lock_irqsave(&obj->child_list_lock, flags);
list_for_each_entry_safe(pt, next, &obj->active_list_head, active_list) {
- if (!pt->base.ops->signaled(&pt->base))
- break;
- else {
- __fence_signal(&pt->base);
+ if (__fence_is_signaled(&pt->base))
list_del(&pt->active_list);
- }
}
spin_unlock_irqrestore(&obj->child_list_lock, flags);
}
@@ -122,6 +128,7 @@ struct sync_pt *sync_pt_create(struct sync_timeline *obj, int size)
return NULL;
spin_lock_irqsave(&obj->child_list_lock, flags);
+ sync_timeline_get(obj);
__fence_init(&pt->base, &android_fence_ops, &obj->child_list_lock, obj->context, ++obj->value);
list_add_tail(&pt->child_list, &obj->child_list_head);
INIT_LIST_HEAD(&pt->active_list);
@@ -255,7 +262,7 @@ struct sync_fence *sync_fence_merge(const char *name,
fence_get(pt);
fence->cbs[a->num_fences + i].sync_pt = pt;
fence->cbs[a->num_fences + i].fence = fence;
- if (fence_add_callback(pt, &fence->cbs[i].cb, fence_check_cb_func))
+ if (fence_add_callback(pt, &fence->cbs[a->num_fences + i].cb, fence_check_cb_func))
atomic_dec(&fence->status);
}
@@ -325,6 +332,8 @@ int sync_fence_wait(struct sync_fence *fence, long timeout)
if (timeout < 0)
timeout = MAX_SCHEDULE_TIMEOUT;
+ else
+ timeout = msecs_to_jiffies(timeout);
trace_sync_wait(fence, 1);
for (i = 0; i < fence->num_fences; ++i)
@@ -383,6 +392,7 @@ static void android_fence_release(struct fence *fence)
if (parent->ops->free_pt)
parent->ops->free_pt(pt);
+ sync_timeline_put(parent);
kfree(pt);
}
@@ -82,18 +82,18 @@ static const char *sync_status_str(int status)
static void sync_print_pt(struct seq_file *s, struct sync_pt *pt, bool fence)
{
- int status = 0;
+ int status = 1;
struct sync_timeline *parent = sync_pt_parent(pt);
- if (fence_is_signaled(&pt->base)) {
+
+ if (__fence_is_signaled(&pt->base))
status = pt->base.status;
- if (!status)
- status = 1;
- }
+
seq_printf(s, " %s%spt %s",
fence ? parent->name : "",
fence ? "_" : "",
sync_status_str(status));
- if (status) {
+
+ if (status <= 0) {
struct timeval tv = ktime_to_timeval(pt->base.timestamp);
seq_printf(s, "@%ld.%06ld", tv.tv_sec, tv.tv_usec);
}
@@ -237,6 +237,20 @@ int fence_add_callback(struct fence *fence, struct fence_cb *cb,
bool fence_remove_callback(struct fence *fence, struct fence_cb *cb);
void fence_enable_sw_signaling(struct fence *fence);
+static inline bool
+__fence_is_signaled(struct fence *fence)
+{
+ if (test_bit(FENCE_FLAG_SIGNALED_BIT, &fence->flags))
+ return true;
+
+ if (fence->ops->signaled && fence->ops->signaled(fence)) {
+ __fence_signal(fence);
+ return true;
+ }
+
+ return false;
+}
+
/**
* fence_is_signaled - Return an indication if the fence is signaled yet.
* @fence: [in] the fence to check