1 /*
2 * Copyright 2023 Intel Corporation
3 * SPDX-License-Identifier: MIT
4 */
5
6 #include "intel_bind_timeline.h"
7
8 #include "drm-uapi/drm.h"
9 #include "intel_gem.h"
10
intel_bind_timeline_init(struct intel_bind_timeline * bind_timeline,int fd)11 bool intel_bind_timeline_init(struct intel_bind_timeline *bind_timeline, int fd)
12 {
13 struct drm_syncobj_create syncobj_create = { .flags = DRM_SYNCOBJ_CREATE_SIGNALED };
14
15 if (intel_ioctl(fd, DRM_IOCTL_SYNCOBJ_CREATE, &syncobj_create))
16 return false;
17
18 simple_mtx_init(&bind_timeline->mutex, mtx_plain);
19 bind_timeline->syncobj = syncobj_create.handle;
20 bind_timeline->point = 0;
21
22 return true;
23 }
24
intel_bind_timeline_finish(struct intel_bind_timeline * bind_timeline,int fd)25 void intel_bind_timeline_finish(struct intel_bind_timeline *bind_timeline, int fd)
26 {
27 if (bind_timeline->syncobj == 0)
28 return;
29
30 uint64_t point = intel_bind_timeline_get_last_point(bind_timeline);
31 struct drm_syncobj_timeline_wait syncobj_wait = {
32 .timeout_nsec = INT64_MAX,
33 .handles = (uintptr_t)&bind_timeline->syncobj,
34 .count_handles = 1,
35 .points = (uintptr_t)&point,
36 };
37 struct drm_syncobj_destroy syncobj_destroy = {
38 .handle = bind_timeline->syncobj,
39 };
40
41 /* Makes sure last unbind was signaled otherwise it can trigger job
42 * timeouts in KMD
43 */
44 intel_ioctl(fd, DRM_IOCTL_SYNCOBJ_TIMELINE_WAIT, &syncobj_wait);
45 intel_ioctl(fd, DRM_IOCTL_SYNCOBJ_DESTROY, &syncobj_destroy);
46
47 simple_mtx_destroy(&bind_timeline->mutex);
48 }
49
intel_bind_timeline_get_syncobj(struct intel_bind_timeline * bind_timeline)50 uint32_t intel_bind_timeline_get_syncobj(struct intel_bind_timeline *bind_timeline)
51 {
52 return bind_timeline->syncobj;
53 }
54
intel_bind_timeline_bind_begin(struct intel_bind_timeline * bind_timeline)55 uint64_t intel_bind_timeline_bind_begin(struct intel_bind_timeline *bind_timeline)
56 {
57 simple_mtx_lock(&bind_timeline->mutex);
58 return ++bind_timeline->point;
59 }
60
intel_bind_timeline_bind_end(struct intel_bind_timeline * bind_timeline)61 void intel_bind_timeline_bind_end(struct intel_bind_timeline *bind_timeline)
62 {
63 simple_mtx_unlock(&bind_timeline->mutex);
64 }
65
66 /*
67 * Returns the timeline point that should be waited on before execute any
68 * batch buffers.
69 */
intel_bind_timeline_get_last_point(struct intel_bind_timeline * bind_timeline)70 uint64_t intel_bind_timeline_get_last_point(struct intel_bind_timeline *bind_timeline)
71 {
72 uint64_t ret;
73
74 simple_mtx_lock(&bind_timeline->mutex);
75 ret = bind_timeline->point;
76 simple_mtx_unlock(&bind_timeline->mutex);
77
78 return ret;
79 }
80