1 | /************************************************************************** |
2 | * |
3 | * Copyright (c) 2006-2023 VMware, Inc., Palo Alto, CA., USA |
4 | * All Rights Reserved. |
5 | * |
6 | * Permission is hereby granted, free of charge, to any person obtaining a |
7 | * copy of this software and associated documentation files (the |
8 | * "Software"), to deal in the Software without restriction, including |
9 | * without limitation the rights to use, copy, modify, merge, publish, |
10 | * distribute, sub license, and/or sell copies of the Software, and to |
11 | * permit persons to whom the Software is furnished to do so, subject to |
12 | * the following conditions: |
13 | * |
14 | * The above copyright notice and this permission notice (including the |
15 | * next paragraph) shall be included in all copies or substantial portions |
16 | * of the Software. |
17 | * |
18 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR |
19 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, |
20 | * FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. IN NO EVENT SHALL |
21 | * THE COPYRIGHT HOLDERS, AUTHORS AND/OR ITS SUPPLIERS BE LIABLE FOR ANY CLAIM, |
22 | * DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR |
23 | * OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE |
24 | * USE OR OTHER DEALINGS IN THE SOFTWARE. |
25 | * |
26 | **************************************************************************/ |
27 | /* |
28 | * Authors: Thomas Hellstrom <thellstrom-at-vmware-dot-com> |
29 | */ |
30 | /** @file ttm_object.h |
31 | * |
32 | * Base- and reference object implementation for the various |
33 | * ttm objects. Implements reference counting, minimal security checks |
34 | * and release on file close. |
35 | */ |
36 | |
37 | #ifndef _TTM_OBJECT_H_ |
38 | #define _TTM_OBJECT_H_ |
39 | |
40 | #include <linux/dma-buf.h> |
41 | #include <linux/kref.h> |
42 | #include <linux/list.h> |
43 | #include <linux/rcupdate.h> |
44 | |
45 | #include <drm/ttm/ttm_bo.h> |
46 | |
47 | /** |
48 | * enum ttm_object_type |
49 | * |
50 | * One entry per ttm object type. |
51 | * Device-specific types should use the |
52 | * ttm_driver_typex types. |
53 | */ |
54 | |
55 | enum ttm_object_type { |
56 | ttm_fence_type, |
57 | ttm_lock_type, |
58 | ttm_prime_type, |
59 | ttm_driver_type0 = 256, |
60 | ttm_driver_type1, |
61 | ttm_driver_type2, |
62 | ttm_driver_type3, |
63 | ttm_driver_type4, |
64 | ttm_driver_type5 |
65 | }; |
66 | |
67 | struct ttm_object_file; |
68 | struct ttm_object_device; |
69 | |
70 | /** |
71 | * struct ttm_base_object |
72 | * |
73 | * @hash: hash entry for the per-device object hash. |
74 | * @type: derived type this object is base class for. |
75 | * @shareable: Other ttm_object_files can access this object. |
76 | * |
77 | * @tfile: Pointer to ttm_object_file of the creator. |
78 | * NULL if the object was not created by a user request. |
79 | * (kernel object). |
80 | * |
81 | * @refcount: Number of references to this object, not |
82 | * including the hash entry. A reference to a base object can |
83 | * only be held by a ref object. |
84 | * |
85 | * @refcount_release: A function to be called when there are |
86 | * no more references to this object. This function should |
87 | * destroy the object (or make sure destruction eventually happens), |
88 | * and when it is called, the object has |
89 | * already been taken out of the per-device hash. The parameter |
90 | * "base" should be set to NULL by the function. |
91 | * |
92 | * @ref_obj_release: A function to be called when a reference object |
93 | * with another ttm_ref_type than TTM_REF_USAGE is deleted. |
94 | * This function may, for example, release a lock held by a user-space |
95 | * process. |
96 | * |
97 | * This struct is intended to be used as a base struct for objects that |
98 | * are visible to user-space. It provides a global name, race-safe |
99 | * access and refcounting, minimal access control and hooks for unref actions. |
100 | */ |
101 | |
102 | struct ttm_base_object { |
103 | struct rcu_head rhead; |
104 | struct ttm_object_file *tfile; |
105 | struct kref refcount; |
106 | void (*refcount_release) (struct ttm_base_object **base); |
107 | u64 handle; |
108 | enum ttm_object_type object_type; |
109 | u32 shareable; |
110 | }; |
111 | |
112 | |
113 | /** |
114 | * struct ttm_prime_object - Modified base object that is prime-aware |
115 | * |
116 | * @base: struct ttm_base_object that we derive from |
117 | * @mutex: Mutex protecting the @dma_buf member. |
118 | * @size: Size of the dma_buf associated with this object |
119 | * @real_type: Type of the underlying object. Needed since we're setting |
120 | * the value of @base::object_type to ttm_prime_type |
121 | * @dma_buf: Non ref-coutned pointer to a struct dma_buf created from this |
122 | * object. |
123 | * @refcount_release: The underlying object's release method. Needed since |
124 | * we set @base::refcount_release to our own release method. |
125 | */ |
126 | |
127 | struct ttm_prime_object { |
128 | struct ttm_base_object base; |
129 | struct mutex mutex; |
130 | size_t size; |
131 | enum ttm_object_type real_type; |
132 | struct dma_buf *dma_buf; |
133 | void (*refcount_release) (struct ttm_base_object **); |
134 | }; |
135 | |
136 | /** |
137 | * ttm_base_object_init |
138 | * |
139 | * @tfile: Pointer to a struct ttm_object_file. |
140 | * @base: The struct ttm_base_object to initialize. |
141 | * @shareable: This object is shareable with other applications. |
142 | * (different @tfile pointers.) |
143 | * @type: The object type. |
144 | * @refcount_release: See the struct ttm_base_object description. |
145 | * @ref_obj_release: See the struct ttm_base_object description. |
146 | * |
147 | * Initializes a struct ttm_base_object. |
148 | */ |
149 | |
150 | extern int ttm_base_object_init(struct ttm_object_file *tfile, |
151 | struct ttm_base_object *base, |
152 | bool shareable, |
153 | enum ttm_object_type type, |
154 | void (*refcount_release) (struct ttm_base_object |
155 | **)); |
156 | |
157 | /** |
158 | * ttm_base_object_lookup |
159 | * |
160 | * @tfile: Pointer to a struct ttm_object_file. |
161 | * @key: Hash key |
162 | * |
163 | * Looks up a struct ttm_base_object with the key @key. |
164 | */ |
165 | |
166 | extern struct ttm_base_object *ttm_base_object_lookup(struct ttm_object_file |
167 | *tfile, uint64_t key); |
168 | |
169 | /** |
170 | * ttm_base_object_lookup_for_ref |
171 | * |
172 | * @tdev: Pointer to a struct ttm_object_device. |
173 | * @key: Hash key |
174 | * |
175 | * Looks up a struct ttm_base_object with the key @key. |
176 | * This function should only be used when the struct tfile associated with the |
177 | * caller doesn't yet have a reference to the base object. |
178 | */ |
179 | |
180 | extern struct ttm_base_object * |
181 | ttm_base_object_lookup_for_ref(struct ttm_object_device *tdev, uint64_t key); |
182 | |
183 | /** |
184 | * ttm_base_object_unref |
185 | * |
186 | * @p_base: Pointer to a pointer referencing a struct ttm_base_object. |
187 | * |
188 | * Decrements the base object refcount and clears the pointer pointed to by |
189 | * p_base. |
190 | */ |
191 | |
192 | extern void ttm_base_object_unref(struct ttm_base_object **p_base); |
193 | |
194 | /** |
195 | * ttm_ref_object_add. |
196 | * |
197 | * @tfile: A struct ttm_object_file representing the application owning the |
198 | * ref_object. |
199 | * @base: The base object to reference. |
200 | * @ref_type: The type of reference. |
201 | * @existed: Upon completion, indicates that an identical reference object |
202 | * already existed, and the refcount was upped on that object instead. |
203 | * @require_existed: Fail with -EPERM if an identical ref object didn't |
204 | * already exist. |
205 | * |
206 | * Checks that the base object is shareable and adds a ref object to it. |
207 | * |
208 | * Adding a ref object to a base object is basically like referencing the |
209 | * base object, but a user-space application holds the reference. When the |
210 | * file corresponding to @tfile is closed, all its reference objects are |
211 | * deleted. A reference object can have different types depending on what |
212 | * it's intended for. It can be refcounting to prevent object destruction, |
213 | * When user-space takes a lock, it can add a ref object to that lock to |
214 | * make sure the lock is released if the application dies. A ref object |
215 | * will hold a single reference on a base object. |
216 | */ |
217 | extern int ttm_ref_object_add(struct ttm_object_file *tfile, |
218 | struct ttm_base_object *base, |
219 | bool *existed, |
220 | bool require_existed); |
221 | |
222 | /** |
223 | * ttm_ref_object_base_unref |
224 | * |
225 | * @key: Key representing the base object. |
226 | * @ref_type: Ref type of the ref object to be dereferenced. |
227 | * |
228 | * Unreference a ref object with type @ref_type |
229 | * on the base object identified by @key. If there are no duplicate |
230 | * references, the ref object will be destroyed and the base object |
231 | * will be unreferenced. |
232 | */ |
233 | extern int ttm_ref_object_base_unref(struct ttm_object_file *tfile, |
234 | unsigned long key); |
235 | |
236 | /** |
237 | * ttm_object_file_init - initialize a struct ttm_object file |
238 | * |
239 | * @tdev: A struct ttm_object device this file is initialized on. |
240 | * |
241 | * This is typically called by the file_ops::open function. |
242 | */ |
243 | |
244 | extern struct ttm_object_file *ttm_object_file_init(struct ttm_object_device |
245 | *tdev); |
246 | |
247 | /** |
248 | * ttm_object_file_release - release data held by a ttm_object_file |
249 | * |
250 | * @p_tfile: Pointer to pointer to the ttm_object_file object to release. |
251 | * *p_tfile will be set to NULL by this function. |
252 | * |
253 | * Releases all data associated by a ttm_object_file. |
254 | * Typically called from file_ops::release. The caller must |
255 | * ensure that there are no concurrent users of tfile. |
256 | */ |
257 | |
258 | extern void ttm_object_file_release(struct ttm_object_file **p_tfile); |
259 | |
260 | /** |
261 | * ttm_object device init - initialize a struct ttm_object_device |
262 | * |
263 | * @ops: DMA buf ops for prime objects of this device. |
264 | * |
265 | * This function is typically called on device initialization to prepare |
266 | * data structures needed for ttm base and ref objects. |
267 | */ |
268 | |
269 | extern struct ttm_object_device * |
270 | ttm_object_device_init(const struct dma_buf_ops *ops); |
271 | |
272 | /** |
273 | * ttm_object_device_release - release data held by a ttm_object_device |
274 | * |
275 | * @p_tdev: Pointer to pointer to the ttm_object_device object to release. |
276 | * *p_tdev will be set to NULL by this function. |
277 | * |
278 | * Releases all data associated by a ttm_object_device. |
279 | * Typically called from driver::unload before the destruction of the |
280 | * device private data structure. |
281 | */ |
282 | |
283 | extern void ttm_object_device_release(struct ttm_object_device **p_tdev); |
284 | |
285 | #define ttm_base_object_kfree(__object, __base)\ |
286 | kfree_rcu(__object, __base.rhead) |
287 | |
288 | extern int ttm_prime_object_init(struct ttm_object_file *tfile, |
289 | size_t size, |
290 | struct ttm_prime_object *prime, |
291 | enum ttm_object_type type, |
292 | void (*refcount_release) |
293 | (struct ttm_base_object **)); |
294 | |
295 | static inline enum ttm_object_type |
296 | ttm_base_object_type(struct ttm_base_object *base) |
297 | { |
298 | return (base->object_type == ttm_prime_type) ? |
299 | container_of(base, struct ttm_prime_object, base)->real_type : |
300 | base->object_type; |
301 | } |
302 | extern int ttm_prime_fd_to_handle(struct ttm_object_file *tfile, |
303 | int fd, u32 *handle); |
304 | extern int ttm_prime_handle_to_fd(struct ttm_object_file *tfile, |
305 | uint32_t handle, uint32_t flags, |
306 | int *prime_fd); |
307 | |
308 | #define ttm_prime_object_kfree(__obj, __prime) \ |
309 | kfree_rcu(__obj, __prime.base.rhead) |
310 | |
311 | static inline int ttm_bo_wait(struct ttm_buffer_object *bo, bool intr, |
312 | bool no_wait) |
313 | { |
314 | struct ttm_operation_ctx ctx = { intr, no_wait }; |
315 | |
316 | return ttm_bo_wait_ctx(bo, ctx: &ctx); |
317 | } |
318 | |
319 | #endif |
320 | |