xref: /linux-6.15/include/drm/drm_gpuvm.h (revision e53c1e26)
1b9c02e10SThomas Hellström /* SPDX-License-Identifier: GPL-2.0-only OR MIT */
2f72c2db4SDanilo Krummrich 
3f72c2db4SDanilo Krummrich #ifndef __DRM_GPUVM_H__
4f72c2db4SDanilo Krummrich #define __DRM_GPUVM_H__
5f72c2db4SDanilo Krummrich 
6f72c2db4SDanilo Krummrich /*
7f72c2db4SDanilo Krummrich  * Copyright (c) 2022 Red Hat.
8f72c2db4SDanilo Krummrich  *
9f72c2db4SDanilo Krummrich  * Permission is hereby granted, free of charge, to any person obtaining a
10f72c2db4SDanilo Krummrich  * copy of this software and associated documentation files (the "Software"),
11f72c2db4SDanilo Krummrich  * to deal in the Software without restriction, including without limitation
12f72c2db4SDanilo Krummrich  * the rights to use, copy, modify, merge, publish, distribute, sublicense,
13f72c2db4SDanilo Krummrich  * and/or sell copies of the Software, and to permit persons to whom the
14f72c2db4SDanilo Krummrich  * Software is furnished to do so, subject to the following conditions:
15f72c2db4SDanilo Krummrich  *
16f72c2db4SDanilo Krummrich  * The above copyright notice and this permission notice shall be included in
17f72c2db4SDanilo Krummrich  * all copies or substantial portions of the Software.
18f72c2db4SDanilo Krummrich  *
19f72c2db4SDanilo Krummrich  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
20f72c2db4SDanilo Krummrich  * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
21f72c2db4SDanilo Krummrich  * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
22f72c2db4SDanilo Krummrich  * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR
23f72c2db4SDanilo Krummrich  * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
24f72c2db4SDanilo Krummrich  * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
25f72c2db4SDanilo Krummrich  * OTHER DEALINGS IN THE SOFTWARE.
26f72c2db4SDanilo Krummrich  */
27f72c2db4SDanilo Krummrich 
2894bc2249SDanilo Krummrich #include <linux/dma-resv.h>
29f72c2db4SDanilo Krummrich #include <linux/list.h>
30f72c2db4SDanilo Krummrich #include <linux/rbtree.h>
31f72c2db4SDanilo Krummrich #include <linux/types.h>
32f72c2db4SDanilo Krummrich 
33546ca4d3SDanilo Krummrich #include <drm/drm_device.h>
34f72c2db4SDanilo Krummrich #include <drm/drm_gem.h>
3550c1a36fSDanilo Krummrich #include <drm/drm_exec.h>
36f72c2db4SDanilo Krummrich 
37f72c2db4SDanilo Krummrich struct drm_gpuvm;
3894bc2249SDanilo Krummrich struct drm_gpuvm_bo;
39f72c2db4SDanilo Krummrich struct drm_gpuvm_ops;
40f72c2db4SDanilo Krummrich 
41f72c2db4SDanilo Krummrich /**
42f72c2db4SDanilo Krummrich  * enum drm_gpuva_flags - flags for struct drm_gpuva
43f72c2db4SDanilo Krummrich  */
44f72c2db4SDanilo Krummrich enum drm_gpuva_flags {
45f72c2db4SDanilo Krummrich 	/**
46f72c2db4SDanilo Krummrich 	 * @DRM_GPUVA_INVALIDATED:
47f72c2db4SDanilo Krummrich 	 *
48f72c2db4SDanilo Krummrich 	 * Flag indicating that the &drm_gpuva's backing GEM is invalidated.
49f72c2db4SDanilo Krummrich 	 */
50f72c2db4SDanilo Krummrich 	DRM_GPUVA_INVALIDATED = (1 << 0),
51f72c2db4SDanilo Krummrich 
52f72c2db4SDanilo Krummrich 	/**
53f72c2db4SDanilo Krummrich 	 * @DRM_GPUVA_SPARSE:
54f72c2db4SDanilo Krummrich 	 *
55f72c2db4SDanilo Krummrich 	 * Flag indicating that the &drm_gpuva is a sparse mapping.
56f72c2db4SDanilo Krummrich 	 */
57f72c2db4SDanilo Krummrich 	DRM_GPUVA_SPARSE = (1 << 1),
58f72c2db4SDanilo Krummrich 
59f72c2db4SDanilo Krummrich 	/**
60f72c2db4SDanilo Krummrich 	 * @DRM_GPUVA_USERBITS: user defined bits
61f72c2db4SDanilo Krummrich 	 */
62f72c2db4SDanilo Krummrich 	DRM_GPUVA_USERBITS = (1 << 2),
63f72c2db4SDanilo Krummrich };
64f72c2db4SDanilo Krummrich 
65f72c2db4SDanilo Krummrich /**
66f72c2db4SDanilo Krummrich  * struct drm_gpuva - structure to track a GPU VA mapping
67f72c2db4SDanilo Krummrich  *
68f72c2db4SDanilo Krummrich  * This structure represents a GPU VA mapping and is associated with a
69f72c2db4SDanilo Krummrich  * &drm_gpuvm.
70f72c2db4SDanilo Krummrich  *
71f72c2db4SDanilo Krummrich  * Typically, this structure is embedded in bigger driver structures.
72f72c2db4SDanilo Krummrich  */
73f72c2db4SDanilo Krummrich struct drm_gpuva {
74f72c2db4SDanilo Krummrich 	/**
75f72c2db4SDanilo Krummrich 	 * @vm: the &drm_gpuvm this object is associated with
76f72c2db4SDanilo Krummrich 	 */
77f72c2db4SDanilo Krummrich 	struct drm_gpuvm *vm;
78f72c2db4SDanilo Krummrich 
79f72c2db4SDanilo Krummrich 	/**
8094bc2249SDanilo Krummrich 	 * @vm_bo: the &drm_gpuvm_bo abstraction for the mapped
8194bc2249SDanilo Krummrich 	 * &drm_gem_object
8294bc2249SDanilo Krummrich 	 */
8394bc2249SDanilo Krummrich 	struct drm_gpuvm_bo *vm_bo;
8494bc2249SDanilo Krummrich 
8594bc2249SDanilo Krummrich 	/**
86f72c2db4SDanilo Krummrich 	 * @flags: the &drm_gpuva_flags for this mapping
87f72c2db4SDanilo Krummrich 	 */
88f72c2db4SDanilo Krummrich 	enum drm_gpuva_flags flags;
89f72c2db4SDanilo Krummrich 
90f72c2db4SDanilo Krummrich 	/**
91f72c2db4SDanilo Krummrich 	 * @va: structure containing the address and range of the &drm_gpuva
92f72c2db4SDanilo Krummrich 	 */
93f72c2db4SDanilo Krummrich 	struct {
94f72c2db4SDanilo Krummrich 		/**
95200a6b3aSRandy Dunlap 		 * @va.addr: the start address
96f72c2db4SDanilo Krummrich 		 */
97f72c2db4SDanilo Krummrich 		u64 addr;
98f72c2db4SDanilo Krummrich 
99f72c2db4SDanilo Krummrich 		/*
100f72c2db4SDanilo Krummrich 		 * @range: the range
101f72c2db4SDanilo Krummrich 		 */
102f72c2db4SDanilo Krummrich 		u64 range;
103f72c2db4SDanilo Krummrich 	} va;
104f72c2db4SDanilo Krummrich 
105f72c2db4SDanilo Krummrich 	/**
106f72c2db4SDanilo Krummrich 	 * @gem: structure containing the &drm_gem_object and it's offset
107f72c2db4SDanilo Krummrich 	 */
108f72c2db4SDanilo Krummrich 	struct {
109f72c2db4SDanilo Krummrich 		/**
110200a6b3aSRandy Dunlap 		 * @gem.offset: the offset within the &drm_gem_object
111f72c2db4SDanilo Krummrich 		 */
112f72c2db4SDanilo Krummrich 		u64 offset;
113f72c2db4SDanilo Krummrich 
114f72c2db4SDanilo Krummrich 		/**
115200a6b3aSRandy Dunlap 		 * @gem.obj: the mapped &drm_gem_object
116f72c2db4SDanilo Krummrich 		 */
117f72c2db4SDanilo Krummrich 		struct drm_gem_object *obj;
118f72c2db4SDanilo Krummrich 
119f72c2db4SDanilo Krummrich 		/**
120200a6b3aSRandy Dunlap 		 * @gem.entry: the &list_head to attach this object to a &drm_gpuvm_bo
121f72c2db4SDanilo Krummrich 		 */
122f72c2db4SDanilo Krummrich 		struct list_head entry;
123f72c2db4SDanilo Krummrich 	} gem;
124f72c2db4SDanilo Krummrich 
125f72c2db4SDanilo Krummrich 	/**
126f72c2db4SDanilo Krummrich 	 * @rb: structure containing data to store &drm_gpuvas in a rb-tree
127f72c2db4SDanilo Krummrich 	 */
128f72c2db4SDanilo Krummrich 	struct {
129f72c2db4SDanilo Krummrich 		/**
130200a6b3aSRandy Dunlap 		 * @rb.node: the rb-tree node
131f72c2db4SDanilo Krummrich 		 */
132f72c2db4SDanilo Krummrich 		struct rb_node node;
133f72c2db4SDanilo Krummrich 
134f72c2db4SDanilo Krummrich 		/**
135200a6b3aSRandy Dunlap 		 * @rb.entry: The &list_head to additionally connect &drm_gpuvas
136f72c2db4SDanilo Krummrich 		 * in the same order they appear in the interval tree. This is
137f72c2db4SDanilo Krummrich 		 * useful to keep iterating &drm_gpuvas from a start node found
138f72c2db4SDanilo Krummrich 		 * through the rb-tree while doing modifications on the rb-tree
139f72c2db4SDanilo Krummrich 		 * itself.
140f72c2db4SDanilo Krummrich 		 */
141f72c2db4SDanilo Krummrich 		struct list_head entry;
142f72c2db4SDanilo Krummrich 
143f72c2db4SDanilo Krummrich 		/**
144200a6b3aSRandy Dunlap 		 * @rb.__subtree_last: needed by the interval tree, holding last-in-subtree
145f72c2db4SDanilo Krummrich 		 */
146f72c2db4SDanilo Krummrich 		u64 __subtree_last;
147f72c2db4SDanilo Krummrich 	} rb;
148f72c2db4SDanilo Krummrich };
149f72c2db4SDanilo Krummrich 
150f72c2db4SDanilo Krummrich int drm_gpuva_insert(struct drm_gpuvm *gpuvm, struct drm_gpuva *va);
151f72c2db4SDanilo Krummrich void drm_gpuva_remove(struct drm_gpuva *va);
152f72c2db4SDanilo Krummrich 
15394bc2249SDanilo Krummrich void drm_gpuva_link(struct drm_gpuva *va, struct drm_gpuvm_bo *vm_bo);
154f72c2db4SDanilo Krummrich void drm_gpuva_unlink(struct drm_gpuva *va);
155f72c2db4SDanilo Krummrich 
156f72c2db4SDanilo Krummrich struct drm_gpuva *drm_gpuva_find(struct drm_gpuvm *gpuvm,
157f72c2db4SDanilo Krummrich 				 u64 addr, u64 range);
158f72c2db4SDanilo Krummrich struct drm_gpuva *drm_gpuva_find_first(struct drm_gpuvm *gpuvm,
159f72c2db4SDanilo Krummrich 				       u64 addr, u64 range);
160f72c2db4SDanilo Krummrich struct drm_gpuva *drm_gpuva_find_prev(struct drm_gpuvm *gpuvm, u64 start);
161f72c2db4SDanilo Krummrich struct drm_gpuva *drm_gpuva_find_next(struct drm_gpuvm *gpuvm, u64 end);
162f72c2db4SDanilo Krummrich 
drm_gpuva_init(struct drm_gpuva * va,u64 addr,u64 range,struct drm_gem_object * obj,u64 offset)163f72c2db4SDanilo Krummrich static inline void drm_gpuva_init(struct drm_gpuva *va, u64 addr, u64 range,
164f72c2db4SDanilo Krummrich 				  struct drm_gem_object *obj, u64 offset)
165f72c2db4SDanilo Krummrich {
166f72c2db4SDanilo Krummrich 	va->va.addr = addr;
167f72c2db4SDanilo Krummrich 	va->va.range = range;
168f72c2db4SDanilo Krummrich 	va->gem.obj = obj;
169f72c2db4SDanilo Krummrich 	va->gem.offset = offset;
170f72c2db4SDanilo Krummrich }
171f72c2db4SDanilo Krummrich 
172f72c2db4SDanilo Krummrich /**
173f72c2db4SDanilo Krummrich  * drm_gpuva_invalidate() - sets whether the backing GEM of this &drm_gpuva is
174f72c2db4SDanilo Krummrich  * invalidated
175f72c2db4SDanilo Krummrich  * @va: the &drm_gpuva to set the invalidate flag for
176f72c2db4SDanilo Krummrich  * @invalidate: indicates whether the &drm_gpuva is invalidated
177f72c2db4SDanilo Krummrich  */
drm_gpuva_invalidate(struct drm_gpuva * va,bool invalidate)178f72c2db4SDanilo Krummrich static inline void drm_gpuva_invalidate(struct drm_gpuva *va, bool invalidate)
179f72c2db4SDanilo Krummrich {
180f72c2db4SDanilo Krummrich 	if (invalidate)
181f72c2db4SDanilo Krummrich 		va->flags |= DRM_GPUVA_INVALIDATED;
182f72c2db4SDanilo Krummrich 	else
183f72c2db4SDanilo Krummrich 		va->flags &= ~DRM_GPUVA_INVALIDATED;
184f72c2db4SDanilo Krummrich }
185f72c2db4SDanilo Krummrich 
186f72c2db4SDanilo Krummrich /**
187f72c2db4SDanilo Krummrich  * drm_gpuva_invalidated() - indicates whether the backing BO of this &drm_gpuva
188f72c2db4SDanilo Krummrich  * is invalidated
189f72c2db4SDanilo Krummrich  * @va: the &drm_gpuva to check
190200a6b3aSRandy Dunlap  *
191200a6b3aSRandy Dunlap  * Returns: %true if the GPU VA is invalidated, %false otherwise
192f72c2db4SDanilo Krummrich  */
drm_gpuva_invalidated(struct drm_gpuva * va)193f72c2db4SDanilo Krummrich static inline bool drm_gpuva_invalidated(struct drm_gpuva *va)
194f72c2db4SDanilo Krummrich {
195f72c2db4SDanilo Krummrich 	return va->flags & DRM_GPUVA_INVALIDATED;
196f72c2db4SDanilo Krummrich }
197f72c2db4SDanilo Krummrich 
198f72c2db4SDanilo Krummrich /**
199809ef191SDanilo Krummrich  * enum drm_gpuvm_flags - flags for struct drm_gpuvm
200809ef191SDanilo Krummrich  */
201809ef191SDanilo Krummrich enum drm_gpuvm_flags {
202809ef191SDanilo Krummrich 	/**
20394bc2249SDanilo Krummrich 	 * @DRM_GPUVM_RESV_PROTECTED: GPUVM is protected externally by the
20494bc2249SDanilo Krummrich 	 * GPUVM's &dma_resv lock
20594bc2249SDanilo Krummrich 	 */
20694bc2249SDanilo Krummrich 	DRM_GPUVM_RESV_PROTECTED = BIT(0),
20794bc2249SDanilo Krummrich 
20894bc2249SDanilo Krummrich 	/**
209809ef191SDanilo Krummrich 	 * @DRM_GPUVM_USERBITS: user defined bits
210809ef191SDanilo Krummrich 	 */
21194bc2249SDanilo Krummrich 	DRM_GPUVM_USERBITS = BIT(1),
212809ef191SDanilo Krummrich };
213809ef191SDanilo Krummrich 
214809ef191SDanilo Krummrich /**
215f72c2db4SDanilo Krummrich  * struct drm_gpuvm - DRM GPU VA Manager
216f72c2db4SDanilo Krummrich  *
217f72c2db4SDanilo Krummrich  * The DRM GPU VA Manager keeps track of a GPU's virtual address space by using
218f72c2db4SDanilo Krummrich  * &maple_tree structures. Typically, this structure is embedded in bigger
219f72c2db4SDanilo Krummrich  * driver structures.
220f72c2db4SDanilo Krummrich  *
221f72c2db4SDanilo Krummrich  * Drivers can pass addresses and ranges in an arbitrary unit, e.g. bytes or
222f72c2db4SDanilo Krummrich  * pages.
223f72c2db4SDanilo Krummrich  *
224f72c2db4SDanilo Krummrich  * There should be one manager instance per GPU virtual address space.
225f72c2db4SDanilo Krummrich  */
226f72c2db4SDanilo Krummrich struct drm_gpuvm {
227f72c2db4SDanilo Krummrich 	/**
228f72c2db4SDanilo Krummrich 	 * @name: the name of the DRM GPU VA space
229f72c2db4SDanilo Krummrich 	 */
230f72c2db4SDanilo Krummrich 	const char *name;
231f72c2db4SDanilo Krummrich 
232f72c2db4SDanilo Krummrich 	/**
233809ef191SDanilo Krummrich 	 * @flags: the &drm_gpuvm_flags of this GPUVM
234809ef191SDanilo Krummrich 	 */
235809ef191SDanilo Krummrich 	enum drm_gpuvm_flags flags;
236809ef191SDanilo Krummrich 
237809ef191SDanilo Krummrich 	/**
238546ca4d3SDanilo Krummrich 	 * @drm: the &drm_device this VM lives in
239546ca4d3SDanilo Krummrich 	 */
240546ca4d3SDanilo Krummrich 	struct drm_device *drm;
241546ca4d3SDanilo Krummrich 
242546ca4d3SDanilo Krummrich 	/**
243f72c2db4SDanilo Krummrich 	 * @mm_start: start of the VA space
244f72c2db4SDanilo Krummrich 	 */
245f72c2db4SDanilo Krummrich 	u64 mm_start;
246f72c2db4SDanilo Krummrich 
247f72c2db4SDanilo Krummrich 	/**
248f72c2db4SDanilo Krummrich 	 * @mm_range: length of the VA space
249f72c2db4SDanilo Krummrich 	 */
250f72c2db4SDanilo Krummrich 	u64 mm_range;
251f72c2db4SDanilo Krummrich 
252f72c2db4SDanilo Krummrich 	/**
253f72c2db4SDanilo Krummrich 	 * @rb: structures to track &drm_gpuva entries
254f72c2db4SDanilo Krummrich 	 */
255f72c2db4SDanilo Krummrich 	struct {
256f72c2db4SDanilo Krummrich 		/**
257200a6b3aSRandy Dunlap 		 * @rb.tree: the rb-tree to track GPU VA mappings
258f72c2db4SDanilo Krummrich 		 */
259f72c2db4SDanilo Krummrich 		struct rb_root_cached tree;
260f72c2db4SDanilo Krummrich 
261f72c2db4SDanilo Krummrich 		/**
262200a6b3aSRandy Dunlap 		 * @rb.list: the &list_head to track GPU VA mappings
263f72c2db4SDanilo Krummrich 		 */
264f72c2db4SDanilo Krummrich 		struct list_head list;
265f72c2db4SDanilo Krummrich 	} rb;
266f72c2db4SDanilo Krummrich 
267f72c2db4SDanilo Krummrich 	/**
2688af72338SDanilo Krummrich 	 * @kref: reference count of this object
2698af72338SDanilo Krummrich 	 */
2708af72338SDanilo Krummrich 	struct kref kref;
2718af72338SDanilo Krummrich 
2728af72338SDanilo Krummrich 	/**
273f72c2db4SDanilo Krummrich 	 * @kernel_alloc_node:
274f72c2db4SDanilo Krummrich 	 *
275f72c2db4SDanilo Krummrich 	 * &drm_gpuva representing the address space cutout reserved for
276f72c2db4SDanilo Krummrich 	 * the kernel
277f72c2db4SDanilo Krummrich 	 */
278f72c2db4SDanilo Krummrich 	struct drm_gpuva kernel_alloc_node;
279f72c2db4SDanilo Krummrich 
280f72c2db4SDanilo Krummrich 	/**
281f72c2db4SDanilo Krummrich 	 * @ops: &drm_gpuvm_ops providing the split/merge steps to drivers
282f72c2db4SDanilo Krummrich 	 */
283f72c2db4SDanilo Krummrich 	const struct drm_gpuvm_ops *ops;
284bbe84580SDanilo Krummrich 
285bbe84580SDanilo Krummrich 	/**
286bbe84580SDanilo Krummrich 	 * @r_obj: Resv GEM object; representing the GPUVM's common &dma_resv.
287bbe84580SDanilo Krummrich 	 */
288bbe84580SDanilo Krummrich 	struct drm_gem_object *r_obj;
28950c1a36fSDanilo Krummrich 
29050c1a36fSDanilo Krummrich 	/**
29150c1a36fSDanilo Krummrich 	 * @extobj: structure holding the extobj list
29250c1a36fSDanilo Krummrich 	 */
29350c1a36fSDanilo Krummrich 	struct {
29450c1a36fSDanilo Krummrich 		/**
295200a6b3aSRandy Dunlap 		 * @extobj.list: &list_head storing &drm_gpuvm_bos serving as
29650c1a36fSDanilo Krummrich 		 * external object
29750c1a36fSDanilo Krummrich 		 */
29850c1a36fSDanilo Krummrich 		struct list_head list;
29950c1a36fSDanilo Krummrich 
30050c1a36fSDanilo Krummrich 		/**
301200a6b3aSRandy Dunlap 		 * @extobj.local_list: pointer to the local list temporarily
302200a6b3aSRandy Dunlap 		 * storing entries from the external object list
30350c1a36fSDanilo Krummrich 		 */
30450c1a36fSDanilo Krummrich 		struct list_head *local_list;
30550c1a36fSDanilo Krummrich 
30650c1a36fSDanilo Krummrich 		/**
307200a6b3aSRandy Dunlap 		 * @extobj.lock: spinlock to protect the extobj list
30850c1a36fSDanilo Krummrich 		 */
30950c1a36fSDanilo Krummrich 		spinlock_t lock;
31050c1a36fSDanilo Krummrich 	} extobj;
31150c1a36fSDanilo Krummrich 
31250c1a36fSDanilo Krummrich 	/**
31350c1a36fSDanilo Krummrich 	 * @evict: structure holding the evict list and evict list lock
31450c1a36fSDanilo Krummrich 	 */
31550c1a36fSDanilo Krummrich 	struct {
31650c1a36fSDanilo Krummrich 		/**
317200a6b3aSRandy Dunlap 		 * @evict.list: &list_head storing &drm_gpuvm_bos currently
318200a6b3aSRandy Dunlap 		 * being evicted
31950c1a36fSDanilo Krummrich 		 */
32050c1a36fSDanilo Krummrich 		struct list_head list;
32150c1a36fSDanilo Krummrich 
32250c1a36fSDanilo Krummrich 		/**
323200a6b3aSRandy Dunlap 		 * @evict.local_list: pointer to the local list temporarily
324200a6b3aSRandy Dunlap 		 * storing entries from the evicted object list
32550c1a36fSDanilo Krummrich 		 */
32650c1a36fSDanilo Krummrich 		struct list_head *local_list;
32750c1a36fSDanilo Krummrich 
32850c1a36fSDanilo Krummrich 		/**
329200a6b3aSRandy Dunlap 		 * @evict.lock: spinlock to protect the evict list
33050c1a36fSDanilo Krummrich 		 */
33150c1a36fSDanilo Krummrich 		spinlock_t lock;
33250c1a36fSDanilo Krummrich 	} evict;
333f72c2db4SDanilo Krummrich };
334f72c2db4SDanilo Krummrich 
335f72c2db4SDanilo Krummrich void drm_gpuvm_init(struct drm_gpuvm *gpuvm, const char *name,
336809ef191SDanilo Krummrich 		    enum drm_gpuvm_flags flags,
337546ca4d3SDanilo Krummrich 		    struct drm_device *drm,
338bbe84580SDanilo Krummrich 		    struct drm_gem_object *r_obj,
339f72c2db4SDanilo Krummrich 		    u64 start_offset, u64 range,
340f72c2db4SDanilo Krummrich 		    u64 reserve_offset, u64 reserve_range,
341f72c2db4SDanilo Krummrich 		    const struct drm_gpuvm_ops *ops);
3428af72338SDanilo Krummrich 
3438af72338SDanilo Krummrich /**
3448af72338SDanilo Krummrich  * drm_gpuvm_get() - acquire a struct drm_gpuvm reference
3458af72338SDanilo Krummrich  * @gpuvm: the &drm_gpuvm to acquire the reference of
3468af72338SDanilo Krummrich  *
3478af72338SDanilo Krummrich  * This function acquires an additional reference to @gpuvm. It is illegal to
3488af72338SDanilo Krummrich  * call this without already holding a reference. No locks required.
349200a6b3aSRandy Dunlap  *
350200a6b3aSRandy Dunlap  * Returns: the &struct drm_gpuvm pointer
3518af72338SDanilo Krummrich  */
3528af72338SDanilo Krummrich static inline struct drm_gpuvm *
drm_gpuvm_get(struct drm_gpuvm * gpuvm)3538af72338SDanilo Krummrich drm_gpuvm_get(struct drm_gpuvm *gpuvm)
3548af72338SDanilo Krummrich {
3558af72338SDanilo Krummrich 	kref_get(&gpuvm->kref);
3568af72338SDanilo Krummrich 
3578af72338SDanilo Krummrich 	return gpuvm;
3588af72338SDanilo Krummrich }
3598af72338SDanilo Krummrich 
3608af72338SDanilo Krummrich void drm_gpuvm_put(struct drm_gpuvm *gpuvm);
361f72c2db4SDanilo Krummrich 
3629297cfc9SDanilo Krummrich bool drm_gpuvm_range_valid(struct drm_gpuvm *gpuvm, u64 addr, u64 range);
363f72c2db4SDanilo Krummrich bool drm_gpuvm_interval_empty(struct drm_gpuvm *gpuvm, u64 addr, u64 range);
364f72c2db4SDanilo Krummrich 
365bbe84580SDanilo Krummrich struct drm_gem_object *
366bbe84580SDanilo Krummrich drm_gpuvm_resv_object_alloc(struct drm_device *drm);
367bbe84580SDanilo Krummrich 
368bbe84580SDanilo Krummrich /**
36994bc2249SDanilo Krummrich  * drm_gpuvm_resv_protected() - indicates whether &DRM_GPUVM_RESV_PROTECTED is
37094bc2249SDanilo Krummrich  * set
37194bc2249SDanilo Krummrich  * @gpuvm: the &drm_gpuvm
37294bc2249SDanilo Krummrich  *
37394bc2249SDanilo Krummrich  * Returns: true if &DRM_GPUVM_RESV_PROTECTED is set, false otherwise.
37494bc2249SDanilo Krummrich  */
37594bc2249SDanilo Krummrich static inline bool
drm_gpuvm_resv_protected(struct drm_gpuvm * gpuvm)37694bc2249SDanilo Krummrich drm_gpuvm_resv_protected(struct drm_gpuvm *gpuvm)
37794bc2249SDanilo Krummrich {
37894bc2249SDanilo Krummrich 	return gpuvm->flags & DRM_GPUVM_RESV_PROTECTED;
37994bc2249SDanilo Krummrich }
38094bc2249SDanilo Krummrich 
38194bc2249SDanilo Krummrich /**
382bbe84580SDanilo Krummrich  * drm_gpuvm_resv() - returns the &drm_gpuvm's &dma_resv
383bbe84580SDanilo Krummrich  * @gpuvm__: the &drm_gpuvm
384bbe84580SDanilo Krummrich  *
385bbe84580SDanilo Krummrich  * Returns: a pointer to the &drm_gpuvm's shared &dma_resv
386bbe84580SDanilo Krummrich  */
387bbe84580SDanilo Krummrich #define drm_gpuvm_resv(gpuvm__) ((gpuvm__)->r_obj->resv)
388bbe84580SDanilo Krummrich 
389bbe84580SDanilo Krummrich /**
390bbe84580SDanilo Krummrich  * drm_gpuvm_resv_obj() - returns the &drm_gem_object holding the &drm_gpuvm's
391bbe84580SDanilo Krummrich  * &dma_resv
392bbe84580SDanilo Krummrich  * @gpuvm__: the &drm_gpuvm
393bbe84580SDanilo Krummrich  *
394bbe84580SDanilo Krummrich  * Returns: a pointer to the &drm_gem_object holding the &drm_gpuvm's shared
395bbe84580SDanilo Krummrich  * &dma_resv
396bbe84580SDanilo Krummrich  */
397bbe84580SDanilo Krummrich #define drm_gpuvm_resv_obj(gpuvm__) ((gpuvm__)->r_obj)
398bbe84580SDanilo Krummrich 
399bbe84580SDanilo Krummrich #define drm_gpuvm_resv_held(gpuvm__) \
400bbe84580SDanilo Krummrich 	dma_resv_held(drm_gpuvm_resv(gpuvm__))
401bbe84580SDanilo Krummrich 
402bbe84580SDanilo Krummrich #define drm_gpuvm_resv_assert_held(gpuvm__) \
403bbe84580SDanilo Krummrich 	dma_resv_assert_held(drm_gpuvm_resv(gpuvm__))
404bbe84580SDanilo Krummrich 
40594bc2249SDanilo Krummrich #define drm_gpuvm_resv_held(gpuvm__) \
40694bc2249SDanilo Krummrich 	dma_resv_held(drm_gpuvm_resv(gpuvm__))
40794bc2249SDanilo Krummrich 
40894bc2249SDanilo Krummrich #define drm_gpuvm_resv_assert_held(gpuvm__) \
40994bc2249SDanilo Krummrich 	dma_resv_assert_held(drm_gpuvm_resv(gpuvm__))
41094bc2249SDanilo Krummrich 
41150c1a36fSDanilo Krummrich /**
41250c1a36fSDanilo Krummrich  * drm_gpuvm_is_extobj() - indicates whether the given &drm_gem_object is an
41350c1a36fSDanilo Krummrich  * external object
41450c1a36fSDanilo Krummrich  * @gpuvm: the &drm_gpuvm to check
41550c1a36fSDanilo Krummrich  * @obj: the &drm_gem_object to check
41650c1a36fSDanilo Krummrich  *
41750c1a36fSDanilo Krummrich  * Returns: true if the &drm_gem_object &dma_resv differs from the
41850c1a36fSDanilo Krummrich  * &drm_gpuvms &dma_resv, false otherwise
41950c1a36fSDanilo Krummrich  */
42050c1a36fSDanilo Krummrich static inline bool
drm_gpuvm_is_extobj(struct drm_gpuvm * gpuvm,struct drm_gem_object * obj)42150c1a36fSDanilo Krummrich drm_gpuvm_is_extobj(struct drm_gpuvm *gpuvm,
42250c1a36fSDanilo Krummrich 		    struct drm_gem_object *obj)
42350c1a36fSDanilo Krummrich {
42450c1a36fSDanilo Krummrich 	return obj && obj->resv != drm_gpuvm_resv(gpuvm);
42550c1a36fSDanilo Krummrich }
42650c1a36fSDanilo Krummrich 
427f72c2db4SDanilo Krummrich static inline struct drm_gpuva *
__drm_gpuva_next(struct drm_gpuva * va)428f72c2db4SDanilo Krummrich __drm_gpuva_next(struct drm_gpuva *va)
429f72c2db4SDanilo Krummrich {
430f72c2db4SDanilo Krummrich 	if (va && !list_is_last(&va->rb.entry, &va->vm->rb.list))
431f72c2db4SDanilo Krummrich 		return list_next_entry(va, rb.entry);
432f72c2db4SDanilo Krummrich 
433f72c2db4SDanilo Krummrich 	return NULL;
434f72c2db4SDanilo Krummrich }
435f72c2db4SDanilo Krummrich 
436f72c2db4SDanilo Krummrich /**
437f72c2db4SDanilo Krummrich  * drm_gpuvm_for_each_va_range() - iterate over a range of &drm_gpuvas
438f72c2db4SDanilo Krummrich  * @va__: &drm_gpuva structure to assign to in each iteration step
439f72c2db4SDanilo Krummrich  * @gpuvm__: &drm_gpuvm to walk over
440f72c2db4SDanilo Krummrich  * @start__: starting offset, the first gpuva will overlap this
441f72c2db4SDanilo Krummrich  * @end__: ending offset, the last gpuva will start before this (but may
442f72c2db4SDanilo Krummrich  * overlap)
443f72c2db4SDanilo Krummrich  *
444f72c2db4SDanilo Krummrich  * This iterator walks over all &drm_gpuvas in the &drm_gpuvm that lie
445f72c2db4SDanilo Krummrich  * between @start__ and @end__. It is implemented similarly to list_for_each(),
446f72c2db4SDanilo Krummrich  * but is using the &drm_gpuvm's internal interval tree to accelerate
447f72c2db4SDanilo Krummrich  * the search for the starting &drm_gpuva, and hence isn't safe against removal
448f72c2db4SDanilo Krummrich  * of elements. It assumes that @end__ is within (or is the upper limit of) the
449f72c2db4SDanilo Krummrich  * &drm_gpuvm. This iterator does not skip over the &drm_gpuvm's
450f72c2db4SDanilo Krummrich  * @kernel_alloc_node.
451f72c2db4SDanilo Krummrich  */
452f72c2db4SDanilo Krummrich #define drm_gpuvm_for_each_va_range(va__, gpuvm__, start__, end__) \
453f72c2db4SDanilo Krummrich 	for (va__ = drm_gpuva_find_first((gpuvm__), (start__), (end__) - (start__)); \
454f72c2db4SDanilo Krummrich 	     va__ && (va__->va.addr < (end__)); \
455f72c2db4SDanilo Krummrich 	     va__ = __drm_gpuva_next(va__))
456f72c2db4SDanilo Krummrich 
457f72c2db4SDanilo Krummrich /**
458f72c2db4SDanilo Krummrich  * drm_gpuvm_for_each_va_range_safe() - safely iterate over a range of
459f72c2db4SDanilo Krummrich  * &drm_gpuvas
460f72c2db4SDanilo Krummrich  * @va__: &drm_gpuva to assign to in each iteration step
461f72c2db4SDanilo Krummrich  * @next__: another &drm_gpuva to use as temporary storage
462f72c2db4SDanilo Krummrich  * @gpuvm__: &drm_gpuvm to walk over
463f72c2db4SDanilo Krummrich  * @start__: starting offset, the first gpuva will overlap this
464f72c2db4SDanilo Krummrich  * @end__: ending offset, the last gpuva will start before this (but may
465f72c2db4SDanilo Krummrich  * overlap)
466f72c2db4SDanilo Krummrich  *
467f72c2db4SDanilo Krummrich  * This iterator walks over all &drm_gpuvas in the &drm_gpuvm that lie
468f72c2db4SDanilo Krummrich  * between @start__ and @end__. It is implemented similarly to
469f72c2db4SDanilo Krummrich  * list_for_each_safe(), but is using the &drm_gpuvm's internal interval
470f72c2db4SDanilo Krummrich  * tree to accelerate the search for the starting &drm_gpuva, and hence is safe
471f72c2db4SDanilo Krummrich  * against removal of elements. It assumes that @end__ is within (or is the
472f72c2db4SDanilo Krummrich  * upper limit of) the &drm_gpuvm. This iterator does not skip over the
473f72c2db4SDanilo Krummrich  * &drm_gpuvm's @kernel_alloc_node.
474f72c2db4SDanilo Krummrich  */
475f72c2db4SDanilo Krummrich #define drm_gpuvm_for_each_va_range_safe(va__, next__, gpuvm__, start__, end__) \
476f72c2db4SDanilo Krummrich 	for (va__ = drm_gpuva_find_first((gpuvm__), (start__), (end__) - (start__)), \
477f72c2db4SDanilo Krummrich 	     next__ = __drm_gpuva_next(va__); \
478f72c2db4SDanilo Krummrich 	     va__ && (va__->va.addr < (end__)); \
479f72c2db4SDanilo Krummrich 	     va__ = next__, next__ = __drm_gpuva_next(va__))
480f72c2db4SDanilo Krummrich 
481f72c2db4SDanilo Krummrich /**
482f72c2db4SDanilo Krummrich  * drm_gpuvm_for_each_va() - iterate over all &drm_gpuvas
483f72c2db4SDanilo Krummrich  * @va__: &drm_gpuva to assign to in each iteration step
484f72c2db4SDanilo Krummrich  * @gpuvm__: &drm_gpuvm to walk over
485f72c2db4SDanilo Krummrich  *
486f72c2db4SDanilo Krummrich  * This iterator walks over all &drm_gpuva structures associated with the given
487f72c2db4SDanilo Krummrich  * &drm_gpuvm.
488f72c2db4SDanilo Krummrich  */
489f72c2db4SDanilo Krummrich #define drm_gpuvm_for_each_va(va__, gpuvm__) \
490f72c2db4SDanilo Krummrich 	list_for_each_entry(va__, &(gpuvm__)->rb.list, rb.entry)
491f72c2db4SDanilo Krummrich 
492f72c2db4SDanilo Krummrich /**
493f72c2db4SDanilo Krummrich  * drm_gpuvm_for_each_va_safe() - safely iterate over all &drm_gpuvas
494f72c2db4SDanilo Krummrich  * @va__: &drm_gpuva to assign to in each iteration step
495f72c2db4SDanilo Krummrich  * @next__: another &drm_gpuva to use as temporary storage
496f72c2db4SDanilo Krummrich  * @gpuvm__: &drm_gpuvm to walk over
497f72c2db4SDanilo Krummrich  *
498f72c2db4SDanilo Krummrich  * This iterator walks over all &drm_gpuva structures associated with the given
499f72c2db4SDanilo Krummrich  * &drm_gpuvm. It is implemented with list_for_each_entry_safe(), and
500f72c2db4SDanilo Krummrich  * hence safe against the removal of elements.
501f72c2db4SDanilo Krummrich  */
502f72c2db4SDanilo Krummrich #define drm_gpuvm_for_each_va_safe(va__, next__, gpuvm__) \
503f72c2db4SDanilo Krummrich 	list_for_each_entry_safe(va__, next__, &(gpuvm__)->rb.list, rb.entry)
504f72c2db4SDanilo Krummrich 
505f72c2db4SDanilo Krummrich /**
50650c1a36fSDanilo Krummrich  * struct drm_gpuvm_exec - &drm_gpuvm abstraction of &drm_exec
50750c1a36fSDanilo Krummrich  *
50850c1a36fSDanilo Krummrich  * This structure should be created on the stack as &drm_exec should be.
50950c1a36fSDanilo Krummrich  *
51050c1a36fSDanilo Krummrich  * Optionally, @extra can be set in order to lock additional &drm_gem_objects.
51150c1a36fSDanilo Krummrich  */
51250c1a36fSDanilo Krummrich struct drm_gpuvm_exec {
51350c1a36fSDanilo Krummrich 	/**
51450c1a36fSDanilo Krummrich 	 * @exec: the &drm_exec structure
51550c1a36fSDanilo Krummrich 	 */
51650c1a36fSDanilo Krummrich 	struct drm_exec exec;
51750c1a36fSDanilo Krummrich 
51850c1a36fSDanilo Krummrich 	/**
51950c1a36fSDanilo Krummrich 	 * @flags: the flags for the struct drm_exec
52050c1a36fSDanilo Krummrich 	 */
521cf41cebfSThomas Hellström 	u32 flags;
52250c1a36fSDanilo Krummrich 
52350c1a36fSDanilo Krummrich 	/**
52450c1a36fSDanilo Krummrich 	 * @vm: the &drm_gpuvm to lock its DMA reservations
52550c1a36fSDanilo Krummrich 	 */
52650c1a36fSDanilo Krummrich 	struct drm_gpuvm *vm;
52750c1a36fSDanilo Krummrich 
52850c1a36fSDanilo Krummrich 	/**
52950c1a36fSDanilo Krummrich 	 * @num_fences: the number of fences to reserve for the &dma_resv of the
53050c1a36fSDanilo Krummrich 	 * locked &drm_gem_objects
53150c1a36fSDanilo Krummrich 	 */
53250c1a36fSDanilo Krummrich 	unsigned int num_fences;
53350c1a36fSDanilo Krummrich 
53450c1a36fSDanilo Krummrich 	/**
53550c1a36fSDanilo Krummrich 	 * @extra: Callback and corresponding private data for the driver to
53650c1a36fSDanilo Krummrich 	 * lock arbitrary additional &drm_gem_objects.
53750c1a36fSDanilo Krummrich 	 */
53850c1a36fSDanilo Krummrich 	struct {
53950c1a36fSDanilo Krummrich 		/**
540200a6b3aSRandy Dunlap 		 * @extra.fn: The driver callback to lock additional
541200a6b3aSRandy Dunlap 		 * &drm_gem_objects.
54250c1a36fSDanilo Krummrich 		 */
54350c1a36fSDanilo Krummrich 		int (*fn)(struct drm_gpuvm_exec *vm_exec);
54450c1a36fSDanilo Krummrich 
54550c1a36fSDanilo Krummrich 		/**
546200a6b3aSRandy Dunlap 		 * @extra.priv: driver private data for the @fn callback
54750c1a36fSDanilo Krummrich 		 */
54850c1a36fSDanilo Krummrich 		void *priv;
54950c1a36fSDanilo Krummrich 	} extra;
55050c1a36fSDanilo Krummrich };
55150c1a36fSDanilo Krummrich 
552e759f2caSDanilo Krummrich int drm_gpuvm_prepare_vm(struct drm_gpuvm *gpuvm,
55350c1a36fSDanilo Krummrich 			 struct drm_exec *exec,
554e759f2caSDanilo Krummrich 			 unsigned int num_fences);
55550c1a36fSDanilo Krummrich 
55650c1a36fSDanilo Krummrich int drm_gpuvm_prepare_objects(struct drm_gpuvm *gpuvm,
55750c1a36fSDanilo Krummrich 			      struct drm_exec *exec,
55850c1a36fSDanilo Krummrich 			      unsigned int num_fences);
55950c1a36fSDanilo Krummrich 
56050c1a36fSDanilo Krummrich int drm_gpuvm_prepare_range(struct drm_gpuvm *gpuvm,
56150c1a36fSDanilo Krummrich 			    struct drm_exec *exec,
56250c1a36fSDanilo Krummrich 			    u64 addr, u64 range,
56350c1a36fSDanilo Krummrich 			    unsigned int num_fences);
56450c1a36fSDanilo Krummrich 
56550c1a36fSDanilo Krummrich int drm_gpuvm_exec_lock(struct drm_gpuvm_exec *vm_exec);
56650c1a36fSDanilo Krummrich 
56750c1a36fSDanilo Krummrich int drm_gpuvm_exec_lock_array(struct drm_gpuvm_exec *vm_exec,
56850c1a36fSDanilo Krummrich 			      struct drm_gem_object **objs,
56950c1a36fSDanilo Krummrich 			      unsigned int num_objs);
57050c1a36fSDanilo Krummrich 
57150c1a36fSDanilo Krummrich int drm_gpuvm_exec_lock_range(struct drm_gpuvm_exec *vm_exec,
57250c1a36fSDanilo Krummrich 			      u64 addr, u64 range);
57350c1a36fSDanilo Krummrich 
57450c1a36fSDanilo Krummrich /**
57550c1a36fSDanilo Krummrich  * drm_gpuvm_exec_unlock() - lock all dma-resv of all assoiciated BOs
57650c1a36fSDanilo Krummrich  * @vm_exec: the &drm_gpuvm_exec wrapper
57750c1a36fSDanilo Krummrich  *
57850c1a36fSDanilo Krummrich  * Releases all dma-resv locks of all &drm_gem_objects previously acquired
57950c1a36fSDanilo Krummrich  * through drm_gpuvm_exec_lock() or its variants.
58050c1a36fSDanilo Krummrich  *
58150c1a36fSDanilo Krummrich  * Returns: 0 on success, negative error code on failure.
58250c1a36fSDanilo Krummrich  */
58350c1a36fSDanilo Krummrich static inline void
drm_gpuvm_exec_unlock(struct drm_gpuvm_exec * vm_exec)58450c1a36fSDanilo Krummrich drm_gpuvm_exec_unlock(struct drm_gpuvm_exec *vm_exec)
58550c1a36fSDanilo Krummrich {
58650c1a36fSDanilo Krummrich 	drm_exec_fini(&vm_exec->exec);
58750c1a36fSDanilo Krummrich }
58850c1a36fSDanilo Krummrich 
58950c1a36fSDanilo Krummrich int drm_gpuvm_validate(struct drm_gpuvm *gpuvm, struct drm_exec *exec);
59050c1a36fSDanilo Krummrich void drm_gpuvm_resv_add_fence(struct drm_gpuvm *gpuvm,
59150c1a36fSDanilo Krummrich 			      struct drm_exec *exec,
59250c1a36fSDanilo Krummrich 			      struct dma_fence *fence,
59350c1a36fSDanilo Krummrich 			      enum dma_resv_usage private_usage,
59450c1a36fSDanilo Krummrich 			      enum dma_resv_usage extobj_usage);
59550c1a36fSDanilo Krummrich 
59650c1a36fSDanilo Krummrich /**
597200a6b3aSRandy Dunlap  * drm_gpuvm_exec_resv_add_fence() - add fence to private and all extobj
59850c1a36fSDanilo Krummrich  * @vm_exec: the &drm_gpuvm_exec wrapper
59950c1a36fSDanilo Krummrich  * @fence: fence to add
60050c1a36fSDanilo Krummrich  * @private_usage: private dma-resv usage
60150c1a36fSDanilo Krummrich  * @extobj_usage: extobj dma-resv usage
60250c1a36fSDanilo Krummrich  *
60350c1a36fSDanilo Krummrich  * See drm_gpuvm_resv_add_fence().
60450c1a36fSDanilo Krummrich  */
60550c1a36fSDanilo Krummrich static inline void
drm_gpuvm_exec_resv_add_fence(struct drm_gpuvm_exec * vm_exec,struct dma_fence * fence,enum dma_resv_usage private_usage,enum dma_resv_usage extobj_usage)60650c1a36fSDanilo Krummrich drm_gpuvm_exec_resv_add_fence(struct drm_gpuvm_exec *vm_exec,
60750c1a36fSDanilo Krummrich 			      struct dma_fence *fence,
60850c1a36fSDanilo Krummrich 			      enum dma_resv_usage private_usage,
60950c1a36fSDanilo Krummrich 			      enum dma_resv_usage extobj_usage)
61050c1a36fSDanilo Krummrich {
61150c1a36fSDanilo Krummrich 	drm_gpuvm_resv_add_fence(vm_exec->vm, &vm_exec->exec, fence,
61250c1a36fSDanilo Krummrich 				 private_usage, extobj_usage);
61350c1a36fSDanilo Krummrich }
61450c1a36fSDanilo Krummrich 
61550c1a36fSDanilo Krummrich /**
616200a6b3aSRandy Dunlap  * drm_gpuvm_exec_validate() - validate all BOs marked as evicted
61750c1a36fSDanilo Krummrich  * @vm_exec: the &drm_gpuvm_exec wrapper
61850c1a36fSDanilo Krummrich  *
61950c1a36fSDanilo Krummrich  * See drm_gpuvm_validate().
620200a6b3aSRandy Dunlap  *
621200a6b3aSRandy Dunlap  * Returns: 0 on success, negative error code on failure.
62250c1a36fSDanilo Krummrich  */
62350c1a36fSDanilo Krummrich static inline int
drm_gpuvm_exec_validate(struct drm_gpuvm_exec * vm_exec)62450c1a36fSDanilo Krummrich drm_gpuvm_exec_validate(struct drm_gpuvm_exec *vm_exec)
62550c1a36fSDanilo Krummrich {
62650c1a36fSDanilo Krummrich 	return drm_gpuvm_validate(vm_exec->vm, &vm_exec->exec);
62750c1a36fSDanilo Krummrich }
62850c1a36fSDanilo Krummrich 
62950c1a36fSDanilo Krummrich /**
63094bc2249SDanilo Krummrich  * struct drm_gpuvm_bo - structure representing a &drm_gpuvm and
63194bc2249SDanilo Krummrich  * &drm_gem_object combination
63294bc2249SDanilo Krummrich  *
63394bc2249SDanilo Krummrich  * This structure is an abstraction representing a &drm_gpuvm and
63494bc2249SDanilo Krummrich  * &drm_gem_object combination. It serves as an indirection to accelerate
63594bc2249SDanilo Krummrich  * iterating all &drm_gpuvas within a &drm_gpuvm backed by the same
63694bc2249SDanilo Krummrich  * &drm_gem_object.
63794bc2249SDanilo Krummrich  *
63894bc2249SDanilo Krummrich  * Furthermore it is used cache evicted GEM objects for a certain GPU-VM to
63994bc2249SDanilo Krummrich  * accelerate validation.
64094bc2249SDanilo Krummrich  *
64194bc2249SDanilo Krummrich  * Typically, drivers want to create an instance of a struct drm_gpuvm_bo once
64294bc2249SDanilo Krummrich  * a GEM object is mapped first in a GPU-VM and release the instance once the
64394bc2249SDanilo Krummrich  * last mapping of the GEM object in this GPU-VM is unmapped.
64494bc2249SDanilo Krummrich  */
64594bc2249SDanilo Krummrich struct drm_gpuvm_bo {
64694bc2249SDanilo Krummrich 	/**
64794bc2249SDanilo Krummrich 	 * @vm: The &drm_gpuvm the @obj is mapped in. This is a reference
64894bc2249SDanilo Krummrich 	 * counted pointer.
64994bc2249SDanilo Krummrich 	 */
65094bc2249SDanilo Krummrich 	struct drm_gpuvm *vm;
65194bc2249SDanilo Krummrich 
65294bc2249SDanilo Krummrich 	/**
65394bc2249SDanilo Krummrich 	 * @obj: The &drm_gem_object being mapped in @vm. This is a reference
65494bc2249SDanilo Krummrich 	 * counted pointer.
65594bc2249SDanilo Krummrich 	 */
65694bc2249SDanilo Krummrich 	struct drm_gem_object *obj;
65794bc2249SDanilo Krummrich 
65894bc2249SDanilo Krummrich 	/**
65950c1a36fSDanilo Krummrich 	 * @evicted: Indicates whether the &drm_gem_object is evicted; field
66050c1a36fSDanilo Krummrich 	 * protected by the &drm_gem_object's dma-resv lock.
66150c1a36fSDanilo Krummrich 	 */
66250c1a36fSDanilo Krummrich 	bool evicted;
66350c1a36fSDanilo Krummrich 
66450c1a36fSDanilo Krummrich 	/**
66594bc2249SDanilo Krummrich 	 * @kref: The reference count for this &drm_gpuvm_bo.
66694bc2249SDanilo Krummrich 	 */
66794bc2249SDanilo Krummrich 	struct kref kref;
66894bc2249SDanilo Krummrich 
66994bc2249SDanilo Krummrich 	/**
67094bc2249SDanilo Krummrich 	 * @list: Structure containing all &list_heads.
67194bc2249SDanilo Krummrich 	 */
67294bc2249SDanilo Krummrich 	struct {
67394bc2249SDanilo Krummrich 		/**
674200a6b3aSRandy Dunlap 		 * @list.gpuva: The list of linked &drm_gpuvas.
67594bc2249SDanilo Krummrich 		 *
67694bc2249SDanilo Krummrich 		 * It is safe to access entries from this list as long as the
67794bc2249SDanilo Krummrich 		 * GEM's gpuva lock is held. See also struct drm_gem_object.
67894bc2249SDanilo Krummrich 		 */
67994bc2249SDanilo Krummrich 		struct list_head gpuva;
68094bc2249SDanilo Krummrich 
68194bc2249SDanilo Krummrich 		/**
682200a6b3aSRandy Dunlap 		 * @list.entry: Structure containing all &list_heads serving as
68394bc2249SDanilo Krummrich 		 * entry.
68494bc2249SDanilo Krummrich 		 */
68594bc2249SDanilo Krummrich 		struct {
68694bc2249SDanilo Krummrich 			/**
687200a6b3aSRandy Dunlap 			 * @list.entry.gem: List entry to attach to the
688200a6b3aSRandy Dunlap 			 * &drm_gem_objects gpuva list.
68994bc2249SDanilo Krummrich 			 */
69094bc2249SDanilo Krummrich 			struct list_head gem;
69150c1a36fSDanilo Krummrich 
69250c1a36fSDanilo Krummrich 			/**
693200a6b3aSRandy Dunlap 			 * @list.entry.evict: List entry to attach to the
694200a6b3aSRandy Dunlap 			 * &drm_gpuvms extobj list.
69550c1a36fSDanilo Krummrich 			 */
69650c1a36fSDanilo Krummrich 			struct list_head extobj;
69750c1a36fSDanilo Krummrich 
69850c1a36fSDanilo Krummrich 			/**
699200a6b3aSRandy Dunlap 			 * @list.entry.evict: List entry to attach to the
700200a6b3aSRandy Dunlap 			 * &drm_gpuvms evict list.
70150c1a36fSDanilo Krummrich 			 */
70250c1a36fSDanilo Krummrich 			struct list_head evict;
70394bc2249SDanilo Krummrich 		} entry;
70494bc2249SDanilo Krummrich 	} list;
70594bc2249SDanilo Krummrich };
70694bc2249SDanilo Krummrich 
70794bc2249SDanilo Krummrich struct drm_gpuvm_bo *
70894bc2249SDanilo Krummrich drm_gpuvm_bo_create(struct drm_gpuvm *gpuvm,
70994bc2249SDanilo Krummrich 		    struct drm_gem_object *obj);
71094bc2249SDanilo Krummrich 
71194bc2249SDanilo Krummrich struct drm_gpuvm_bo *
71294bc2249SDanilo Krummrich drm_gpuvm_bo_obtain(struct drm_gpuvm *gpuvm,
71394bc2249SDanilo Krummrich 		    struct drm_gem_object *obj);
71494bc2249SDanilo Krummrich struct drm_gpuvm_bo *
71594bc2249SDanilo Krummrich drm_gpuvm_bo_obtain_prealloc(struct drm_gpuvm_bo *vm_bo);
71694bc2249SDanilo Krummrich 
71794bc2249SDanilo Krummrich /**
71894bc2249SDanilo Krummrich  * drm_gpuvm_bo_get() - acquire a struct drm_gpuvm_bo reference
71994bc2249SDanilo Krummrich  * @vm_bo: the &drm_gpuvm_bo to acquire the reference of
72094bc2249SDanilo Krummrich  *
72194bc2249SDanilo Krummrich  * This function acquires an additional reference to @vm_bo. It is illegal to
72294bc2249SDanilo Krummrich  * call this without already holding a reference. No locks required.
723200a6b3aSRandy Dunlap  *
724200a6b3aSRandy Dunlap  * Returns: the &struct vm_bo pointer
72594bc2249SDanilo Krummrich  */
72694bc2249SDanilo Krummrich static inline struct drm_gpuvm_bo *
drm_gpuvm_bo_get(struct drm_gpuvm_bo * vm_bo)72794bc2249SDanilo Krummrich drm_gpuvm_bo_get(struct drm_gpuvm_bo *vm_bo)
72894bc2249SDanilo Krummrich {
72994bc2249SDanilo Krummrich 	kref_get(&vm_bo->kref);
73094bc2249SDanilo Krummrich 	return vm_bo;
73194bc2249SDanilo Krummrich }
73294bc2249SDanilo Krummrich 
733c50a291dSBoris Brezillon bool drm_gpuvm_bo_put(struct drm_gpuvm_bo *vm_bo);
73494bc2249SDanilo Krummrich 
73594bc2249SDanilo Krummrich struct drm_gpuvm_bo *
73694bc2249SDanilo Krummrich drm_gpuvm_bo_find(struct drm_gpuvm *gpuvm,
73794bc2249SDanilo Krummrich 		  struct drm_gem_object *obj);
73894bc2249SDanilo Krummrich 
73950c1a36fSDanilo Krummrich void drm_gpuvm_bo_evict(struct drm_gpuvm_bo *vm_bo, bool evict);
74050c1a36fSDanilo Krummrich 
74150c1a36fSDanilo Krummrich /**
742200a6b3aSRandy Dunlap  * drm_gpuvm_bo_gem_evict() - add/remove all &drm_gpuvm_bo's in the list
743200a6b3aSRandy Dunlap  * to/from the &drm_gpuvms evicted list
74450c1a36fSDanilo Krummrich  * @obj: the &drm_gem_object
74550c1a36fSDanilo Krummrich  * @evict: indicates whether @obj is evicted
74650c1a36fSDanilo Krummrich  *
74750c1a36fSDanilo Krummrich  * See drm_gpuvm_bo_evict().
74850c1a36fSDanilo Krummrich  */
74950c1a36fSDanilo Krummrich static inline void
drm_gpuvm_bo_gem_evict(struct drm_gem_object * obj,bool evict)75050c1a36fSDanilo Krummrich drm_gpuvm_bo_gem_evict(struct drm_gem_object *obj, bool evict)
75150c1a36fSDanilo Krummrich {
75250c1a36fSDanilo Krummrich 	struct drm_gpuvm_bo *vm_bo;
75350c1a36fSDanilo Krummrich 
75450c1a36fSDanilo Krummrich 	drm_gem_gpuva_assert_lock_held(obj);
75550c1a36fSDanilo Krummrich 	drm_gem_for_each_gpuvm_bo(vm_bo, obj)
75650c1a36fSDanilo Krummrich 		drm_gpuvm_bo_evict(vm_bo, evict);
75750c1a36fSDanilo Krummrich }
75850c1a36fSDanilo Krummrich 
75950c1a36fSDanilo Krummrich void drm_gpuvm_bo_extobj_add(struct drm_gpuvm_bo *vm_bo);
76050c1a36fSDanilo Krummrich 
76194bc2249SDanilo Krummrich /**
76294bc2249SDanilo Krummrich  * drm_gpuvm_bo_for_each_va() - iterator to walk over a list of &drm_gpuva
76394bc2249SDanilo Krummrich  * @va__: &drm_gpuva structure to assign to in each iteration step
76494bc2249SDanilo Krummrich  * @vm_bo__: the &drm_gpuvm_bo the &drm_gpuva to walk are associated with
76594bc2249SDanilo Krummrich  *
76694bc2249SDanilo Krummrich  * This iterator walks over all &drm_gpuva structures associated with the
76794bc2249SDanilo Krummrich  * &drm_gpuvm_bo.
76894bc2249SDanilo Krummrich  *
76994bc2249SDanilo Krummrich  * The caller must hold the GEM's gpuva lock.
77094bc2249SDanilo Krummrich  */
77194bc2249SDanilo Krummrich #define drm_gpuvm_bo_for_each_va(va__, vm_bo__) \
77294bc2249SDanilo Krummrich 	list_for_each_entry(va__, &(vm_bo)->list.gpuva, gem.entry)
77394bc2249SDanilo Krummrich 
77494bc2249SDanilo Krummrich /**
77594bc2249SDanilo Krummrich  * drm_gpuvm_bo_for_each_va_safe() - iterator to safely walk over a list of
77694bc2249SDanilo Krummrich  * &drm_gpuva
77794bc2249SDanilo Krummrich  * @va__: &drm_gpuva structure to assign to in each iteration step
77894bc2249SDanilo Krummrich  * @next__: &next &drm_gpuva to store the next step
77994bc2249SDanilo Krummrich  * @vm_bo__: the &drm_gpuvm_bo the &drm_gpuva to walk are associated with
78094bc2249SDanilo Krummrich  *
78194bc2249SDanilo Krummrich  * This iterator walks over all &drm_gpuva structures associated with the
78294bc2249SDanilo Krummrich  * &drm_gpuvm_bo. It is implemented with list_for_each_entry_safe(), hence
78394bc2249SDanilo Krummrich  * it is save against removal of elements.
78494bc2249SDanilo Krummrich  *
78594bc2249SDanilo Krummrich  * The caller must hold the GEM's gpuva lock.
78694bc2249SDanilo Krummrich  */
78794bc2249SDanilo Krummrich #define drm_gpuvm_bo_for_each_va_safe(va__, next__, vm_bo__) \
78894bc2249SDanilo Krummrich 	list_for_each_entry_safe(va__, next__, &(vm_bo)->list.gpuva, gem.entry)
78994bc2249SDanilo Krummrich 
79094bc2249SDanilo Krummrich /**
791f72c2db4SDanilo Krummrich  * enum drm_gpuva_op_type - GPU VA operation type
792f72c2db4SDanilo Krummrich  *
793f72c2db4SDanilo Krummrich  * Operations to alter the GPU VA mappings tracked by the &drm_gpuvm.
794f72c2db4SDanilo Krummrich  */
795f72c2db4SDanilo Krummrich enum drm_gpuva_op_type {
796f72c2db4SDanilo Krummrich 	/**
797f72c2db4SDanilo Krummrich 	 * @DRM_GPUVA_OP_MAP: the map op type
798f72c2db4SDanilo Krummrich 	 */
799f72c2db4SDanilo Krummrich 	DRM_GPUVA_OP_MAP,
800f72c2db4SDanilo Krummrich 
801f72c2db4SDanilo Krummrich 	/**
802f72c2db4SDanilo Krummrich 	 * @DRM_GPUVA_OP_REMAP: the remap op type
803f72c2db4SDanilo Krummrich 	 */
804f72c2db4SDanilo Krummrich 	DRM_GPUVA_OP_REMAP,
805f72c2db4SDanilo Krummrich 
806f72c2db4SDanilo Krummrich 	/**
807f72c2db4SDanilo Krummrich 	 * @DRM_GPUVA_OP_UNMAP: the unmap op type
808f72c2db4SDanilo Krummrich 	 */
809f72c2db4SDanilo Krummrich 	DRM_GPUVA_OP_UNMAP,
810f72c2db4SDanilo Krummrich 
811f72c2db4SDanilo Krummrich 	/**
812f72c2db4SDanilo Krummrich 	 * @DRM_GPUVA_OP_PREFETCH: the prefetch op type
813f72c2db4SDanilo Krummrich 	 */
814f72c2db4SDanilo Krummrich 	DRM_GPUVA_OP_PREFETCH,
815*e53c1e26SMatthew Brost 
816*e53c1e26SMatthew Brost 	/**
817*e53c1e26SMatthew Brost 	 * @DRM_GPUVA_OP_DRIVER: the driver defined op type
818*e53c1e26SMatthew Brost 	 */
819*e53c1e26SMatthew Brost 	DRM_GPUVA_OP_DRIVER,
820f72c2db4SDanilo Krummrich };
821f72c2db4SDanilo Krummrich 
822f72c2db4SDanilo Krummrich /**
823f72c2db4SDanilo Krummrich  * struct drm_gpuva_op_map - GPU VA map operation
824f72c2db4SDanilo Krummrich  *
825f72c2db4SDanilo Krummrich  * This structure represents a single map operation generated by the
826f72c2db4SDanilo Krummrich  * DRM GPU VA manager.
827f72c2db4SDanilo Krummrich  */
828f72c2db4SDanilo Krummrich struct drm_gpuva_op_map {
829f72c2db4SDanilo Krummrich 	/**
830f72c2db4SDanilo Krummrich 	 * @va: structure containing address and range of a map
831f72c2db4SDanilo Krummrich 	 * operation
832f72c2db4SDanilo Krummrich 	 */
833f72c2db4SDanilo Krummrich 	struct {
834f72c2db4SDanilo Krummrich 		/**
835200a6b3aSRandy Dunlap 		 * @va.addr: the base address of the new mapping
836f72c2db4SDanilo Krummrich 		 */
837f72c2db4SDanilo Krummrich 		u64 addr;
838f72c2db4SDanilo Krummrich 
839f72c2db4SDanilo Krummrich 		/**
840200a6b3aSRandy Dunlap 		 * @va.range: the range of the new mapping
841f72c2db4SDanilo Krummrich 		 */
842f72c2db4SDanilo Krummrich 		u64 range;
843f72c2db4SDanilo Krummrich 	} va;
844f72c2db4SDanilo Krummrich 
845f72c2db4SDanilo Krummrich 	/**
846f72c2db4SDanilo Krummrich 	 * @gem: structure containing the &drm_gem_object and it's offset
847f72c2db4SDanilo Krummrich 	 */
848f72c2db4SDanilo Krummrich 	struct {
849f72c2db4SDanilo Krummrich 		/**
850200a6b3aSRandy Dunlap 		 * @gem.offset: the offset within the &drm_gem_object
851f72c2db4SDanilo Krummrich 		 */
852f72c2db4SDanilo Krummrich 		u64 offset;
853f72c2db4SDanilo Krummrich 
854f72c2db4SDanilo Krummrich 		/**
855200a6b3aSRandy Dunlap 		 * @gem.obj: the &drm_gem_object to map
856f72c2db4SDanilo Krummrich 		 */
857f72c2db4SDanilo Krummrich 		struct drm_gem_object *obj;
858f72c2db4SDanilo Krummrich 	} gem;
859f72c2db4SDanilo Krummrich };
860f72c2db4SDanilo Krummrich 
861f72c2db4SDanilo Krummrich /**
862f72c2db4SDanilo Krummrich  * struct drm_gpuva_op_unmap - GPU VA unmap operation
863f72c2db4SDanilo Krummrich  *
864f72c2db4SDanilo Krummrich  * This structure represents a single unmap operation generated by the
865f72c2db4SDanilo Krummrich  * DRM GPU VA manager.
866f72c2db4SDanilo Krummrich  */
867f72c2db4SDanilo Krummrich struct drm_gpuva_op_unmap {
868f72c2db4SDanilo Krummrich 	/**
869f72c2db4SDanilo Krummrich 	 * @va: the &drm_gpuva to unmap
870f72c2db4SDanilo Krummrich 	 */
871f72c2db4SDanilo Krummrich 	struct drm_gpuva *va;
872f72c2db4SDanilo Krummrich 
873f72c2db4SDanilo Krummrich 	/**
874f72c2db4SDanilo Krummrich 	 * @keep:
875f72c2db4SDanilo Krummrich 	 *
876f72c2db4SDanilo Krummrich 	 * Indicates whether this &drm_gpuva is physically contiguous with the
877f72c2db4SDanilo Krummrich 	 * original mapping request.
878f72c2db4SDanilo Krummrich 	 *
879f72c2db4SDanilo Krummrich 	 * Optionally, if &keep is set, drivers may keep the actual page table
880f72c2db4SDanilo Krummrich 	 * mappings for this &drm_gpuva, adding the missing page table entries
881f72c2db4SDanilo Krummrich 	 * only and update the &drm_gpuvm accordingly.
882f72c2db4SDanilo Krummrich 	 */
883f72c2db4SDanilo Krummrich 	bool keep;
884f72c2db4SDanilo Krummrich };
885f72c2db4SDanilo Krummrich 
886f72c2db4SDanilo Krummrich /**
887f72c2db4SDanilo Krummrich  * struct drm_gpuva_op_remap - GPU VA remap operation
888f72c2db4SDanilo Krummrich  *
889f72c2db4SDanilo Krummrich  * This represents a single remap operation generated by the DRM GPU VA manager.
890f72c2db4SDanilo Krummrich  *
891f72c2db4SDanilo Krummrich  * A remap operation is generated when an existing GPU VA mmapping is split up
892f72c2db4SDanilo Krummrich  * by inserting a new GPU VA mapping or by partially unmapping existent
893f72c2db4SDanilo Krummrich  * mapping(s), hence it consists of a maximum of two map and one unmap
894f72c2db4SDanilo Krummrich  * operation.
895f72c2db4SDanilo Krummrich  *
896f72c2db4SDanilo Krummrich  * The @unmap operation takes care of removing the original existing mapping.
897f72c2db4SDanilo Krummrich  * @prev is used to remap the preceding part, @next the subsequent part.
898f72c2db4SDanilo Krummrich  *
899f72c2db4SDanilo Krummrich  * If either a new mapping's start address is aligned with the start address
900f72c2db4SDanilo Krummrich  * of the old mapping or the new mapping's end address is aligned with the
901f72c2db4SDanilo Krummrich  * end address of the old mapping, either @prev or @next is NULL.
902f72c2db4SDanilo Krummrich  *
903f72c2db4SDanilo Krummrich  * Note, the reason for a dedicated remap operation, rather than arbitrary
904f72c2db4SDanilo Krummrich  * unmap and map operations, is to give drivers the chance of extracting driver
905f72c2db4SDanilo Krummrich  * specific data for creating the new mappings from the unmap operations's
906f72c2db4SDanilo Krummrich  * &drm_gpuva structure which typically is embedded in larger driver specific
907f72c2db4SDanilo Krummrich  * structures.
908f72c2db4SDanilo Krummrich  */
909f72c2db4SDanilo Krummrich struct drm_gpuva_op_remap {
910f72c2db4SDanilo Krummrich 	/**
911f72c2db4SDanilo Krummrich 	 * @prev: the preceding part of a split mapping
912f72c2db4SDanilo Krummrich 	 */
913f72c2db4SDanilo Krummrich 	struct drm_gpuva_op_map *prev;
914f72c2db4SDanilo Krummrich 
915f72c2db4SDanilo Krummrich 	/**
916f72c2db4SDanilo Krummrich 	 * @next: the subsequent part of a split mapping
917f72c2db4SDanilo Krummrich 	 */
918f72c2db4SDanilo Krummrich 	struct drm_gpuva_op_map *next;
919f72c2db4SDanilo Krummrich 
920f72c2db4SDanilo Krummrich 	/**
921f72c2db4SDanilo Krummrich 	 * @unmap: the unmap operation for the original existing mapping
922f72c2db4SDanilo Krummrich 	 */
923f72c2db4SDanilo Krummrich 	struct drm_gpuva_op_unmap *unmap;
924f72c2db4SDanilo Krummrich };
925f72c2db4SDanilo Krummrich 
926f72c2db4SDanilo Krummrich /**
927f72c2db4SDanilo Krummrich  * struct drm_gpuva_op_prefetch - GPU VA prefetch operation
928f72c2db4SDanilo Krummrich  *
929f72c2db4SDanilo Krummrich  * This structure represents a single prefetch operation generated by the
930f72c2db4SDanilo Krummrich  * DRM GPU VA manager.
931f72c2db4SDanilo Krummrich  */
932f72c2db4SDanilo Krummrich struct drm_gpuva_op_prefetch {
933f72c2db4SDanilo Krummrich 	/**
934f72c2db4SDanilo Krummrich 	 * @va: the &drm_gpuva to prefetch
935f72c2db4SDanilo Krummrich 	 */
936f72c2db4SDanilo Krummrich 	struct drm_gpuva *va;
937f72c2db4SDanilo Krummrich };
938f72c2db4SDanilo Krummrich 
939f72c2db4SDanilo Krummrich /**
940f72c2db4SDanilo Krummrich  * struct drm_gpuva_op - GPU VA operation
941f72c2db4SDanilo Krummrich  *
942f72c2db4SDanilo Krummrich  * This structure represents a single generic operation.
943f72c2db4SDanilo Krummrich  *
944f72c2db4SDanilo Krummrich  * The particular type of the operation is defined by @op.
945f72c2db4SDanilo Krummrich  */
946f72c2db4SDanilo Krummrich struct drm_gpuva_op {
947f72c2db4SDanilo Krummrich 	/**
948f72c2db4SDanilo Krummrich 	 * @entry:
949f72c2db4SDanilo Krummrich 	 *
950f72c2db4SDanilo Krummrich 	 * The &list_head used to distribute instances of this struct within
951f72c2db4SDanilo Krummrich 	 * &drm_gpuva_ops.
952f72c2db4SDanilo Krummrich 	 */
953f72c2db4SDanilo Krummrich 	struct list_head entry;
954f72c2db4SDanilo Krummrich 
955f72c2db4SDanilo Krummrich 	/**
956f72c2db4SDanilo Krummrich 	 * @op: the type of the operation
957f72c2db4SDanilo Krummrich 	 */
958f72c2db4SDanilo Krummrich 	enum drm_gpuva_op_type op;
959f72c2db4SDanilo Krummrich 
960f72c2db4SDanilo Krummrich 	union {
961f72c2db4SDanilo Krummrich 		/**
962f72c2db4SDanilo Krummrich 		 * @map: the map operation
963f72c2db4SDanilo Krummrich 		 */
964f72c2db4SDanilo Krummrich 		struct drm_gpuva_op_map map;
965f72c2db4SDanilo Krummrich 
966f72c2db4SDanilo Krummrich 		/**
967f72c2db4SDanilo Krummrich 		 * @remap: the remap operation
968f72c2db4SDanilo Krummrich 		 */
969f72c2db4SDanilo Krummrich 		struct drm_gpuva_op_remap remap;
970f72c2db4SDanilo Krummrich 
971f72c2db4SDanilo Krummrich 		/**
972f72c2db4SDanilo Krummrich 		 * @unmap: the unmap operation
973f72c2db4SDanilo Krummrich 		 */
974f72c2db4SDanilo Krummrich 		struct drm_gpuva_op_unmap unmap;
975f72c2db4SDanilo Krummrich 
976f72c2db4SDanilo Krummrich 		/**
977f72c2db4SDanilo Krummrich 		 * @prefetch: the prefetch operation
978f72c2db4SDanilo Krummrich 		 */
979f72c2db4SDanilo Krummrich 		struct drm_gpuva_op_prefetch prefetch;
980f72c2db4SDanilo Krummrich 	};
981f72c2db4SDanilo Krummrich };
982f72c2db4SDanilo Krummrich 
983f72c2db4SDanilo Krummrich /**
984f72c2db4SDanilo Krummrich  * struct drm_gpuva_ops - wraps a list of &drm_gpuva_op
985f72c2db4SDanilo Krummrich  */
986f72c2db4SDanilo Krummrich struct drm_gpuva_ops {
987f72c2db4SDanilo Krummrich 	/**
988f72c2db4SDanilo Krummrich 	 * @list: the &list_head
989f72c2db4SDanilo Krummrich 	 */
990f72c2db4SDanilo Krummrich 	struct list_head list;
991f72c2db4SDanilo Krummrich };
992f72c2db4SDanilo Krummrich 
993f72c2db4SDanilo Krummrich /**
994f72c2db4SDanilo Krummrich  * drm_gpuva_for_each_op() - iterator to walk over &drm_gpuva_ops
995f72c2db4SDanilo Krummrich  * @op: &drm_gpuva_op to assign in each iteration step
996f72c2db4SDanilo Krummrich  * @ops: &drm_gpuva_ops to walk
997f72c2db4SDanilo Krummrich  *
998f72c2db4SDanilo Krummrich  * This iterator walks over all ops within a given list of operations.
999f72c2db4SDanilo Krummrich  */
1000f72c2db4SDanilo Krummrich #define drm_gpuva_for_each_op(op, ops) list_for_each_entry(op, &(ops)->list, entry)
1001f72c2db4SDanilo Krummrich 
1002f72c2db4SDanilo Krummrich /**
1003f72c2db4SDanilo Krummrich  * drm_gpuva_for_each_op_safe() - iterator to safely walk over &drm_gpuva_ops
1004f72c2db4SDanilo Krummrich  * @op: &drm_gpuva_op to assign in each iteration step
1005f72c2db4SDanilo Krummrich  * @next: &next &drm_gpuva_op to store the next step
1006f72c2db4SDanilo Krummrich  * @ops: &drm_gpuva_ops to walk
1007f72c2db4SDanilo Krummrich  *
1008f72c2db4SDanilo Krummrich  * This iterator walks over all ops within a given list of operations. It is
1009f72c2db4SDanilo Krummrich  * implemented with list_for_each_safe(), so save against removal of elements.
1010f72c2db4SDanilo Krummrich  */
1011f72c2db4SDanilo Krummrich #define drm_gpuva_for_each_op_safe(op, next, ops) \
1012f72c2db4SDanilo Krummrich 	list_for_each_entry_safe(op, next, &(ops)->list, entry)
1013f72c2db4SDanilo Krummrich 
1014f72c2db4SDanilo Krummrich /**
1015f72c2db4SDanilo Krummrich  * drm_gpuva_for_each_op_from_reverse() - iterate backwards from the given point
1016f72c2db4SDanilo Krummrich  * @op: &drm_gpuva_op to assign in each iteration step
1017f72c2db4SDanilo Krummrich  * @ops: &drm_gpuva_ops to walk
1018f72c2db4SDanilo Krummrich  *
1019f72c2db4SDanilo Krummrich  * This iterator walks over all ops within a given list of operations beginning
1020f72c2db4SDanilo Krummrich  * from the given operation in reverse order.
1021f72c2db4SDanilo Krummrich  */
1022f72c2db4SDanilo Krummrich #define drm_gpuva_for_each_op_from_reverse(op, ops) \
1023f72c2db4SDanilo Krummrich 	list_for_each_entry_from_reverse(op, &(ops)->list, entry)
1024f72c2db4SDanilo Krummrich 
1025f72c2db4SDanilo Krummrich /**
1026bbd52b61SMatthew Brost  * drm_gpuva_for_each_op_reverse - iterator to walk over &drm_gpuva_ops in reverse
1027bbd52b61SMatthew Brost  * @op: &drm_gpuva_op to assign in each iteration step
1028bbd52b61SMatthew Brost  * @ops: &drm_gpuva_ops to walk
1029bbd52b61SMatthew Brost  *
1030bbd52b61SMatthew Brost  * This iterator walks over all ops within a given list of operations in reverse
1031bbd52b61SMatthew Brost  */
1032bbd52b61SMatthew Brost #define drm_gpuva_for_each_op_reverse(op, ops) \
1033bbd52b61SMatthew Brost 	list_for_each_entry_reverse(op, &(ops)->list, entry)
1034bbd52b61SMatthew Brost 
1035bbd52b61SMatthew Brost /**
1036f72c2db4SDanilo Krummrich  * drm_gpuva_first_op() - returns the first &drm_gpuva_op from &drm_gpuva_ops
1037f72c2db4SDanilo Krummrich  * @ops: the &drm_gpuva_ops to get the fist &drm_gpuva_op from
1038f72c2db4SDanilo Krummrich  */
1039f72c2db4SDanilo Krummrich #define drm_gpuva_first_op(ops) \
1040f72c2db4SDanilo Krummrich 	list_first_entry(&(ops)->list, struct drm_gpuva_op, entry)
1041f72c2db4SDanilo Krummrich 
1042f72c2db4SDanilo Krummrich /**
1043f72c2db4SDanilo Krummrich  * drm_gpuva_last_op() - returns the last &drm_gpuva_op from &drm_gpuva_ops
1044f72c2db4SDanilo Krummrich  * @ops: the &drm_gpuva_ops to get the last &drm_gpuva_op from
1045f72c2db4SDanilo Krummrich  */
1046f72c2db4SDanilo Krummrich #define drm_gpuva_last_op(ops) \
1047f72c2db4SDanilo Krummrich 	list_last_entry(&(ops)->list, struct drm_gpuva_op, entry)
1048f72c2db4SDanilo Krummrich 
1049f72c2db4SDanilo Krummrich /**
1050f72c2db4SDanilo Krummrich  * drm_gpuva_prev_op() - previous &drm_gpuva_op in the list
1051f72c2db4SDanilo Krummrich  * @op: the current &drm_gpuva_op
1052f72c2db4SDanilo Krummrich  */
1053f72c2db4SDanilo Krummrich #define drm_gpuva_prev_op(op) list_prev_entry(op, entry)
1054f72c2db4SDanilo Krummrich 
1055f72c2db4SDanilo Krummrich /**
1056f72c2db4SDanilo Krummrich  * drm_gpuva_next_op() - next &drm_gpuva_op in the list
1057f72c2db4SDanilo Krummrich  * @op: the current &drm_gpuva_op
1058f72c2db4SDanilo Krummrich  */
1059f72c2db4SDanilo Krummrich #define drm_gpuva_next_op(op) list_next_entry(op, entry)
1060f72c2db4SDanilo Krummrich 
1061f72c2db4SDanilo Krummrich struct drm_gpuva_ops *
1062f72c2db4SDanilo Krummrich drm_gpuvm_sm_map_ops_create(struct drm_gpuvm *gpuvm,
1063f72c2db4SDanilo Krummrich 			    u64 addr, u64 range,
1064f72c2db4SDanilo Krummrich 			    struct drm_gem_object *obj, u64 offset);
1065f72c2db4SDanilo Krummrich struct drm_gpuva_ops *
1066f72c2db4SDanilo Krummrich drm_gpuvm_sm_unmap_ops_create(struct drm_gpuvm *gpuvm,
1067f72c2db4SDanilo Krummrich 			      u64 addr, u64 range);
1068f72c2db4SDanilo Krummrich 
1069f72c2db4SDanilo Krummrich struct drm_gpuva_ops *
1070f72c2db4SDanilo Krummrich drm_gpuvm_prefetch_ops_create(struct drm_gpuvm *gpuvm,
1071f72c2db4SDanilo Krummrich 				 u64 addr, u64 range);
1072f72c2db4SDanilo Krummrich 
1073f72c2db4SDanilo Krummrich struct drm_gpuva_ops *
107494bc2249SDanilo Krummrich drm_gpuvm_bo_unmap_ops_create(struct drm_gpuvm_bo *vm_bo);
1075f72c2db4SDanilo Krummrich 
1076f72c2db4SDanilo Krummrich void drm_gpuva_ops_free(struct drm_gpuvm *gpuvm,
1077f72c2db4SDanilo Krummrich 			struct drm_gpuva_ops *ops);
1078f72c2db4SDanilo Krummrich 
drm_gpuva_init_from_op(struct drm_gpuva * va,struct drm_gpuva_op_map * op)1079f72c2db4SDanilo Krummrich static inline void drm_gpuva_init_from_op(struct drm_gpuva *va,
1080f72c2db4SDanilo Krummrich 					  struct drm_gpuva_op_map *op)
1081f72c2db4SDanilo Krummrich {
1082f72c2db4SDanilo Krummrich 	drm_gpuva_init(va, op->va.addr, op->va.range,
1083f72c2db4SDanilo Krummrich 		       op->gem.obj, op->gem.offset);
1084f72c2db4SDanilo Krummrich }
1085f72c2db4SDanilo Krummrich 
1086f72c2db4SDanilo Krummrich /**
1087f72c2db4SDanilo Krummrich  * struct drm_gpuvm_ops - callbacks for split/merge steps
1088f72c2db4SDanilo Krummrich  *
1089f72c2db4SDanilo Krummrich  * This structure defines the callbacks used by &drm_gpuvm_sm_map and
1090f72c2db4SDanilo Krummrich  * &drm_gpuvm_sm_unmap to provide the split/merge steps for map and unmap
1091f72c2db4SDanilo Krummrich  * operations to drivers.
1092f72c2db4SDanilo Krummrich  */
1093f72c2db4SDanilo Krummrich struct drm_gpuvm_ops {
1094f72c2db4SDanilo Krummrich 	/**
10958af72338SDanilo Krummrich 	 * @vm_free: called when the last reference of a struct drm_gpuvm is
10968af72338SDanilo Krummrich 	 * dropped
10978af72338SDanilo Krummrich 	 *
10988af72338SDanilo Krummrich 	 * This callback is mandatory.
10998af72338SDanilo Krummrich 	 */
11008af72338SDanilo Krummrich 	void (*vm_free)(struct drm_gpuvm *gpuvm);
11018af72338SDanilo Krummrich 
11028af72338SDanilo Krummrich 	/**
1103f72c2db4SDanilo Krummrich 	 * @op_alloc: called when the &drm_gpuvm allocates
1104f72c2db4SDanilo Krummrich 	 * a struct drm_gpuva_op
1105f72c2db4SDanilo Krummrich 	 *
1106f72c2db4SDanilo Krummrich 	 * Some drivers may want to embed struct drm_gpuva_op into driver
1107f72c2db4SDanilo Krummrich 	 * specific structures. By implementing this callback drivers can
1108f72c2db4SDanilo Krummrich 	 * allocate memory accordingly.
1109f72c2db4SDanilo Krummrich 	 *
1110f72c2db4SDanilo Krummrich 	 * This callback is optional.
1111f72c2db4SDanilo Krummrich 	 */
1112f72c2db4SDanilo Krummrich 	struct drm_gpuva_op *(*op_alloc)(void);
1113f72c2db4SDanilo Krummrich 
1114f72c2db4SDanilo Krummrich 	/**
1115f72c2db4SDanilo Krummrich 	 * @op_free: called when the &drm_gpuvm frees a
1116f72c2db4SDanilo Krummrich 	 * struct drm_gpuva_op
1117f72c2db4SDanilo Krummrich 	 *
1118f72c2db4SDanilo Krummrich 	 * Some drivers may want to embed struct drm_gpuva_op into driver
1119f72c2db4SDanilo Krummrich 	 * specific structures. By implementing this callback drivers can
1120f72c2db4SDanilo Krummrich 	 * free the previously allocated memory accordingly.
1121f72c2db4SDanilo Krummrich 	 *
1122f72c2db4SDanilo Krummrich 	 * This callback is optional.
1123f72c2db4SDanilo Krummrich 	 */
1124f72c2db4SDanilo Krummrich 	void (*op_free)(struct drm_gpuva_op *op);
1125f72c2db4SDanilo Krummrich 
1126f72c2db4SDanilo Krummrich 	/**
112794bc2249SDanilo Krummrich 	 * @vm_bo_alloc: called when the &drm_gpuvm allocates
112894bc2249SDanilo Krummrich 	 * a struct drm_gpuvm_bo
112994bc2249SDanilo Krummrich 	 *
113094bc2249SDanilo Krummrich 	 * Some drivers may want to embed struct drm_gpuvm_bo into driver
113194bc2249SDanilo Krummrich 	 * specific structures. By implementing this callback drivers can
113294bc2249SDanilo Krummrich 	 * allocate memory accordingly.
113394bc2249SDanilo Krummrich 	 *
113494bc2249SDanilo Krummrich 	 * This callback is optional.
113594bc2249SDanilo Krummrich 	 */
113694bc2249SDanilo Krummrich 	struct drm_gpuvm_bo *(*vm_bo_alloc)(void);
113794bc2249SDanilo Krummrich 
113894bc2249SDanilo Krummrich 	/**
113994bc2249SDanilo Krummrich 	 * @vm_bo_free: called when the &drm_gpuvm frees a
114094bc2249SDanilo Krummrich 	 * struct drm_gpuvm_bo
114194bc2249SDanilo Krummrich 	 *
114294bc2249SDanilo Krummrich 	 * Some drivers may want to embed struct drm_gpuvm_bo into driver
114394bc2249SDanilo Krummrich 	 * specific structures. By implementing this callback drivers can
114494bc2249SDanilo Krummrich 	 * free the previously allocated memory accordingly.
114594bc2249SDanilo Krummrich 	 *
114694bc2249SDanilo Krummrich 	 * This callback is optional.
114794bc2249SDanilo Krummrich 	 */
114894bc2249SDanilo Krummrich 	void (*vm_bo_free)(struct drm_gpuvm_bo *vm_bo);
114994bc2249SDanilo Krummrich 
115094bc2249SDanilo Krummrich 	/**
115150c1a36fSDanilo Krummrich 	 * @vm_bo_validate: called from drm_gpuvm_validate()
115250c1a36fSDanilo Krummrich 	 *
115350c1a36fSDanilo Krummrich 	 * Drivers receive this callback for every evicted &drm_gem_object being
115450c1a36fSDanilo Krummrich 	 * mapped in the corresponding &drm_gpuvm.
115550c1a36fSDanilo Krummrich 	 *
115650c1a36fSDanilo Krummrich 	 * Typically, drivers would call their driver specific variant of
115750c1a36fSDanilo Krummrich 	 * ttm_bo_validate() from within this callback.
115850c1a36fSDanilo Krummrich 	 */
115950c1a36fSDanilo Krummrich 	int (*vm_bo_validate)(struct drm_gpuvm_bo *vm_bo,
116050c1a36fSDanilo Krummrich 			      struct drm_exec *exec);
116150c1a36fSDanilo Krummrich 
116250c1a36fSDanilo Krummrich 	/**
1163f72c2db4SDanilo Krummrich 	 * @sm_step_map: called from &drm_gpuvm_sm_map to finally insert the
1164f72c2db4SDanilo Krummrich 	 * mapping once all previous steps were completed
1165f72c2db4SDanilo Krummrich 	 *
1166f72c2db4SDanilo Krummrich 	 * The &priv pointer matches the one the driver passed to
1167f72c2db4SDanilo Krummrich 	 * &drm_gpuvm_sm_map or &drm_gpuvm_sm_unmap, respectively.
1168f72c2db4SDanilo Krummrich 	 *
1169f72c2db4SDanilo Krummrich 	 * Can be NULL if &drm_gpuvm_sm_map is used.
1170f72c2db4SDanilo Krummrich 	 */
1171f72c2db4SDanilo Krummrich 	int (*sm_step_map)(struct drm_gpuva_op *op, void *priv);
1172f72c2db4SDanilo Krummrich 
1173f72c2db4SDanilo Krummrich 	/**
1174f72c2db4SDanilo Krummrich 	 * @sm_step_remap: called from &drm_gpuvm_sm_map and
1175f72c2db4SDanilo Krummrich 	 * &drm_gpuvm_sm_unmap to split up an existent mapping
1176f72c2db4SDanilo Krummrich 	 *
1177f72c2db4SDanilo Krummrich 	 * This callback is called when existent mapping needs to be split up.
1178f72c2db4SDanilo Krummrich 	 * This is the case when either a newly requested mapping overlaps or
1179f72c2db4SDanilo Krummrich 	 * is enclosed by an existent mapping or a partial unmap of an existent
1180f72c2db4SDanilo Krummrich 	 * mapping is requested.
1181f72c2db4SDanilo Krummrich 	 *
1182f72c2db4SDanilo Krummrich 	 * The &priv pointer matches the one the driver passed to
1183f72c2db4SDanilo Krummrich 	 * &drm_gpuvm_sm_map or &drm_gpuvm_sm_unmap, respectively.
1184f72c2db4SDanilo Krummrich 	 *
1185f72c2db4SDanilo Krummrich 	 * Can be NULL if neither &drm_gpuvm_sm_map nor &drm_gpuvm_sm_unmap is
1186f72c2db4SDanilo Krummrich 	 * used.
1187f72c2db4SDanilo Krummrich 	 */
1188f72c2db4SDanilo Krummrich 	int (*sm_step_remap)(struct drm_gpuva_op *op, void *priv);
1189f72c2db4SDanilo Krummrich 
1190f72c2db4SDanilo Krummrich 	/**
1191f72c2db4SDanilo Krummrich 	 * @sm_step_unmap: called from &drm_gpuvm_sm_map and
1192f72c2db4SDanilo Krummrich 	 * &drm_gpuvm_sm_unmap to unmap an existent mapping
1193f72c2db4SDanilo Krummrich 	 *
1194f72c2db4SDanilo Krummrich 	 * This callback is called when existent mapping needs to be unmapped.
1195f72c2db4SDanilo Krummrich 	 * This is the case when either a newly requested mapping encloses an
1196f72c2db4SDanilo Krummrich 	 * existent mapping or an unmap of an existent mapping is requested.
1197f72c2db4SDanilo Krummrich 	 *
1198f72c2db4SDanilo Krummrich 	 * The &priv pointer matches the one the driver passed to
1199f72c2db4SDanilo Krummrich 	 * &drm_gpuvm_sm_map or &drm_gpuvm_sm_unmap, respectively.
1200f72c2db4SDanilo Krummrich 	 *
1201f72c2db4SDanilo Krummrich 	 * Can be NULL if neither &drm_gpuvm_sm_map nor &drm_gpuvm_sm_unmap is
1202f72c2db4SDanilo Krummrich 	 * used.
1203f72c2db4SDanilo Krummrich 	 */
1204f72c2db4SDanilo Krummrich 	int (*sm_step_unmap)(struct drm_gpuva_op *op, void *priv);
1205f72c2db4SDanilo Krummrich };
1206f72c2db4SDanilo Krummrich 
1207f72c2db4SDanilo Krummrich int drm_gpuvm_sm_map(struct drm_gpuvm *gpuvm, void *priv,
1208f72c2db4SDanilo Krummrich 		     u64 addr, u64 range,
1209f72c2db4SDanilo Krummrich 		     struct drm_gem_object *obj, u64 offset);
1210f72c2db4SDanilo Krummrich 
1211f72c2db4SDanilo Krummrich int drm_gpuvm_sm_unmap(struct drm_gpuvm *gpuvm, void *priv,
1212f72c2db4SDanilo Krummrich 		       u64 addr, u64 range);
1213f72c2db4SDanilo Krummrich 
1214f72c2db4SDanilo Krummrich void drm_gpuva_map(struct drm_gpuvm *gpuvm,
1215f72c2db4SDanilo Krummrich 		   struct drm_gpuva *va,
1216f72c2db4SDanilo Krummrich 		   struct drm_gpuva_op_map *op);
1217f72c2db4SDanilo Krummrich 
1218f72c2db4SDanilo Krummrich void drm_gpuva_remap(struct drm_gpuva *prev,
1219f72c2db4SDanilo Krummrich 		     struct drm_gpuva *next,
1220f72c2db4SDanilo Krummrich 		     struct drm_gpuva_op_remap *op);
1221f72c2db4SDanilo Krummrich 
1222f72c2db4SDanilo Krummrich void drm_gpuva_unmap(struct drm_gpuva_op_unmap *op);
1223f72c2db4SDanilo Krummrich 
1224a191f73dSDonald Robson /**
1225a191f73dSDonald Robson  * drm_gpuva_op_remap_to_unmap_range() - Helper to get the start and range of
1226a191f73dSDonald Robson  * the unmap stage of a remap op.
1227a191f73dSDonald Robson  * @op: Remap op.
1228a191f73dSDonald Robson  * @start_addr: Output pointer for the start of the required unmap.
1229a191f73dSDonald Robson  * @range: Output pointer for the length of the required unmap.
1230a191f73dSDonald Robson  *
1231a191f73dSDonald Robson  * The given start address and range will be set such that they represent the
1232a191f73dSDonald Robson  * range of the address space that was previously covered by the mapping being
1233a191f73dSDonald Robson  * re-mapped, but is now empty.
1234a191f73dSDonald Robson  */
1235a191f73dSDonald Robson static inline void
drm_gpuva_op_remap_to_unmap_range(const struct drm_gpuva_op_remap * op,u64 * start_addr,u64 * range)1236a191f73dSDonald Robson drm_gpuva_op_remap_to_unmap_range(const struct drm_gpuva_op_remap *op,
1237a191f73dSDonald Robson 				  u64 *start_addr, u64 *range)
1238a191f73dSDonald Robson {
1239a191f73dSDonald Robson 	const u64 va_start = op->prev ?
1240a191f73dSDonald Robson 			     op->prev->va.addr + op->prev->va.range :
1241a191f73dSDonald Robson 			     op->unmap->va->va.addr;
1242a191f73dSDonald Robson 	const u64 va_end = op->next ?
1243a191f73dSDonald Robson 			   op->next->va.addr :
1244a191f73dSDonald Robson 			   op->unmap->va->va.addr + op->unmap->va->va.range;
1245a191f73dSDonald Robson 
1246a191f73dSDonald Robson 	if (start_addr)
1247a191f73dSDonald Robson 		*start_addr = va_start;
1248a191f73dSDonald Robson 	if (range)
1249a191f73dSDonald Robson 		*range = va_end - va_start;
1250a191f73dSDonald Robson }
1251a191f73dSDonald Robson 
1252f72c2db4SDanilo Krummrich #endif /* __DRM_GPUVM_H__ */
1253