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