1 /*
2 * drm_sync_helper.h: software fence and helper functions for fences and
3 * reservations used for dma buffer access synchronization between drivers.
4 *
5 * Copyright 2014 Google, Inc.
6 *
7 * This software is licensed under the terms of the GNU General Public
8 * License version 2, as published by the Free Software Foundation, and
9 * may be copied, distributed, and modified under those terms.
10 *
11 * This program is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 * GNU General Public License for more details.
15 */
16
17 #ifndef _DRM_SYNC_HELPER_H_
18 #define _DRM_SYNC_HELPER_H_
19
20 #include <linux/fence.h>
21 #include <linux/reservation.h>
22 #include <linux/atomic.h>
23 #include <linux/workqueue.h>
24
25 /**
26 * Create software fence
27 * @context: execution context
28 * @seqno: the sequence number of this fence inside the execution context
29 */
30 struct fence *drm_sw_fence_new(unsigned int context, unsigned seqno);
31
32 /**
33 * Signal and decrease reference count for a fence if it exists
34 * @fence: fence to signal
35 *
36 * Utility function called when owner access to object associated with fence is
37 * finished (e.g. GPU done with rendering).
38 */
drm_fence_signal_and_put(struct fence **fence)39 static inline void drm_fence_signal_and_put(struct fence **fence)
40 {
41 if (*fence) {
42 fence_signal(*fence);
43 fence_put(*fence);
44 *fence = NULL;
45 }
46 }
47
48 struct drm_reservation_cb;
49
50 struct drm_reservation_fence_cb {
51 struct fence_cb base;
52 struct drm_reservation_cb *parent;
53 struct fence *fence;
54 };
55
56 /**
57 * Callback executed when all fences in reservation callback are signaled
58 * @rcb: reservation callback structure
59 * @context: context provided by user at init time
60 */
61 typedef void (*drm_reservation_cb_func_t)(struct drm_reservation_cb *rcb, void *context);
62
63 /**
64 * Reservation callback structure
65 * @work: work context in which func is executed
66 * @fence_cbs: fence callbacks array
67 * @num_fence_cbs: number of fence callbacks
68 * @count: count of signaled fences, when it drops to 0 func is called
69 * @func: callback to execute when all fences are signaled
70 * @context: context provided by user during initialization
71 *
72 * It is safe and expected that func will destroy this structure before
73 * returning.
74 */
75 struct drm_reservation_cb {
76 struct work_struct work;
77 struct drm_reservation_fence_cb **fence_cbs;
78 unsigned num_fence_cbs;
79 atomic_t count;
80 void *context;
81 drm_reservation_cb_func_t func;
82 };
83
84 /**
85 * Initialize reservation callback
86 * @rcb: reservation callback structure to initialize
87 * @func: function to call when all fences are signaled
88 * @context: parameter to call func with
89 */
90 void drm_reservation_cb_init(struct drm_reservation_cb *rcb, drm_reservation_cb_func_t func, void *context);
91
92 /**
93 * Add fences from reservation object to callback
94 * @rcb: reservation callback structure
95 * @resv: reservation object
96 * @exclusive: (for exclusive wait) when true add all fences, otherwise only
97 * exclusive fence
98 */
99 int drm_reservation_cb_add(struct drm_reservation_cb *rcb, struct reservation_object *resv, bool exclusive);
100
101 /**
102 * Finish adding fences
103 * @rcb: reservation callback structure
104 *
105 * It will trigger callback worker if all fences were signaled before.
106 */
107 void drm_reservation_cb_done(struct drm_reservation_cb *rcb);
108
109 /**
110 * Cleanup reservation callback structure
111 * @rcb: reservation callback structure
112 *
113 * Can be called to cancel primed reservation callback.
114 */
115 void drm_reservation_cb_fini(struct drm_reservation_cb *rcb);
116
117 /**
118 * Add reservation to array of reservations
119 * @resv: reservation to add
120 * @resvs: array of reservations
121 * @excl_resvs_bitmap: bitmap for exclusive reservations
122 * @num_resvs: number of reservations in array
123 * @exclusive: bool to store in excl_resvs_bitmap
124 */
125 void drm_add_reservation(struct reservation_object *resv, struct reservation_object **resvs,
126 unsigned long *excl_resvs_bitmap, unsigned int *num_resvs, bool exclusive);
127
128 /**
129 * Acquire ww_mutex lock on all reservations in the array
130 * @resvs: array of reservations
131 * @num_resvs: number of reservations in the array
132 * @ctx: ww mutex context
133 */
134 int drm_lock_reservations(struct reservation_object **resvs, unsigned int num_resvs, struct ww_acquire_ctx *ctx);
135
136 /**
137 * Release ww_mutex lock on all reservations in the array
138 * @resvs: array of reservations
139 * @num_resvs: number of reservations in the array
140 * @ctx: ww mutex context
141 */
142 void drm_unlock_reservations(struct reservation_object **resvs, unsigned int num_resvs, struct ww_acquire_ctx *ctx);
143
144 #endif
145