aboutsummaryrefslogtreecommitdiffstats
path: root/include/gk20a/fence_gk20a.c
diff options
context:
space:
mode:
authorJoshua Bakita <bakitajoshua@gmail.com>2023-06-28 18:24:25 -0400
committerJoshua Bakita <bakitajoshua@gmail.com>2023-06-28 18:24:25 -0400
commit01e6fac4d61fdd7fff5433942ec93fc2ea1e4df1 (patch)
tree4ef34501728a087be24f4ba0af90f91486bf780b /include/gk20a/fence_gk20a.c
parent306a03d18b305e4e573be3b2931978fa10679eb9 (diff)
Include nvgpu headers
These are needed to build on NVIDIA's Jetson boards for the time being. Only a couple structs are required, so it should be fairly easy to remove this dependency at some point in the future.
Diffstat (limited to 'include/gk20a/fence_gk20a.c')
-rw-r--r--include/gk20a/fence_gk20a.c319
1 files changed, 319 insertions, 0 deletions
diff --git a/include/gk20a/fence_gk20a.c b/include/gk20a/fence_gk20a.c
new file mode 100644
index 0000000..af42130
--- /dev/null
+++ b/include/gk20a/fence_gk20a.c
@@ -0,0 +1,319 @@
1/*
2 * Copyright (c) 2014-2018, NVIDIA CORPORATION. All rights reserved.
3 *
4 * Permission is hereby granted, free of charge, to any person obtaining a
5 * copy of this software and associated documentation files (the "Software"),
6 * to deal in the Software without restriction, including without limitation
7 * the rights to use, copy, modify, merge, publish, distribute, sublicense,
8 * and/or sell copies of the Software, and to permit persons to whom the
9 * Software is furnished to do so, subject to the following conditions:
10 *
11 * The above copyright notice and this permission notice shall be included in
12 * all copies or substantial portions of the Software.
13 *
14 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
15 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
16 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
17 * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
18 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
19 * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
20 * DEALINGS IN THE SOFTWARE.
21 */
22
23#include "fence_gk20a.h"
24
25#include <nvgpu/semaphore.h>
26#include <nvgpu/kmem.h>
27#include <nvgpu/soc.h>
28#include <nvgpu/nvhost.h>
29#include <nvgpu/barrier.h>
30#include <nvgpu/os_fence.h>
31#include <nvgpu/channel.h>
32
33#include "gk20a.h"
34
35struct gk20a_fence_ops {
36 int (*wait)(struct gk20a_fence *, long timeout);
37 bool (*is_expired)(struct gk20a_fence *);
38 void *(*free)(struct nvgpu_ref *);
39};
40
41static void gk20a_fence_free(struct nvgpu_ref *ref)
42{
43 struct gk20a_fence *f =
44 container_of(ref, struct gk20a_fence, ref);
45 struct gk20a *g = f->g;
46
47 if (nvgpu_os_fence_is_initialized(&f->os_fence)) {
48 f->os_fence.ops->drop_ref(&f->os_fence);
49 }
50
51 if (f->semaphore) {
52 nvgpu_semaphore_put(f->semaphore);
53 }
54
55 if (f->allocator) {
56 if (nvgpu_alloc_initialized(f->allocator)) {
57 nvgpu_free(f->allocator, (u64)(uintptr_t)f);
58 }
59 } else {
60 nvgpu_kfree(g, f);
61 }
62}
63
64void gk20a_fence_put(struct gk20a_fence *f)
65{
66 if (f) {
67 nvgpu_ref_put(&f->ref, gk20a_fence_free);
68 }
69}
70
71struct gk20a_fence *gk20a_fence_get(struct gk20a_fence *f)
72{
73 if (f) {
74 nvgpu_ref_get(&f->ref);
75 }
76 return f;
77}
78
79inline bool gk20a_fence_is_valid(struct gk20a_fence *f)
80{
81 bool valid = f->valid;
82
83 nvgpu_smp_rmb();
84 return valid;
85}
86
87int gk20a_fence_install_fd(struct gk20a_fence *f, int fd)
88{
89 if (!f || !gk20a_fence_is_valid(f) ||
90 !nvgpu_os_fence_is_initialized(&f->os_fence)) {
91 return -EINVAL;
92 }
93
94 f->os_fence.ops->install_fence(&f->os_fence, fd);
95
96 return 0;
97}
98
99int gk20a_fence_wait(struct gk20a *g, struct gk20a_fence *f,
100 unsigned long timeout)
101{
102 if (f && gk20a_fence_is_valid(f)) {
103 if (!nvgpu_platform_is_silicon(g)) {
104 timeout = MAX_SCHEDULE_TIMEOUT;
105 }
106 return f->ops->wait(f, timeout);
107 }
108 return 0;
109}
110
111bool gk20a_fence_is_expired(struct gk20a_fence *f)
112{
113 if (f && gk20a_fence_is_valid(f) && f->ops) {
114 return f->ops->is_expired(f);
115 } else {
116 return true;
117 }
118}
119
120int gk20a_alloc_fence_pool(struct channel_gk20a *c, unsigned int count)
121{
122 int err;
123 size_t size;
124 struct gk20a_fence *fence_pool = NULL;
125
126 size = sizeof(struct gk20a_fence);
127 if (count <= UINT_MAX / size) {
128 size = count * size;
129 fence_pool = nvgpu_vzalloc(c->g, size);
130 }
131
132 if (!fence_pool) {
133 return -ENOMEM;
134 }
135
136 err = nvgpu_lockless_allocator_init(c->g, &c->fence_allocator,
137 "fence_pool", (size_t)fence_pool, size,
138 sizeof(struct gk20a_fence), 0);
139 if (err) {
140 goto fail;
141 }
142
143 return 0;
144
145fail:
146 nvgpu_vfree(c->g, fence_pool);
147 return err;
148}
149
150void gk20a_free_fence_pool(struct channel_gk20a *c)
151{
152 if (nvgpu_alloc_initialized(&c->fence_allocator)) {
153 struct gk20a_fence *fence_pool;
154 fence_pool = (struct gk20a_fence *)(uintptr_t)
155 nvgpu_alloc_base(&c->fence_allocator);
156 nvgpu_alloc_destroy(&c->fence_allocator);
157 nvgpu_vfree(c->g, fence_pool);
158 }
159}
160
161struct gk20a_fence *gk20a_alloc_fence(struct channel_gk20a *c)
162{
163 struct gk20a_fence *fence = NULL;
164
165 if (channel_gk20a_is_prealloc_enabled(c)) {
166 if (nvgpu_alloc_initialized(&c->fence_allocator)) {
167 fence = (struct gk20a_fence *)(uintptr_t)
168 nvgpu_alloc(&c->fence_allocator,
169 sizeof(struct gk20a_fence));
170
171 /* clear the node and reset the allocator pointer */
172 if (fence) {
173 memset(fence, 0, sizeof(*fence));
174 fence->allocator = &c->fence_allocator;
175 }
176 }
177 } else {
178 fence = nvgpu_kzalloc(c->g, sizeof(struct gk20a_fence));
179 }
180
181 if (fence) {
182 nvgpu_ref_init(&fence->ref);
183 fence->g = c->g;
184 }
185
186 return fence;
187}
188
189void gk20a_init_fence(struct gk20a_fence *f,
190 const struct gk20a_fence_ops *ops,
191 struct nvgpu_os_fence os_fence)
192{
193 if (!f) {
194 return;
195 }
196 f->ops = ops;
197 f->syncpt_id = -1;
198 f->semaphore = NULL;
199 f->os_fence = os_fence;
200}
201
202/* Fences that are backed by GPU semaphores: */
203
204static int nvgpu_semaphore_fence_wait(struct gk20a_fence *f, long timeout)
205{
206 if (!nvgpu_semaphore_is_acquired(f->semaphore)) {
207 return 0;
208 }
209
210 return NVGPU_COND_WAIT_INTERRUPTIBLE(
211 f->semaphore_wq,
212 !nvgpu_semaphore_is_acquired(f->semaphore),
213 timeout);
214}
215
216static bool nvgpu_semaphore_fence_is_expired(struct gk20a_fence *f)
217{
218 return !nvgpu_semaphore_is_acquired(f->semaphore);
219}
220
221static const struct gk20a_fence_ops nvgpu_semaphore_fence_ops = {
222 .wait = &nvgpu_semaphore_fence_wait,
223 .is_expired = &nvgpu_semaphore_fence_is_expired,
224};
225
226/* This function takes ownership of the semaphore as well as the os_fence */
227int gk20a_fence_from_semaphore(
228 struct gk20a_fence *fence_out,
229 struct nvgpu_semaphore *semaphore,
230 struct nvgpu_cond *semaphore_wq,
231 struct nvgpu_os_fence os_fence)
232{
233 struct gk20a_fence *f = fence_out;
234
235 gk20a_init_fence(f, &nvgpu_semaphore_fence_ops, os_fence);
236 if (!f) {
237 return -EINVAL;
238 }
239
240
241 f->semaphore = semaphore;
242 f->semaphore_wq = semaphore_wq;
243
244 /* commit previous writes before setting the valid flag */
245 nvgpu_smp_wmb();
246 f->valid = true;
247
248 return 0;
249}
250
251#ifdef CONFIG_TEGRA_GK20A_NVHOST
252/* Fences that are backed by host1x syncpoints: */
253
254static int gk20a_syncpt_fence_wait(struct gk20a_fence *f, long timeout)
255{
256 return nvgpu_nvhost_syncpt_wait_timeout_ext(
257 f->nvhost_dev, f->syncpt_id, f->syncpt_value,
258 (u32)timeout, NULL, NULL);
259}
260
261static bool gk20a_syncpt_fence_is_expired(struct gk20a_fence *f)
262{
263
264 /*
265 * In cases we don't register a notifier, we can't expect the
266 * syncpt value to be updated. For this case, we force a read
267 * of the value from HW, and then check for expiration.
268 */
269 if (!nvgpu_nvhost_syncpt_is_expired_ext(f->nvhost_dev, f->syncpt_id,
270 f->syncpt_value)) {
271 u32 val;
272
273 if (!nvgpu_nvhost_syncpt_read_ext_check(f->nvhost_dev,
274 f->syncpt_id, &val)) {
275 return nvgpu_nvhost_syncpt_is_expired_ext(
276 f->nvhost_dev,
277 f->syncpt_id, f->syncpt_value);
278 }
279 }
280
281 return true;
282}
283
284static const struct gk20a_fence_ops gk20a_syncpt_fence_ops = {
285 .wait = &gk20a_syncpt_fence_wait,
286 .is_expired = &gk20a_syncpt_fence_is_expired,
287};
288
289/* This function takes the ownership of the os_fence */
290int gk20a_fence_from_syncpt(
291 struct gk20a_fence *fence_out,
292 struct nvgpu_nvhost_dev *nvhost_dev,
293 u32 id, u32 value, struct nvgpu_os_fence os_fence)
294{
295 struct gk20a_fence *f = fence_out;
296
297 gk20a_init_fence(f, &gk20a_syncpt_fence_ops, os_fence);
298 if (!f)
299 return -EINVAL;
300
301 f->nvhost_dev = nvhost_dev;
302 f->syncpt_id = id;
303 f->syncpt_value = value;
304
305 /* commit previous writes before setting the valid flag */
306 nvgpu_smp_wmb();
307 f->valid = true;
308
309 return 0;
310}
311#else
312int gk20a_fence_from_syncpt(
313 struct gk20a_fence *fence_out,
314 struct nvgpu_nvhost_dev *nvhost_dev,
315 u32 id, u32 value, struct nvgpu_os_fence os_fence)
316{
317 return -EINVAL;
318}
319#endif