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,
31 			unsigned seqno);
32 
33 /**
34  * Signal and decrease reference count for a fence if it exists
35  * @fence: fence to signal
36  *
37  * Utility function called when owner access to object associated with fence is
38  * finished (e.g. GPU done with rendering).
39  */
drm_fence_signal_and_put(struct fence **fence)40 static inline void drm_fence_signal_and_put(struct fence **fence)
41 {
42 	if (*fence) {
43 		fence_signal(*fence);
44 		fence_put(*fence);
45 		*fence = NULL;
46 	}
47 }
48 
49 struct drm_reservation_cb;
50 
51 struct drm_reservation_fence_cb {
52 	struct fence_cb base;
53 	struct drm_reservation_cb *parent;
54 	struct fence *fence;
55 };
56 
57 /**
58  * Callback executed when all fences in reservation callback are signaled
59  * @rcb: reservation callback structure
60  * @context: context provided by user at init time
61  */
62 typedef void (*drm_reservation_cb_func_t)(struct drm_reservation_cb *rcb,
63 					  void *context);
64 
65 /**
66  * Reservation callback structure
67  * @work: work context in which func is executed
68  * @fence_cbs: fence callbacks array
69  * @num_fence_cbs: number of fence callbacks
70  * @count: count of signaled fences, when it drops to 0 func is called
71  * @func: callback to execute when all fences are signaled
72  * @context: context provided by user during initialization
73  *
74  * It is safe and expected that func will destroy this structure before
75  * returning.
76  */
77 struct drm_reservation_cb {
78 	struct work_struct work;
79 	struct drm_reservation_fence_cb **fence_cbs;
80 	unsigned num_fence_cbs;
81 	atomic_t count;
82 	void *context;
83 	drm_reservation_cb_func_t func;
84 };
85 
86 /**
87  * Initialize reservation callback
88  * @rcb: reservation callback structure to initialize
89  * @func: function to call when all fences are signaled
90  * @context: parameter to call func with
91  */
92 void drm_reservation_cb_init(struct drm_reservation_cb *rcb,
93 			     drm_reservation_cb_func_t func,
94 			     void *context);
95 
96 /**
97  * Add fences from reservation object to callback
98  * @rcb: reservation callback structure
99  * @resv: reservation object
100  * @exclusive: (for exclusive wait) when true add all fences, otherwise only
101  *    exclusive fence
102  */
103 int drm_reservation_cb_add(struct drm_reservation_cb *rcb,
104 			   struct reservation_object *resv,
105 			   bool exclusive);
106 
107 /**
108  * Finish adding fences
109  * @rcb: reservation callback structure
110  *
111  * It will trigger callback worker if all fences were signaled before.
112  */
113 void drm_reservation_cb_done(struct drm_reservation_cb *rcb);
114 
115 /**
116  * Cleanup reservation callback structure
117  * @rcb: reservation callback structure
118  *
119  * Can be called to cancel primed reservation callback.
120  */
121 void drm_reservation_cb_fini(struct drm_reservation_cb *rcb);
122 
123 /**
124  * Add reservation to array of reservations
125  * @resv: reservation to add
126  * @resvs: array of reservations
127  * @excl_resvs_bitmap: bitmap for exclusive reservations
128  * @num_resvs: number of reservations in array
129  * @exclusive: bool to store in excl_resvs_bitmap
130  */
131 void
132 drm_add_reservation(struct reservation_object *resv,
133 			struct reservation_object **resvs,
134 			unsigned long *excl_resvs_bitmap,
135 			unsigned int *num_resvs, bool exclusive);
136 
137 /**
138  * Acquire ww_mutex lock on all reservations in the array
139  * @resvs: array of reservations
140  * @num_resvs: number of reservations in the array
141  * @ctx: ww mutex context
142  */
143 int drm_lock_reservations(struct reservation_object **resvs,
144 			unsigned int num_resvs, struct ww_acquire_ctx *ctx);
145 
146 /**
147  * Release ww_mutex lock on all reservations in the array
148  * @resvs: array of reservations
149  * @num_resvs: number of reservations in the array
150  * @ctx: ww mutex context
151  */
152 void drm_unlock_reservations(struct reservation_object **resvs,
153 				unsigned int num_resvs,
154 				struct ww_acquire_ctx *ctx);
155 
156 #endif
157