2 * Copyright (C) 2011-2012 ARM Limited. All rights reserved.
4 * This program is free software and is provided to you under the terms of the GNU General Public License version 2
5 * as published by the Free Software Foundation, and any use by you of this program is subject to the terms of such GNU licence.
7 * A copy of the licence is included with the program, and can also be obtained from Free Software
8 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
16 #include <linux/seq_file.h>
17 #include <linux/sync.h>
20 #include "mali_kernel_common.h"
22 struct mali_sync_timeline
24 struct sync_timeline timeline;
36 static inline struct mali_sync_timeline *to_mali_sync_timeline(struct sync_timeline *timeline)
38 return container_of(timeline, struct mali_sync_timeline, timeline);
41 static inline struct mali_sync_pt *to_mali_sync_pt(struct sync_pt *pt)
43 return container_of(pt, struct mali_sync_pt, pt);
46 static struct sync_pt *timeline_dup(struct sync_pt *pt)
48 struct mali_sync_pt *mpt = to_mali_sync_pt(pt);
49 struct mali_sync_pt *new_mpt;
50 struct sync_pt *new_pt = sync_pt_create(pt->parent, sizeof(struct mali_sync_pt));
57 new_mpt = to_mali_sync_pt(new_pt);
58 new_mpt->order = mpt->order;
64 static int timeline_has_signaled(struct sync_pt *pt)
66 struct mali_sync_pt *mpt = to_mali_sync_pt(pt);
67 struct mali_sync_timeline *mtl = to_mali_sync_timeline(pt->parent);
75 diff = atomic_read(&mtl->signalled) - mpt->order;
80 static int timeline_compare(struct sync_pt *a, struct sync_pt *b)
82 struct mali_sync_pt *ma = container_of(a, struct mali_sync_pt, pt);
83 struct mali_sync_pt *mb = container_of(b, struct mali_sync_pt, pt);
85 long diff = ma->order - mb->order;
101 static void timeline_print_tl(struct seq_file *s, struct sync_timeline *sync_timeline)
103 struct mali_sync_timeline *mtl = to_mali_sync_timeline(sync_timeline);
105 seq_printf(s, "%u, %u", atomic_read(&mtl->signalled), atomic_read(&mtl->counter));
108 static void timeline_print_pt(struct seq_file *s, struct sync_pt *sync_pt)
110 struct mali_sync_pt *mpt = to_mali_sync_pt(sync_pt);
112 seq_printf(s, "%u", mpt->order);
116 static struct sync_timeline_ops mali_timeline_ops = {
117 .driver_name = "Mali",
119 .has_signaled = timeline_has_signaled,
120 .compare = timeline_compare,
121 .print_obj = timeline_print_tl,
122 .print_pt = timeline_print_pt
125 int mali_sync_timeline_is_ours(struct sync_timeline *timeline)
127 return (timeline->ops == &mali_timeline_ops);
130 struct sync_timeline *mali_sync_timeline_alloc(const char * name)
132 struct sync_timeline *tl;
133 struct mali_sync_timeline *mtl;
135 tl = sync_timeline_create(&mali_timeline_ops,
136 sizeof(struct mali_sync_timeline), name);
142 /* Set the counter in our private struct */
143 mtl = to_mali_sync_timeline(tl);
144 atomic_set(&mtl->counter, 0);
145 atomic_set(&mtl->signalled, 0);
150 struct sync_pt *mali_sync_pt_alloc(struct sync_timeline *parent)
152 struct sync_pt *pt = sync_pt_create(parent, sizeof(struct mali_sync_pt));
153 struct mali_sync_timeline *mtl = to_mali_sync_timeline(parent);
154 struct mali_sync_pt *mpt;
161 mpt = to_mali_sync_pt(pt);
162 mpt->order = atomic_inc_return(&mtl->counter);
168 void mali_sync_signal_pt(struct sync_pt *pt, int error)
170 struct mali_sync_pt *mpt = to_mali_sync_pt(pt);
171 struct mali_sync_timeline *mtl = to_mali_sync_timeline(pt->parent);
177 MALI_DEBUG_ASSERT(0 > error);
183 signalled = atomic_read(&mtl->signalled);
185 diff = signalled - mpt->order;
189 /* The timeline is already at or ahead of this point. This should not happen unless userspace
190 * has been signalling fences out of order, so warn but don't violate the sync_pt API.
191 * The warning is only in debug builds to prevent a malicious user being able to spam dmesg.
193 MALI_DEBUG_PRINT_ERROR(("Sync points were triggerd in a different order to allocation!\n"));
196 } while (atomic_cmpxchg(&mtl->signalled, signalled, mpt->order) != signalled);
198 sync_timeline_signal(pt->parent);