aboutsummaryrefslogtreecommitdiff
path: root/drivers/staging/android/sync.c
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/staging/android/sync.c')
-rw-r--r--drivers/staging/android/sync.c50
1 files changed, 31 insertions, 19 deletions
diff --git a/drivers/staging/android/sync.c b/drivers/staging/android/sync.c
index 3893a357476..18174f7c871 100644
--- a/drivers/staging/android/sync.c
+++ b/drivers/staging/android/sync.c
@@ -79,27 +79,31 @@ static void sync_timeline_free(struct kref *kref)
container_of(kref, struct sync_timeline, kref);
unsigned long flags;
- if (obj->ops->release_obj)
- obj->ops->release_obj(obj);
-
spin_lock_irqsave(&sync_timeline_list_lock, flags);
list_del(&obj->sync_timeline_list);
spin_unlock_irqrestore(&sync_timeline_list_lock, flags);
+ if (obj->ops->release_obj)
+ obj->ops->release_obj(obj);
+
kfree(obj);
}
void sync_timeline_destroy(struct sync_timeline *obj)
{
obj->destroyed = true;
+ /*
+ * Ensure timeline is marked as destroyed before
+ * changing timeline's fences status.
+ */
+ smp_wmb();
/*
- * If this is not the last reference, signal any children
- * that their parent is going away.
+ * signal any children that their parent is going away.
*/
+ sync_timeline_signal(obj);
- if (!kref_put(&obj->kref, sync_timeline_free))
- sync_timeline_signal(obj);
+ kref_put(&obj->kref, sync_timeline_free);
}
EXPORT_SYMBOL(sync_timeline_destroy);
@@ -125,9 +129,9 @@ static void sync_timeline_remove_pt(struct sync_pt *pt)
spin_unlock_irqrestore(&obj->active_list_lock, flags);
spin_lock_irqsave(&obj->child_list_lock, flags);
- if (!list_empty(&pt->child_list)) {
+ if (!list_empty(&pt->child_list))
list_del_init(&pt->child_list);
- }
+
spin_unlock_irqrestore(&obj->child_list_lock, flags);
}
@@ -384,6 +388,7 @@ static void sync_fence_detach_pts(struct sync_fence *fence)
list_for_each_safe(pos, n, &fence->pt_list_head) {
struct sync_pt *pt = container_of(pos, struct sync_pt, pt_list);
+
sync_timeline_remove_pt(pt);
}
}
@@ -394,6 +399,7 @@ static void sync_fence_free_pts(struct sync_fence *fence)
list_for_each_safe(pos, n, &fence->pt_list_head) {
struct sync_pt *pt = container_of(pos, struct sync_pt, pt_list);
+
sync_pt_free(pt);
}
}
@@ -697,7 +703,7 @@ static long sync_fence_ioctl_wait(struct sync_fence *fence, unsigned long arg)
static long sync_fence_ioctl_merge(struct sync_fence *fence, unsigned long arg)
{
- int fd = get_unused_fd();
+ int fd = get_unused_fd_flags(O_CLOEXEC);
int err;
struct sync_fence *fence2, *fence3;
struct sync_merge_data data;
@@ -827,6 +833,7 @@ static long sync_fence_ioctl(struct file *file, unsigned int cmd,
unsigned long arg)
{
struct sync_fence *fence = file->private_data;
+
switch (cmd) {
case SYNC_IOC_WAIT:
return sync_fence_ioctl_wait(fence, arg);
@@ -856,18 +863,21 @@ 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 = pt->status;
+
seq_printf(s, " %s%spt %s",
fence ? pt->parent->name : "",
fence ? "_" : "",
sync_status_str(status));
if (pt->status) {
struct timeval tv = ktime_to_timeval(pt->timestamp);
+
seq_printf(s, "@%ld.%06ld", tv.tv_sec, tv.tv_usec);
}
if (pt->parent->ops->timeline_value_str &&
pt->parent->ops->pt_value_str) {
char value[64];
+
pt->parent->ops->pt_value_str(pt, value, sizeof(value));
seq_printf(s, ": %s", value);
if (fence) {
@@ -876,11 +886,11 @@ static void sync_print_pt(struct seq_file *s, struct sync_pt *pt, bool fence)
seq_printf(s, " / %s", value);
}
} else if (pt->parent->ops->print_pt) {
- seq_printf(s, ": ");
+ seq_puts(s, ": ");
pt->parent->ops->print_pt(s, pt);
}
- seq_printf(s, "\n");
+ seq_puts(s, "\n");
}
static void sync_print_obj(struct seq_file *s, struct sync_timeline *obj)
@@ -892,14 +902,15 @@ static void sync_print_obj(struct seq_file *s, struct sync_timeline *obj)
if (obj->ops->timeline_value_str) {
char value[64];
+
obj->ops->timeline_value_str(obj, value, sizeof(value));
seq_printf(s, ": %s", value);
} else if (obj->ops->print_obj) {
- seq_printf(s, ": ");
+ seq_puts(s, ": ");
obj->ops->print_obj(s, obj);
}
- seq_printf(s, "\n");
+ seq_puts(s, "\n");
spin_lock_irqsave(&obj->child_list_lock, flags);
list_for_each(pos, &obj->child_list_head) {
@@ -940,7 +951,7 @@ static int sync_debugfs_show(struct seq_file *s, void *unused)
unsigned long flags;
struct list_head *pos;
- seq_printf(s, "objs:\n--------------\n");
+ seq_puts(s, "objs:\n--------------\n");
spin_lock_irqsave(&sync_timeline_list_lock, flags);
list_for_each(pos, &sync_timeline_list_head) {
@@ -949,11 +960,11 @@ static int sync_debugfs_show(struct seq_file *s, void *unused)
sync_timeline_list);
sync_print_obj(s, obj);
- seq_printf(s, "\n");
+ seq_puts(s, "\n");
}
spin_unlock_irqrestore(&sync_timeline_list_lock, flags);
- seq_printf(s, "fences:\n--------------\n");
+ seq_puts(s, "fences:\n--------------\n");
spin_lock_irqsave(&sync_fence_list_lock, flags);
list_for_each(pos, &sync_fence_list_head) {
@@ -961,7 +972,7 @@ static int sync_debugfs_show(struct seq_file *s, void *unused)
container_of(pos, struct sync_fence, sync_fence_list);
sync_print_fence(s, fence);
- seq_printf(s, "\n");
+ seq_puts(s, "\n");
}
spin_unlock_irqrestore(&sync_fence_list_lock, flags);
return 0;
@@ -988,7 +999,7 @@ late_initcall(sync_debugfs_init);
#define DUMP_CHUNK 256
static char sync_dump_buf[64 * 1024];
-void sync_dump(void)
+static void sync_dump(void)
{
struct seq_file s = {
.buf = sync_dump_buf,
@@ -1001,6 +1012,7 @@ void sync_dump(void)
for (i = 0; i < s.count; i += DUMP_CHUNK) {
if ((s.count - i) > DUMP_CHUNK) {
char c = s.buf[i + DUMP_CHUNK];
+
s.buf[i + DUMP_CHUNK] = 0;
pr_cont("%s", s.buf + i);
s.buf[i + DUMP_CHUNK] = c;