]> Git Repo - J-linux.git/blob - drivers/gpu/drm/drm_gpuvm.c
drm/amdgpu: SW part of MES event log enablement
[J-linux.git] / drivers / gpu / drm / drm_gpuvm.c
1 // SPDX-License-Identifier: GPL-2.0 OR MIT
2 /*
3  * Copyright (c) 2022 Red Hat.
4  *
5  * Permission is hereby granted, free of charge, to any person obtaining a
6  * copy of this software and associated documentation files (the "Software"),
7  * to deal in the Software without restriction, including without limitation
8  * the rights to use, copy, modify, merge, publish, distribute, sublicense,
9  * and/or sell copies of the Software, and to permit persons to whom the
10  * Software is furnished to do so, subject to the following conditions:
11  *
12  * The above copyright notice and this permission notice shall be included in
13  * all copies or substantial portions of the Software.
14  *
15  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16  * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17  * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
18  * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR
19  * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
20  * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
21  * OTHER DEALINGS IN THE SOFTWARE.
22  *
23  * Authors:
24  *     Danilo Krummrich <[email protected]>
25  *
26  */
27
28 #include <drm/drm_gpuvm.h>
29
30 #include <linux/interval_tree_generic.h>
31 #include <linux/mm.h>
32
33 /**
34  * DOC: Overview
35  *
36  * The DRM GPU VA Manager, represented by struct drm_gpuvm keeps track of a
37  * GPU's virtual address (VA) space and manages the corresponding virtual
38  * mappings represented by &drm_gpuva objects. It also keeps track of the
39  * mapping's backing &drm_gem_object buffers.
40  *
41  * &drm_gem_object buffers maintain a list of &drm_gpuva objects representing
42  * all existent GPU VA mappings using this &drm_gem_object as backing buffer.
43  *
44  * GPU VAs can be flagged as sparse, such that drivers may use GPU VAs to also
45  * keep track of sparse PTEs in order to support Vulkan 'Sparse Resources'.
46  *
47  * The GPU VA manager internally uses a rb-tree to manage the
48  * &drm_gpuva mappings within a GPU's virtual address space.
49  *
50  * The &drm_gpuvm structure contains a special &drm_gpuva representing the
51  * portion of VA space reserved by the kernel. This node is initialized together
52  * with the GPU VA manager instance and removed when the GPU VA manager is
53  * destroyed.
54  *
55  * In a typical application drivers would embed struct drm_gpuvm and
56  * struct drm_gpuva within their own driver specific structures, there won't be
57  * any memory allocations of its own nor memory allocations of &drm_gpuva
58  * entries.
59  *
60  * The data structures needed to store &drm_gpuvas within the &drm_gpuvm are
61  * contained within struct drm_gpuva already. Hence, for inserting &drm_gpuva
62  * entries from within dma-fence signalling critical sections it is enough to
63  * pre-allocate the &drm_gpuva structures.
64  *
65  * &drm_gem_objects which are private to a single VM can share a common
66  * &dma_resv in order to improve locking efficiency (e.g. with &drm_exec).
67  * For this purpose drivers must pass a &drm_gem_object to drm_gpuvm_init(), in
68  * the following called 'resv object', which serves as the container of the
69  * GPUVM's shared &dma_resv. This resv object can be a driver specific
70  * &drm_gem_object, such as the &drm_gem_object containing the root page table,
71  * but it can also be a 'dummy' object, which can be allocated with
72  * drm_gpuvm_resv_object_alloc().
73  *
74  * In order to connect a struct drm_gpuva its backing &drm_gem_object each
75  * &drm_gem_object maintains a list of &drm_gpuvm_bo structures, and each
76  * &drm_gpuvm_bo contains a list of &drm_gpuva structures.
77  *
78  * A &drm_gpuvm_bo is an abstraction that represents a combination of a
79  * &drm_gpuvm and a &drm_gem_object. Every such combination should be unique.
80  * This is ensured by the API through drm_gpuvm_bo_obtain() and
81  * drm_gpuvm_bo_obtain_prealloc() which first look into the corresponding
82  * &drm_gem_object list of &drm_gpuvm_bos for an existing instance of this
83  * particular combination. If not existent a new instance is created and linked
84  * to the &drm_gem_object.
85  *
86  * &drm_gpuvm_bo structures, since unique for a given &drm_gpuvm, are also used
87  * as entry for the &drm_gpuvm's lists of external and evicted objects. Those
88  * lists are maintained in order to accelerate locking of dma-resv locks and
89  * validation of evicted objects bound in a &drm_gpuvm. For instance, all
90  * &drm_gem_object's &dma_resv of a given &drm_gpuvm can be locked by calling
91  * drm_gpuvm_exec_lock(). Once locked drivers can call drm_gpuvm_validate() in
92  * order to validate all evicted &drm_gem_objects. It is also possible to lock
93  * additional &drm_gem_objects by providing the corresponding parameters to
94  * drm_gpuvm_exec_lock() as well as open code the &drm_exec loop while making
95  * use of helper functions such as drm_gpuvm_prepare_range() or
96  * drm_gpuvm_prepare_objects().
97  *
98  * Every bound &drm_gem_object is treated as external object when its &dma_resv
99  * structure is different than the &drm_gpuvm's common &dma_resv structure.
100  */
101
102 /**
103  * DOC: Split and Merge
104  *
105  * Besides its capability to manage and represent a GPU VA space, the
106  * GPU VA manager also provides functions to let the &drm_gpuvm calculate a
107  * sequence of operations to satisfy a given map or unmap request.
108  *
109  * Therefore the DRM GPU VA manager provides an algorithm implementing splitting
110  * and merging of existent GPU VA mappings with the ones that are requested to
111  * be mapped or unmapped. This feature is required by the Vulkan API to
112  * implement Vulkan 'Sparse Memory Bindings' - drivers UAPIs often refer to this
113  * as VM BIND.
114  *
115  * Drivers can call drm_gpuvm_sm_map() to receive a sequence of callbacks
116  * containing map, unmap and remap operations for a given newly requested
117  * mapping. The sequence of callbacks represents the set of operations to
118  * execute in order to integrate the new mapping cleanly into the current state
119  * of the GPU VA space.
120  *
121  * Depending on how the new GPU VA mapping intersects with the existent mappings
122  * of the GPU VA space the &drm_gpuvm_ops callbacks contain an arbitrary amount
123  * of unmap operations, a maximum of two remap operations and a single map
124  * operation. The caller might receive no callback at all if no operation is
125  * required, e.g. if the requested mapping already exists in the exact same way.
126  *
127  * The single map operation represents the original map operation requested by
128  * the caller.
129  *
130  * &drm_gpuva_op_unmap contains a 'keep' field, which indicates whether the
131  * &drm_gpuva to unmap is physically contiguous with the original mapping
132  * request. Optionally, if 'keep' is set, drivers may keep the actual page table
133  * entries for this &drm_gpuva, adding the missing page table entries only and
134  * update the &drm_gpuvm's view of things accordingly.
135  *
136  * Drivers may do the same optimization, namely delta page table updates, also
137  * for remap operations. This is possible since &drm_gpuva_op_remap consists of
138  * one unmap operation and one or two map operations, such that drivers can
139  * derive the page table update delta accordingly.
140  *
141  * Note that there can't be more than two existent mappings to split up, one at
142  * the beginning and one at the end of the new mapping, hence there is a
143  * maximum of two remap operations.
144  *
145  * Analogous to drm_gpuvm_sm_map() drm_gpuvm_sm_unmap() uses &drm_gpuvm_ops to
146  * call back into the driver in order to unmap a range of GPU VA space. The
147  * logic behind this function is way simpler though: For all existent mappings
148  * enclosed by the given range unmap operations are created. For mappings which
149  * are only partically located within the given range, remap operations are
150  * created such that those mappings are split up and re-mapped partically.
151  *
152  * As an alternative to drm_gpuvm_sm_map() and drm_gpuvm_sm_unmap(),
153  * drm_gpuvm_sm_map_ops_create() and drm_gpuvm_sm_unmap_ops_create() can be used
154  * to directly obtain an instance of struct drm_gpuva_ops containing a list of
155  * &drm_gpuva_op, which can be iterated with drm_gpuva_for_each_op(). This list
156  * contains the &drm_gpuva_ops analogous to the callbacks one would receive when
157  * calling drm_gpuvm_sm_map() or drm_gpuvm_sm_unmap(). While this way requires
158  * more memory (to allocate the &drm_gpuva_ops), it provides drivers a way to
159  * iterate the &drm_gpuva_op multiple times, e.g. once in a context where memory
160  * allocations are possible (e.g. to allocate GPU page tables) and once in the
161  * dma-fence signalling critical path.
162  *
163  * To update the &drm_gpuvm's view of the GPU VA space drm_gpuva_insert() and
164  * drm_gpuva_remove() may be used. These functions can safely be used from
165  * &drm_gpuvm_ops callbacks originating from drm_gpuvm_sm_map() or
166  * drm_gpuvm_sm_unmap(). However, it might be more convenient to use the
167  * provided helper functions drm_gpuva_map(), drm_gpuva_remap() and
168  * drm_gpuva_unmap() instead.
169  *
170  * The following diagram depicts the basic relationships of existent GPU VA
171  * mappings, a newly requested mapping and the resulting mappings as implemented
172  * by drm_gpuvm_sm_map() - it doesn't cover any arbitrary combinations of these.
173  *
174  * 1) Requested mapping is identical. Replace it, but indicate the backing PTEs
175  *    could be kept.
176  *
177  *    ::
178  *
179  *           0     a     1
180  *      old: |-----------| (bo_offset=n)
181  *
182  *           0     a     1
183  *      req: |-----------| (bo_offset=n)
184  *
185  *           0     a     1
186  *      new: |-----------| (bo_offset=n)
187  *
188  *
189  * 2) Requested mapping is identical, except for the BO offset, hence replace
190  *    the mapping.
191  *
192  *    ::
193  *
194  *           0     a     1
195  *      old: |-----------| (bo_offset=n)
196  *
197  *           0     a     1
198  *      req: |-----------| (bo_offset=m)
199  *
200  *           0     a     1
201  *      new: |-----------| (bo_offset=m)
202  *
203  *
204  * 3) Requested mapping is identical, except for the backing BO, hence replace
205  *    the mapping.
206  *
207  *    ::
208  *
209  *           0     a     1
210  *      old: |-----------| (bo_offset=n)
211  *
212  *           0     b     1
213  *      req: |-----------| (bo_offset=n)
214  *
215  *           0     b     1
216  *      new: |-----------| (bo_offset=n)
217  *
218  *
219  * 4) Existent mapping is a left aligned subset of the requested one, hence
220  *    replace the existent one.
221  *
222  *    ::
223  *
224  *           0  a  1
225  *      old: |-----|       (bo_offset=n)
226  *
227  *           0     a     2
228  *      req: |-----------| (bo_offset=n)
229  *
230  *           0     a     2
231  *      new: |-----------| (bo_offset=n)
232  *
233  *    .. note::
234  *       We expect to see the same result for a request with a different BO
235  *       and/or non-contiguous BO offset.
236  *
237  *
238  * 5) Requested mapping's range is a left aligned subset of the existent one,
239  *    but backed by a different BO. Hence, map the requested mapping and split
240  *    the existent one adjusting its BO offset.
241  *
242  *    ::
243  *
244  *           0     a     2
245  *      old: |-----------| (bo_offset=n)
246  *
247  *           0  b  1
248  *      req: |-----|       (bo_offset=n)
249  *
250  *           0  b  1  a' 2
251  *      new: |-----|-----| (b.bo_offset=n, a.bo_offset=n+1)
252  *
253  *    .. note::
254  *       We expect to see the same result for a request with a different BO
255  *       and/or non-contiguous BO offset.
256  *
257  *
258  * 6) Existent mapping is a superset of the requested mapping. Split it up, but
259  *    indicate that the backing PTEs could be kept.
260  *
261  *    ::
262  *
263  *           0     a     2
264  *      old: |-----------| (bo_offset=n)
265  *
266  *           0  a  1
267  *      req: |-----|       (bo_offset=n)
268  *
269  *           0  a  1  a' 2
270  *      new: |-----|-----| (a.bo_offset=n, a'.bo_offset=n+1)
271  *
272  *
273  * 7) Requested mapping's range is a right aligned subset of the existent one,
274  *    but backed by a different BO. Hence, map the requested mapping and split
275  *    the existent one, without adjusting the BO offset.
276  *
277  *    ::
278  *
279  *           0     a     2
280  *      old: |-----------| (bo_offset=n)
281  *
282  *                 1  b  2
283  *      req:       |-----| (bo_offset=m)
284  *
285  *           0  a  1  b  2
286  *      new: |-----|-----| (a.bo_offset=n,b.bo_offset=m)
287  *
288  *
289  * 8) Existent mapping is a superset of the requested mapping. Split it up, but
290  *    indicate that the backing PTEs could be kept.
291  *
292  *    ::
293  *
294  *            0     a     2
295  *      old: |-----------| (bo_offset=n)
296  *
297  *                 1  a  2
298  *      req:       |-----| (bo_offset=n+1)
299  *
300  *           0  a' 1  a  2
301  *      new: |-----|-----| (a'.bo_offset=n, a.bo_offset=n+1)
302  *
303  *
304  * 9) Existent mapping is overlapped at the end by the requested mapping backed
305  *    by a different BO. Hence, map the requested mapping and split up the
306  *    existent one, without adjusting the BO offset.
307  *
308  *    ::
309  *
310  *           0     a     2
311  *      old: |-----------|       (bo_offset=n)
312  *
313  *                 1     b     3
314  *      req:       |-----------| (bo_offset=m)
315  *
316  *           0  a  1     b     3
317  *      new: |-----|-----------| (a.bo_offset=n,b.bo_offset=m)
318  *
319  *
320  * 10) Existent mapping is overlapped by the requested mapping, both having the
321  *     same backing BO with a contiguous offset. Indicate the backing PTEs of
322  *     the old mapping could be kept.
323  *
324  *     ::
325  *
326  *            0     a     2
327  *       old: |-----------|       (bo_offset=n)
328  *
329  *                  1     a     3
330  *       req:       |-----------| (bo_offset=n+1)
331  *
332  *            0  a' 1     a     3
333  *       new: |-----|-----------| (a'.bo_offset=n, a.bo_offset=n+1)
334  *
335  *
336  * 11) Requested mapping's range is a centered subset of the existent one
337  *     having a different backing BO. Hence, map the requested mapping and split
338  *     up the existent one in two mappings, adjusting the BO offset of the right
339  *     one accordingly.
340  *
341  *     ::
342  *
343  *            0        a        3
344  *       old: |-----------------| (bo_offset=n)
345  *
346  *                  1  b  2
347  *       req:       |-----|       (bo_offset=m)
348  *
349  *            0  a  1  b  2  a' 3
350  *       new: |-----|-----|-----| (a.bo_offset=n,b.bo_offset=m,a'.bo_offset=n+2)
351  *
352  *
353  * 12) Requested mapping is a contiguous subset of the existent one. Split it
354  *     up, but indicate that the backing PTEs could be kept.
355  *
356  *     ::
357  *
358  *            0        a        3
359  *       old: |-----------------| (bo_offset=n)
360  *
361  *                  1  a  2
362  *       req:       |-----|       (bo_offset=n+1)
363  *
364  *            0  a' 1  a  2 a'' 3
365  *       old: |-----|-----|-----| (a'.bo_offset=n, a.bo_offset=n+1, a''.bo_offset=n+2)
366  *
367  *
368  * 13) Existent mapping is a right aligned subset of the requested one, hence
369  *     replace the existent one.
370  *
371  *     ::
372  *
373  *                  1  a  2
374  *       old:       |-----| (bo_offset=n+1)
375  *
376  *            0     a     2
377  *       req: |-----------| (bo_offset=n)
378  *
379  *            0     a     2
380  *       new: |-----------| (bo_offset=n)
381  *
382  *     .. note::
383  *        We expect to see the same result for a request with a different bo
384  *        and/or non-contiguous bo_offset.
385  *
386  *
387  * 14) Existent mapping is a centered subset of the requested one, hence
388  *     replace the existent one.
389  *
390  *     ::
391  *
392  *                  1  a  2
393  *       old:       |-----| (bo_offset=n+1)
394  *
395  *            0        a       3
396  *       req: |----------------| (bo_offset=n)
397  *
398  *            0        a       3
399  *       new: |----------------| (bo_offset=n)
400  *
401  *     .. note::
402  *        We expect to see the same result for a request with a different bo
403  *        and/or non-contiguous bo_offset.
404  *
405  *
406  * 15) Existent mappings is overlapped at the beginning by the requested mapping
407  *     backed by a different BO. Hence, map the requested mapping and split up
408  *     the existent one, adjusting its BO offset accordingly.
409  *
410  *     ::
411  *
412  *                  1     a     3
413  *       old:       |-----------| (bo_offset=n)
414  *
415  *            0     b     2
416  *       req: |-----------|       (bo_offset=m)
417  *
418  *            0     b     2  a' 3
419  *       new: |-----------|-----| (b.bo_offset=m,a.bo_offset=n+2)
420  */
421
422 /**
423  * DOC: Locking
424  *
425  * In terms of managing &drm_gpuva entries DRM GPUVM does not take care of
426  * locking itself, it is the drivers responsibility to take care about locking.
427  * Drivers might want to protect the following operations: inserting, removing
428  * and iterating &drm_gpuva objects as well as generating all kinds of
429  * operations, such as split / merge or prefetch.
430  *
431  * DRM GPUVM also does not take care of the locking of the backing
432  * &drm_gem_object buffers GPU VA lists and &drm_gpuvm_bo abstractions by
433  * itself; drivers are responsible to enforce mutual exclusion using either the
434  * GEMs dma_resv lock or alternatively a driver specific external lock. For the
435  * latter see also drm_gem_gpuva_set_lock().
436  *
437  * However, DRM GPUVM contains lockdep checks to ensure callers of its API hold
438  * the corresponding lock whenever the &drm_gem_objects GPU VA list is accessed
439  * by functions such as drm_gpuva_link() or drm_gpuva_unlink(), but also
440  * drm_gpuvm_bo_obtain() and drm_gpuvm_bo_put().
441  *
442  * The latter is required since on creation and destruction of a &drm_gpuvm_bo
443  * the &drm_gpuvm_bo is attached / removed from the &drm_gem_objects gpuva list.
444  * Subsequent calls to drm_gpuvm_bo_obtain() for the same &drm_gpuvm and
445  * &drm_gem_object must be able to observe previous creations and destructions
446  * of &drm_gpuvm_bos in order to keep instances unique.
447  *
448  * The &drm_gpuvm's lists for keeping track of external and evicted objects are
449  * protected against concurrent insertion / removal and iteration internally.
450  *
451  * However, drivers still need ensure to protect concurrent calls to functions
452  * iterating those lists, namely drm_gpuvm_prepare_objects() and
453  * drm_gpuvm_validate().
454  *
455  * Alternatively, drivers can set the &DRM_GPUVM_RESV_PROTECTED flag to indicate
456  * that the corresponding &dma_resv locks are held in order to protect the
457  * lists. If &DRM_GPUVM_RESV_PROTECTED is set, internal locking is disabled and
458  * the corresponding lockdep checks are enabled. This is an optimization for
459  * drivers which are capable of taking the corresponding &dma_resv locks and
460  * hence do not require internal locking.
461  */
462
463 /**
464  * DOC: Examples
465  *
466  * This section gives two examples on how to let the DRM GPUVA Manager generate
467  * &drm_gpuva_op in order to satisfy a given map or unmap request and how to
468  * make use of them.
469  *
470  * The below code is strictly limited to illustrate the generic usage pattern.
471  * To maintain simplicitly, it doesn't make use of any abstractions for common
472  * code, different (asyncronous) stages with fence signalling critical paths,
473  * any other helpers or error handling in terms of freeing memory and dropping
474  * previously taken locks.
475  *
476  * 1) Obtain a list of &drm_gpuva_op to create a new mapping::
477  *
478  *      // Allocates a new &drm_gpuva.
479  *      struct drm_gpuva * driver_gpuva_alloc(void);
480  *
481  *      // Typically drivers would embedd the &drm_gpuvm and &drm_gpuva
482  *      // structure in individual driver structures and lock the dma-resv with
483  *      // drm_exec or similar helpers.
484  *      int driver_mapping_create(struct drm_gpuvm *gpuvm,
485  *                                u64 addr, u64 range,
486  *                                struct drm_gem_object *obj, u64 offset)
487  *      {
488  *              struct drm_gpuva_ops *ops;
489  *              struct drm_gpuva_op *op
490  *              struct drm_gpuvm_bo *vm_bo;
491  *
492  *              driver_lock_va_space();
493  *              ops = drm_gpuvm_sm_map_ops_create(gpuvm, addr, range,
494  *                                                obj, offset);
495  *              if (IS_ERR(ops))
496  *                      return PTR_ERR(ops);
497  *
498  *              vm_bo = drm_gpuvm_bo_obtain(gpuvm, obj);
499  *              if (IS_ERR(vm_bo))
500  *                      return PTR_ERR(vm_bo);
501  *
502  *              drm_gpuva_for_each_op(op, ops) {
503  *                      struct drm_gpuva *va;
504  *
505  *                      switch (op->op) {
506  *                      case DRM_GPUVA_OP_MAP:
507  *                              va = driver_gpuva_alloc();
508  *                              if (!va)
509  *                                      ; // unwind previous VA space updates,
510  *                                        // free memory and unlock
511  *
512  *                              driver_vm_map();
513  *                              drm_gpuva_map(gpuvm, va, &op->map);
514  *                              drm_gpuva_link(va, vm_bo);
515  *
516  *                              break;
517  *                      case DRM_GPUVA_OP_REMAP: {
518  *                              struct drm_gpuva *prev = NULL, *next = NULL;
519  *
520  *                              va = op->remap.unmap->va;
521  *
522  *                              if (op->remap.prev) {
523  *                                      prev = driver_gpuva_alloc();
524  *                                      if (!prev)
525  *                                              ; // unwind previous VA space
526  *                                                // updates, free memory and
527  *                                                // unlock
528  *                              }
529  *
530  *                              if (op->remap.next) {
531  *                                      next = driver_gpuva_alloc();
532  *                                      if (!next)
533  *                                              ; // unwind previous VA space
534  *                                                // updates, free memory and
535  *                                                // unlock
536  *                              }
537  *
538  *                              driver_vm_remap();
539  *                              drm_gpuva_remap(prev, next, &op->remap);
540  *
541  *                              if (prev)
542  *                                      drm_gpuva_link(prev, va->vm_bo);
543  *                              if (next)
544  *                                      drm_gpuva_link(next, va->vm_bo);
545  *                              drm_gpuva_unlink(va);
546  *
547  *                              break;
548  *                      }
549  *                      case DRM_GPUVA_OP_UNMAP:
550  *                              va = op->unmap->va;
551  *
552  *                              driver_vm_unmap();
553  *                              drm_gpuva_unlink(va);
554  *                              drm_gpuva_unmap(&op->unmap);
555  *
556  *                              break;
557  *                      default:
558  *                              break;
559  *                      }
560  *              }
561  *              drm_gpuvm_bo_put(vm_bo);
562  *              driver_unlock_va_space();
563  *
564  *              return 0;
565  *      }
566  *
567  * 2) Receive a callback for each &drm_gpuva_op to create a new mapping::
568  *
569  *      struct driver_context {
570  *              struct drm_gpuvm *gpuvm;
571  *              struct drm_gpuvm_bo *vm_bo;
572  *              struct drm_gpuva *new_va;
573  *              struct drm_gpuva *prev_va;
574  *              struct drm_gpuva *next_va;
575  *      };
576  *
577  *      // ops to pass to drm_gpuvm_init()
578  *      static const struct drm_gpuvm_ops driver_gpuvm_ops = {
579  *              .sm_step_map = driver_gpuva_map,
580  *              .sm_step_remap = driver_gpuva_remap,
581  *              .sm_step_unmap = driver_gpuva_unmap,
582  *      };
583  *
584  *      // Typically drivers would embedd the &drm_gpuvm and &drm_gpuva
585  *      // structure in individual driver structures and lock the dma-resv with
586  *      // drm_exec or similar helpers.
587  *      int driver_mapping_create(struct drm_gpuvm *gpuvm,
588  *                                u64 addr, u64 range,
589  *                                struct drm_gem_object *obj, u64 offset)
590  *      {
591  *              struct driver_context ctx;
592  *              struct drm_gpuvm_bo *vm_bo;
593  *              struct drm_gpuva_ops *ops;
594  *              struct drm_gpuva_op *op;
595  *              int ret = 0;
596  *
597  *              ctx.gpuvm = gpuvm;
598  *
599  *              ctx.new_va = kzalloc(sizeof(*ctx.new_va), GFP_KERNEL);
600  *              ctx.prev_va = kzalloc(sizeof(*ctx.prev_va), GFP_KERNEL);
601  *              ctx.next_va = kzalloc(sizeof(*ctx.next_va), GFP_KERNEL);
602  *              ctx.vm_bo = drm_gpuvm_bo_create(gpuvm, obj);
603  *              if (!ctx.new_va || !ctx.prev_va || !ctx.next_va || !vm_bo) {
604  *                      ret = -ENOMEM;
605  *                      goto out;
606  *              }
607  *
608  *              // Typically protected with a driver specific GEM gpuva lock
609  *              // used in the fence signaling path for drm_gpuva_link() and
610  *              // drm_gpuva_unlink(), hence pre-allocate.
611  *              ctx.vm_bo = drm_gpuvm_bo_obtain_prealloc(ctx.vm_bo);
612  *
613  *              driver_lock_va_space();
614  *              ret = drm_gpuvm_sm_map(gpuvm, &ctx, addr, range, obj, offset);
615  *              driver_unlock_va_space();
616  *
617  *      out:
618  *              drm_gpuvm_bo_put(ctx.vm_bo);
619  *              kfree(ctx.new_va);
620  *              kfree(ctx.prev_va);
621  *              kfree(ctx.next_va);
622  *              return ret;
623  *      }
624  *
625  *      int driver_gpuva_map(struct drm_gpuva_op *op, void *__ctx)
626  *      {
627  *              struct driver_context *ctx = __ctx;
628  *
629  *              drm_gpuva_map(ctx->vm, ctx->new_va, &op->map);
630  *
631  *              drm_gpuva_link(ctx->new_va, ctx->vm_bo);
632  *
633  *              // prevent the new GPUVA from being freed in
634  *              // driver_mapping_create()
635  *              ctx->new_va = NULL;
636  *
637  *              return 0;
638  *      }
639  *
640  *      int driver_gpuva_remap(struct drm_gpuva_op *op, void *__ctx)
641  *      {
642  *              struct driver_context *ctx = __ctx;
643  *              struct drm_gpuva *va = op->remap.unmap->va;
644  *
645  *              drm_gpuva_remap(ctx->prev_va, ctx->next_va, &op->remap);
646  *
647  *              if (op->remap.prev) {
648  *                      drm_gpuva_link(ctx->prev_va, va->vm_bo);
649  *                      ctx->prev_va = NULL;
650  *              }
651  *
652  *              if (op->remap.next) {
653  *                      drm_gpuva_link(ctx->next_va, va->vm_bo);
654  *                      ctx->next_va = NULL;
655  *              }
656  *
657  *              drm_gpuva_unlink(va);
658  *              kfree(va);
659  *
660  *              return 0;
661  *      }
662  *
663  *      int driver_gpuva_unmap(struct drm_gpuva_op *op, void *__ctx)
664  *      {
665  *              drm_gpuva_unlink(op->unmap.va);
666  *              drm_gpuva_unmap(&op->unmap);
667  *              kfree(op->unmap.va);
668  *
669  *              return 0;
670  *      }
671  */
672
673 /**
674  * get_next_vm_bo_from_list() - get the next vm_bo element
675  * @__gpuvm: the &drm_gpuvm
676  * @__list_name: the name of the list we're iterating on
677  * @__local_list: a pointer to the local list used to store already iterated items
678  * @__prev_vm_bo: the previous element we got from get_next_vm_bo_from_list()
679  *
680  * This helper is here to provide lockless list iteration. Lockless as in, the
681  * iterator releases the lock immediately after picking the first element from
682  * the list, so list insertion deletion can happen concurrently.
683  *
684  * Elements popped from the original list are kept in a local list, so removal
685  * and is_empty checks can still happen while we're iterating the list.
686  */
687 #define get_next_vm_bo_from_list(__gpuvm, __list_name, __local_list, __prev_vm_bo)      \
688         ({                                                                              \
689                 struct drm_gpuvm_bo *__vm_bo = NULL;                                    \
690                                                                                         \
691                 drm_gpuvm_bo_put(__prev_vm_bo);                                         \
692                                                                                         \
693                 spin_lock(&(__gpuvm)->__list_name.lock);                                \
694                 if (!(__gpuvm)->__list_name.local_list)                                 \
695                         (__gpuvm)->__list_name.local_list = __local_list;               \
696                 else                                                                    \
697                         drm_WARN_ON((__gpuvm)->drm,                                     \
698                                     (__gpuvm)->__list_name.local_list != __local_list); \
699                                                                                         \
700                 while (!list_empty(&(__gpuvm)->__list_name.list)) {                     \
701                         __vm_bo = list_first_entry(&(__gpuvm)->__list_name.list,        \
702                                                    struct drm_gpuvm_bo,                 \
703                                                    list.entry.__list_name);             \
704                         if (kref_get_unless_zero(&__vm_bo->kref)) {                     \
705                                 list_move_tail(&(__vm_bo)->list.entry.__list_name,      \
706                                                __local_list);                           \
707                                 break;                                                  \
708                         } else {                                                        \
709                                 list_del_init(&(__vm_bo)->list.entry.__list_name);      \
710                                 __vm_bo = NULL;                                         \
711                         }                                                               \
712                 }                                                                       \
713                 spin_unlock(&(__gpuvm)->__list_name.lock);                              \
714                                                                                         \
715                 __vm_bo;                                                                \
716         })
717
718 /**
719  * for_each_vm_bo_in_list() - internal vm_bo list iterator
720  * @__gpuvm: the &drm_gpuvm
721  * @__list_name: the name of the list we're iterating on
722  * @__local_list: a pointer to the local list used to store already iterated items
723  * @__vm_bo: the struct drm_gpuvm_bo to assign in each iteration step
724  *
725  * This helper is here to provide lockless list iteration. Lockless as in, the
726  * iterator releases the lock immediately after picking the first element from the
727  * list, hence list insertion and deletion can happen concurrently.
728  *
729  * It is not allowed to re-assign the vm_bo pointer from inside this loop.
730  *
731  * Typical use:
732  *
733  *      struct drm_gpuvm_bo *vm_bo;
734  *      LIST_HEAD(my_local_list);
735  *
736  *      ret = 0;
737  *      for_each_vm_bo_in_list(gpuvm, <list_name>, &my_local_list, vm_bo) {
738  *              ret = do_something_with_vm_bo(..., vm_bo);
739  *              if (ret)
740  *                      break;
741  *      }
742  *      // Drop ref in case we break out of the loop.
743  *      drm_gpuvm_bo_put(vm_bo);
744  *      restore_vm_bo_list(gpuvm, <list_name>, &my_local_list);
745  *
746  *
747  * Only used for internal list iterations, not meant to be exposed to the outside
748  * world.
749  */
750 #define for_each_vm_bo_in_list(__gpuvm, __list_name, __local_list, __vm_bo)     \
751         for (__vm_bo = get_next_vm_bo_from_list(__gpuvm, __list_name,           \
752                                                 __local_list, NULL);            \
753              __vm_bo;                                                           \
754              __vm_bo = get_next_vm_bo_from_list(__gpuvm, __list_name,           \
755                                                 __local_list, __vm_bo))
756
757 static void
758 __restore_vm_bo_list(struct drm_gpuvm *gpuvm, spinlock_t *lock,
759                      struct list_head *list, struct list_head **local_list)
760 {
761         /* Merge back the two lists, moving local list elements to the
762          * head to preserve previous ordering, in case it matters.
763          */
764         spin_lock(lock);
765         if (*local_list) {
766                 list_splice(*local_list, list);
767                 *local_list = NULL;
768         }
769         spin_unlock(lock);
770 }
771
772 /**
773  * restore_vm_bo_list() - move vm_bo elements back to their original list
774  * @__gpuvm: the &drm_gpuvm
775  * @__list_name: the name of the list we're iterating on
776  *
777  * When we're done iterating a vm_bo list, we should call restore_vm_bo_list()
778  * to restore the original state and let new iterations take place.
779  */
780 #define restore_vm_bo_list(__gpuvm, __list_name)                        \
781         __restore_vm_bo_list((__gpuvm), &(__gpuvm)->__list_name.lock,   \
782                              &(__gpuvm)->__list_name.list,              \
783                              &(__gpuvm)->__list_name.local_list)
784
785 static void
786 cond_spin_lock(spinlock_t *lock, bool cond)
787 {
788         if (cond)
789                 spin_lock(lock);
790 }
791
792 static void
793 cond_spin_unlock(spinlock_t *lock, bool cond)
794 {
795         if (cond)
796                 spin_unlock(lock);
797 }
798
799 static void
800 __drm_gpuvm_bo_list_add(struct drm_gpuvm *gpuvm, spinlock_t *lock,
801                         struct list_head *entry, struct list_head *list)
802 {
803         cond_spin_lock(lock, !!lock);
804         if (list_empty(entry))
805                 list_add_tail(entry, list);
806         cond_spin_unlock(lock, !!lock);
807 }
808
809 /**
810  * drm_gpuvm_bo_list_add() - insert a vm_bo into the given list
811  * @__vm_bo: the &drm_gpuvm_bo
812  * @__list_name: the name of the list to insert into
813  * @__lock: whether to lock with the internal spinlock
814  *
815  * Inserts the given @__vm_bo into the list specified by @__list_name.
816  */
817 #define drm_gpuvm_bo_list_add(__vm_bo, __list_name, __lock)                     \
818         __drm_gpuvm_bo_list_add((__vm_bo)->vm,                                  \
819                                 __lock ? &(__vm_bo)->vm->__list_name.lock :     \
820                                          NULL,                                  \
821                                 &(__vm_bo)->list.entry.__list_name,             \
822                                 &(__vm_bo)->vm->__list_name.list)
823
824 static void
825 __drm_gpuvm_bo_list_del(struct drm_gpuvm *gpuvm, spinlock_t *lock,
826                         struct list_head *entry, bool init)
827 {
828         cond_spin_lock(lock, !!lock);
829         if (init) {
830                 if (!list_empty(entry))
831                         list_del_init(entry);
832         } else {
833                 list_del(entry);
834         }
835         cond_spin_unlock(lock, !!lock);
836 }
837
838 /**
839  * drm_gpuvm_bo_list_del_init() - remove a vm_bo from the given list
840  * @__vm_bo: the &drm_gpuvm_bo
841  * @__list_name: the name of the list to insert into
842  * @__lock: whether to lock with the internal spinlock
843  *
844  * Removes the given @__vm_bo from the list specified by @__list_name.
845  */
846 #define drm_gpuvm_bo_list_del_init(__vm_bo, __list_name, __lock)                \
847         __drm_gpuvm_bo_list_del((__vm_bo)->vm,                                  \
848                                 __lock ? &(__vm_bo)->vm->__list_name.lock :     \
849                                          NULL,                                  \
850                                 &(__vm_bo)->list.entry.__list_name,             \
851                                 true)
852
853 /**
854  * drm_gpuvm_bo_list_del() - remove a vm_bo from the given list
855  * @__vm_bo: the &drm_gpuvm_bo
856  * @__list_name: the name of the list to insert into
857  * @__lock: whether to lock with the internal spinlock
858  *
859  * Removes the given @__vm_bo from the list specified by @__list_name.
860  */
861 #define drm_gpuvm_bo_list_del(__vm_bo, __list_name, __lock)                     \
862         __drm_gpuvm_bo_list_del((__vm_bo)->vm,                                  \
863                                 __lock ? &(__vm_bo)->vm->__list_name.lock :     \
864                                          NULL,                                  \
865                                 &(__vm_bo)->list.entry.__list_name,             \
866                                 false)
867
868 #define to_drm_gpuva(__node)    container_of((__node), struct drm_gpuva, rb.node)
869
870 #define GPUVA_START(node) ((node)->va.addr)
871 #define GPUVA_LAST(node) ((node)->va.addr + (node)->va.range - 1)
872
873 /* We do not actually use drm_gpuva_it_next(), tell the compiler to not complain
874  * about this.
875  */
876 INTERVAL_TREE_DEFINE(struct drm_gpuva, rb.node, u64, rb.__subtree_last,
877                      GPUVA_START, GPUVA_LAST, static __maybe_unused,
878                      drm_gpuva_it)
879
880 static int __drm_gpuva_insert(struct drm_gpuvm *gpuvm,
881                               struct drm_gpuva *va);
882 static void __drm_gpuva_remove(struct drm_gpuva *va);
883
884 static bool
885 drm_gpuvm_check_overflow(u64 addr, u64 range)
886 {
887         u64 end;
888
889         return check_add_overflow(addr, range, &end);
890 }
891
892 static bool
893 drm_gpuvm_warn_check_overflow(struct drm_gpuvm *gpuvm, u64 addr, u64 range)
894 {
895         return drm_WARN(gpuvm->drm, drm_gpuvm_check_overflow(addr, range),
896                         "GPUVA address limited to %zu bytes.\n", sizeof(addr));
897 }
898
899 static bool
900 drm_gpuvm_in_mm_range(struct drm_gpuvm *gpuvm, u64 addr, u64 range)
901 {
902         u64 end = addr + range;
903         u64 mm_start = gpuvm->mm_start;
904         u64 mm_end = mm_start + gpuvm->mm_range;
905
906         return addr >= mm_start && end <= mm_end;
907 }
908
909 static bool
910 drm_gpuvm_in_kernel_node(struct drm_gpuvm *gpuvm, u64 addr, u64 range)
911 {
912         u64 end = addr + range;
913         u64 kstart = gpuvm->kernel_alloc_node.va.addr;
914         u64 krange = gpuvm->kernel_alloc_node.va.range;
915         u64 kend = kstart + krange;
916
917         return krange && addr < kend && kstart < end;
918 }
919
920 /**
921  * drm_gpuvm_range_valid() - checks whether the given range is valid for the
922  * given &drm_gpuvm
923  * @gpuvm: the GPUVM to check the range for
924  * @addr: the base address
925  * @range: the range starting from the base address
926  *
927  * Checks whether the range is within the GPUVM's managed boundaries.
928  *
929  * Returns: true for a valid range, false otherwise
930  */
931 bool
932 drm_gpuvm_range_valid(struct drm_gpuvm *gpuvm,
933                       u64 addr, u64 range)
934 {
935         return !drm_gpuvm_check_overflow(addr, range) &&
936                drm_gpuvm_in_mm_range(gpuvm, addr, range) &&
937                !drm_gpuvm_in_kernel_node(gpuvm, addr, range);
938 }
939 EXPORT_SYMBOL_GPL(drm_gpuvm_range_valid);
940
941 static void
942 drm_gpuvm_gem_object_free(struct drm_gem_object *obj)
943 {
944         drm_gem_object_release(obj);
945         kfree(obj);
946 }
947
948 static const struct drm_gem_object_funcs drm_gpuvm_object_funcs = {
949         .free = drm_gpuvm_gem_object_free,
950 };
951
952 /**
953  * drm_gpuvm_resv_object_alloc() - allocate a dummy &drm_gem_object
954  * @drm: the drivers &drm_device
955  *
956  * Allocates a dummy &drm_gem_object which can be passed to drm_gpuvm_init() in
957  * order to serve as root GEM object providing the &drm_resv shared across
958  * &drm_gem_objects local to a single GPUVM.
959  *
960  * Returns: the &drm_gem_object on success, NULL on failure
961  */
962 struct drm_gem_object *
963 drm_gpuvm_resv_object_alloc(struct drm_device *drm)
964 {
965         struct drm_gem_object *obj;
966
967         obj = kzalloc(sizeof(*obj), GFP_KERNEL);
968         if (!obj)
969                 return NULL;
970
971         obj->funcs = &drm_gpuvm_object_funcs;
972         drm_gem_private_object_init(drm, obj, 0);
973
974         return obj;
975 }
976 EXPORT_SYMBOL_GPL(drm_gpuvm_resv_object_alloc);
977
978 /**
979  * drm_gpuvm_init() - initialize a &drm_gpuvm
980  * @gpuvm: pointer to the &drm_gpuvm to initialize
981  * @name: the name of the GPU VA space
982  * @flags: the &drm_gpuvm_flags for this GPUVM
983  * @drm: the &drm_device this VM resides in
984  * @r_obj: the resv &drm_gem_object providing the GPUVM's common &dma_resv
985  * @start_offset: the start offset of the GPU VA space
986  * @range: the size of the GPU VA space
987  * @reserve_offset: the start of the kernel reserved GPU VA area
988  * @reserve_range: the size of the kernel reserved GPU VA area
989  * @ops: &drm_gpuvm_ops called on &drm_gpuvm_sm_map / &drm_gpuvm_sm_unmap
990  *
991  * The &drm_gpuvm must be initialized with this function before use.
992  *
993  * Note that @gpuvm must be cleared to 0 before calling this function. The given
994  * &name is expected to be managed by the surrounding driver structures.
995  */
996 void
997 drm_gpuvm_init(struct drm_gpuvm *gpuvm, const char *name,
998                enum drm_gpuvm_flags flags,
999                struct drm_device *drm,
1000                struct drm_gem_object *r_obj,
1001                u64 start_offset, u64 range,
1002                u64 reserve_offset, u64 reserve_range,
1003                const struct drm_gpuvm_ops *ops)
1004 {
1005         gpuvm->rb.tree = RB_ROOT_CACHED;
1006         INIT_LIST_HEAD(&gpuvm->rb.list);
1007
1008         INIT_LIST_HEAD(&gpuvm->extobj.list);
1009         spin_lock_init(&gpuvm->extobj.lock);
1010
1011         INIT_LIST_HEAD(&gpuvm->evict.list);
1012         spin_lock_init(&gpuvm->evict.lock);
1013
1014         kref_init(&gpuvm->kref);
1015
1016         gpuvm->name = name ? name : "unknown";
1017         gpuvm->flags = flags;
1018         gpuvm->ops = ops;
1019         gpuvm->drm = drm;
1020         gpuvm->r_obj = r_obj;
1021
1022         drm_gem_object_get(r_obj);
1023
1024         drm_gpuvm_warn_check_overflow(gpuvm, start_offset, range);
1025         gpuvm->mm_start = start_offset;
1026         gpuvm->mm_range = range;
1027
1028         memset(&gpuvm->kernel_alloc_node, 0, sizeof(struct drm_gpuva));
1029         if (reserve_range) {
1030                 gpuvm->kernel_alloc_node.va.addr = reserve_offset;
1031                 gpuvm->kernel_alloc_node.va.range = reserve_range;
1032
1033                 if (likely(!drm_gpuvm_warn_check_overflow(gpuvm, reserve_offset,
1034                                                           reserve_range)))
1035                         __drm_gpuva_insert(gpuvm, &gpuvm->kernel_alloc_node);
1036         }
1037 }
1038 EXPORT_SYMBOL_GPL(drm_gpuvm_init);
1039
1040 static void
1041 drm_gpuvm_fini(struct drm_gpuvm *gpuvm)
1042 {
1043         gpuvm->name = NULL;
1044
1045         if (gpuvm->kernel_alloc_node.va.range)
1046                 __drm_gpuva_remove(&gpuvm->kernel_alloc_node);
1047
1048         drm_WARN(gpuvm->drm, !RB_EMPTY_ROOT(&gpuvm->rb.tree.rb_root),
1049                  "GPUVA tree is not empty, potentially leaking memory.\n");
1050
1051         drm_WARN(gpuvm->drm, !list_empty(&gpuvm->extobj.list),
1052                  "Extobj list should be empty.\n");
1053         drm_WARN(gpuvm->drm, !list_empty(&gpuvm->evict.list),
1054                  "Evict list should be empty.\n");
1055
1056         drm_gem_object_put(gpuvm->r_obj);
1057 }
1058
1059 static void
1060 drm_gpuvm_free(struct kref *kref)
1061 {
1062         struct drm_gpuvm *gpuvm = container_of(kref, struct drm_gpuvm, kref);
1063
1064         drm_gpuvm_fini(gpuvm);
1065
1066         if (drm_WARN_ON(gpuvm->drm, !gpuvm->ops->vm_free))
1067                 return;
1068
1069         gpuvm->ops->vm_free(gpuvm);
1070 }
1071
1072 /**
1073  * drm_gpuvm_put() - drop a struct drm_gpuvm reference
1074  * @gpuvm: the &drm_gpuvm to release the reference of
1075  *
1076  * This releases a reference to @gpuvm.
1077  *
1078  * This function may be called from atomic context.
1079  */
1080 void
1081 drm_gpuvm_put(struct drm_gpuvm *gpuvm)
1082 {
1083         if (gpuvm)
1084                 kref_put(&gpuvm->kref, drm_gpuvm_free);
1085 }
1086 EXPORT_SYMBOL_GPL(drm_gpuvm_put);
1087
1088 static int
1089 __drm_gpuvm_prepare_objects(struct drm_gpuvm *gpuvm,
1090                             struct drm_exec *exec,
1091                             unsigned int num_fences)
1092 {
1093         struct drm_gpuvm_bo *vm_bo;
1094         LIST_HEAD(extobjs);
1095         int ret = 0;
1096
1097         for_each_vm_bo_in_list(gpuvm, extobj, &extobjs, vm_bo) {
1098                 ret = drm_exec_prepare_obj(exec, vm_bo->obj, num_fences);
1099                 if (ret)
1100                         break;
1101         }
1102         /* Drop ref in case we break out of the loop. */
1103         drm_gpuvm_bo_put(vm_bo);
1104         restore_vm_bo_list(gpuvm, extobj);
1105
1106         return ret;
1107 }
1108
1109 static int
1110 drm_gpuvm_prepare_objects_locked(struct drm_gpuvm *gpuvm,
1111                                  struct drm_exec *exec,
1112                                  unsigned int num_fences)
1113 {
1114         struct drm_gpuvm_bo *vm_bo;
1115         int ret = 0;
1116
1117         drm_gpuvm_resv_assert_held(gpuvm);
1118         list_for_each_entry(vm_bo, &gpuvm->extobj.list, list.entry.extobj) {
1119                 ret = drm_exec_prepare_obj(exec, vm_bo->obj, num_fences);
1120                 if (ret)
1121                         break;
1122
1123                 if (vm_bo->evicted)
1124                         drm_gpuvm_bo_list_add(vm_bo, evict, false);
1125         }
1126
1127         return ret;
1128 }
1129
1130 /**
1131  * drm_gpuvm_prepare_objects() - prepare all assoiciated BOs
1132  * @gpuvm: the &drm_gpuvm
1133  * @exec: the &drm_exec locking context
1134  * @num_fences: the amount of &dma_fences to reserve
1135  *
1136  * Calls drm_exec_prepare_obj() for all &drm_gem_objects the given
1137  * &drm_gpuvm contains mappings of.
1138  *
1139  * Using this function directly, it is the drivers responsibility to call
1140  * drm_exec_init() and drm_exec_fini() accordingly.
1141  *
1142  * Note: This function is safe against concurrent insertion and removal of
1143  * external objects, however it is not safe against concurrent usage itself.
1144  *
1145  * Drivers need to make sure to protect this case with either an outer VM lock
1146  * or by calling drm_gpuvm_prepare_vm() before this function within the
1147  * drm_exec_until_all_locked() loop, such that the GPUVM's dma-resv lock ensures
1148  * mutual exclusion.
1149  *
1150  * Returns: 0 on success, negative error code on failure.
1151  */
1152 int
1153 drm_gpuvm_prepare_objects(struct drm_gpuvm *gpuvm,
1154                           struct drm_exec *exec,
1155                           unsigned int num_fences)
1156 {
1157         if (drm_gpuvm_resv_protected(gpuvm))
1158                 return drm_gpuvm_prepare_objects_locked(gpuvm, exec,
1159                                                         num_fences);
1160         else
1161                 return __drm_gpuvm_prepare_objects(gpuvm, exec, num_fences);
1162 }
1163 EXPORT_SYMBOL_GPL(drm_gpuvm_prepare_objects);
1164
1165 /**
1166  * drm_gpuvm_prepare_range() - prepare all BOs mapped within a given range
1167  * @gpuvm: the &drm_gpuvm
1168  * @exec: the &drm_exec locking context
1169  * @addr: the start address within the VA space
1170  * @range: the range to iterate within the VA space
1171  * @num_fences: the amount of &dma_fences to reserve
1172  *
1173  * Calls drm_exec_prepare_obj() for all &drm_gem_objects mapped between @addr
1174  * and @addr + @range.
1175  *
1176  * Returns: 0 on success, negative error code on failure.
1177  */
1178 int
1179 drm_gpuvm_prepare_range(struct drm_gpuvm *gpuvm, struct drm_exec *exec,
1180                         u64 addr, u64 range, unsigned int num_fences)
1181 {
1182         struct drm_gpuva *va;
1183         u64 end = addr + range;
1184         int ret;
1185
1186         drm_gpuvm_for_each_va_range(va, gpuvm, addr, end) {
1187                 struct drm_gem_object *obj = va->gem.obj;
1188
1189                 ret = drm_exec_prepare_obj(exec, obj, num_fences);
1190                 if (ret)
1191                         return ret;
1192         }
1193
1194         return 0;
1195 }
1196 EXPORT_SYMBOL_GPL(drm_gpuvm_prepare_range);
1197
1198 /**
1199  * drm_gpuvm_exec_lock() - lock all dma-resv of all assoiciated BOs
1200  * @vm_exec: the &drm_gpuvm_exec wrapper
1201  *
1202  * Acquires all dma-resv locks of all &drm_gem_objects the given
1203  * &drm_gpuvm contains mappings of.
1204  *
1205  * Addionally, when calling this function with struct drm_gpuvm_exec::extra
1206  * being set the driver receives the given @fn callback to lock additional
1207  * dma-resv in the context of the &drm_gpuvm_exec instance. Typically, drivers
1208  * would call drm_exec_prepare_obj() from within this callback.
1209  *
1210  * Returns: 0 on success, negative error code on failure.
1211  */
1212 int
1213 drm_gpuvm_exec_lock(struct drm_gpuvm_exec *vm_exec)
1214 {
1215         struct drm_gpuvm *gpuvm = vm_exec->vm;
1216         struct drm_exec *exec = &vm_exec->exec;
1217         unsigned int num_fences = vm_exec->num_fences;
1218         int ret;
1219
1220         drm_exec_init(exec, vm_exec->flags);
1221
1222         drm_exec_until_all_locked(exec) {
1223                 ret = drm_gpuvm_prepare_vm(gpuvm, exec, num_fences);
1224                 drm_exec_retry_on_contention(exec);
1225                 if (ret)
1226                         goto err;
1227
1228                 ret = drm_gpuvm_prepare_objects(gpuvm, exec, num_fences);
1229                 drm_exec_retry_on_contention(exec);
1230                 if (ret)
1231                         goto err;
1232
1233                 if (vm_exec->extra.fn) {
1234                         ret = vm_exec->extra.fn(vm_exec);
1235                         drm_exec_retry_on_contention(exec);
1236                         if (ret)
1237                                 goto err;
1238                 }
1239         }
1240
1241         return 0;
1242
1243 err:
1244         drm_exec_fini(exec);
1245         return ret;
1246 }
1247 EXPORT_SYMBOL_GPL(drm_gpuvm_exec_lock);
1248
1249 static int
1250 fn_lock_array(struct drm_gpuvm_exec *vm_exec)
1251 {
1252         struct {
1253                 struct drm_gem_object **objs;
1254                 unsigned int num_objs;
1255         } *args = vm_exec->extra.priv;
1256
1257         return drm_exec_prepare_array(&vm_exec->exec, args->objs,
1258                                       args->num_objs, vm_exec->num_fences);
1259 }
1260
1261 /**
1262  * drm_gpuvm_exec_lock_array() - lock all dma-resv of all assoiciated BOs
1263  * @vm_exec: the &drm_gpuvm_exec wrapper
1264  * @objs: additional &drm_gem_objects to lock
1265  * @num_objs: the number of additional &drm_gem_objects to lock
1266  *
1267  * Acquires all dma-resv locks of all &drm_gem_objects the given &drm_gpuvm
1268  * contains mappings of, plus the ones given through @objs.
1269  *
1270  * Returns: 0 on success, negative error code on failure.
1271  */
1272 int
1273 drm_gpuvm_exec_lock_array(struct drm_gpuvm_exec *vm_exec,
1274                           struct drm_gem_object **objs,
1275                           unsigned int num_objs)
1276 {
1277         struct {
1278                 struct drm_gem_object **objs;
1279                 unsigned int num_objs;
1280         } args;
1281
1282         args.objs = objs;
1283         args.num_objs = num_objs;
1284
1285         vm_exec->extra.fn = fn_lock_array;
1286         vm_exec->extra.priv = &args;
1287
1288         return drm_gpuvm_exec_lock(vm_exec);
1289 }
1290 EXPORT_SYMBOL_GPL(drm_gpuvm_exec_lock_array);
1291
1292 /**
1293  * drm_gpuvm_exec_lock_range() - prepare all BOs mapped within a given range
1294  * @vm_exec: the &drm_gpuvm_exec wrapper
1295  * @addr: the start address within the VA space
1296  * @range: the range to iterate within the VA space
1297  *
1298  * Acquires all dma-resv locks of all &drm_gem_objects mapped between @addr and
1299  * @addr + @range.
1300  *
1301  * Returns: 0 on success, negative error code on failure.
1302  */
1303 int
1304 drm_gpuvm_exec_lock_range(struct drm_gpuvm_exec *vm_exec,
1305                           u64 addr, u64 range)
1306 {
1307         struct drm_gpuvm *gpuvm = vm_exec->vm;
1308         struct drm_exec *exec = &vm_exec->exec;
1309         int ret;
1310
1311         drm_exec_init(exec, vm_exec->flags);
1312
1313         drm_exec_until_all_locked(exec) {
1314                 ret = drm_gpuvm_prepare_range(gpuvm, exec, addr, range,
1315                                               vm_exec->num_fences);
1316                 drm_exec_retry_on_contention(exec);
1317                 if (ret)
1318                         goto err;
1319         }
1320
1321         return ret;
1322
1323 err:
1324         drm_exec_fini(exec);
1325         return ret;
1326 }
1327 EXPORT_SYMBOL_GPL(drm_gpuvm_exec_lock_range);
1328
1329 static int
1330 __drm_gpuvm_validate(struct drm_gpuvm *gpuvm, struct drm_exec *exec)
1331 {
1332         const struct drm_gpuvm_ops *ops = gpuvm->ops;
1333         struct drm_gpuvm_bo *vm_bo;
1334         LIST_HEAD(evict);
1335         int ret = 0;
1336
1337         for_each_vm_bo_in_list(gpuvm, evict, &evict, vm_bo) {
1338                 ret = ops->vm_bo_validate(vm_bo, exec);
1339                 if (ret)
1340                         break;
1341         }
1342         /* Drop ref in case we break out of the loop. */
1343         drm_gpuvm_bo_put(vm_bo);
1344         restore_vm_bo_list(gpuvm, evict);
1345
1346         return ret;
1347 }
1348
1349 static int
1350 drm_gpuvm_validate_locked(struct drm_gpuvm *gpuvm, struct drm_exec *exec)
1351 {
1352         const struct drm_gpuvm_ops *ops = gpuvm->ops;
1353         struct drm_gpuvm_bo *vm_bo, *next;
1354         int ret = 0;
1355
1356         drm_gpuvm_resv_assert_held(gpuvm);
1357
1358         list_for_each_entry_safe(vm_bo, next, &gpuvm->evict.list,
1359                                  list.entry.evict) {
1360                 ret = ops->vm_bo_validate(vm_bo, exec);
1361                 if (ret)
1362                         break;
1363
1364                 dma_resv_assert_held(vm_bo->obj->resv);
1365                 if (!vm_bo->evicted)
1366                         drm_gpuvm_bo_list_del_init(vm_bo, evict, false);
1367         }
1368
1369         return ret;
1370 }
1371
1372 /**
1373  * drm_gpuvm_validate() - validate all BOs marked as evicted
1374  * @gpuvm: the &drm_gpuvm to validate evicted BOs
1375  * @exec: the &drm_exec instance used for locking the GPUVM
1376  *
1377  * Calls the &drm_gpuvm_ops::vm_bo_validate callback for all evicted buffer
1378  * objects being mapped in the given &drm_gpuvm.
1379  *
1380  * Returns: 0 on success, negative error code on failure.
1381  */
1382 int
1383 drm_gpuvm_validate(struct drm_gpuvm *gpuvm, struct drm_exec *exec)
1384 {
1385         const struct drm_gpuvm_ops *ops = gpuvm->ops;
1386
1387         if (unlikely(!ops || !ops->vm_bo_validate))
1388                 return -EOPNOTSUPP;
1389
1390         if (drm_gpuvm_resv_protected(gpuvm))
1391                 return drm_gpuvm_validate_locked(gpuvm, exec);
1392         else
1393                 return __drm_gpuvm_validate(gpuvm, exec);
1394 }
1395 EXPORT_SYMBOL_GPL(drm_gpuvm_validate);
1396
1397 /**
1398  * drm_gpuvm_resv_add_fence - add fence to private and all extobj
1399  * dma-resv
1400  * @gpuvm: the &drm_gpuvm to add a fence to
1401  * @exec: the &drm_exec locking context
1402  * @fence: fence to add
1403  * @private_usage: private dma-resv usage
1404  * @extobj_usage: extobj dma-resv usage
1405  */
1406 void
1407 drm_gpuvm_resv_add_fence(struct drm_gpuvm *gpuvm,
1408                          struct drm_exec *exec,
1409                          struct dma_fence *fence,
1410                          enum dma_resv_usage private_usage,
1411                          enum dma_resv_usage extobj_usage)
1412 {
1413         struct drm_gem_object *obj;
1414         unsigned long index;
1415
1416         drm_exec_for_each_locked_object(exec, index, obj) {
1417                 dma_resv_assert_held(obj->resv);
1418                 dma_resv_add_fence(obj->resv, fence,
1419                                    drm_gpuvm_is_extobj(gpuvm, obj) ?
1420                                    extobj_usage : private_usage);
1421         }
1422 }
1423 EXPORT_SYMBOL_GPL(drm_gpuvm_resv_add_fence);
1424
1425 /**
1426  * drm_gpuvm_bo_create() - create a new instance of struct drm_gpuvm_bo
1427  * @gpuvm: The &drm_gpuvm the @obj is mapped in.
1428  * @obj: The &drm_gem_object being mapped in the @gpuvm.
1429  *
1430  * If provided by the driver, this function uses the &drm_gpuvm_ops
1431  * vm_bo_alloc() callback to allocate.
1432  *
1433  * Returns: a pointer to the &drm_gpuvm_bo on success, NULL on failure
1434  */
1435 struct drm_gpuvm_bo *
1436 drm_gpuvm_bo_create(struct drm_gpuvm *gpuvm,
1437                     struct drm_gem_object *obj)
1438 {
1439         const struct drm_gpuvm_ops *ops = gpuvm->ops;
1440         struct drm_gpuvm_bo *vm_bo;
1441
1442         if (ops && ops->vm_bo_alloc)
1443                 vm_bo = ops->vm_bo_alloc();
1444         else
1445                 vm_bo = kzalloc(sizeof(*vm_bo), GFP_KERNEL);
1446
1447         if (unlikely(!vm_bo))
1448                 return NULL;
1449
1450         vm_bo->vm = drm_gpuvm_get(gpuvm);
1451         vm_bo->obj = obj;
1452         drm_gem_object_get(obj);
1453
1454         kref_init(&vm_bo->kref);
1455         INIT_LIST_HEAD(&vm_bo->list.gpuva);
1456         INIT_LIST_HEAD(&vm_bo->list.entry.gem);
1457
1458         INIT_LIST_HEAD(&vm_bo->list.entry.extobj);
1459         INIT_LIST_HEAD(&vm_bo->list.entry.evict);
1460
1461         return vm_bo;
1462 }
1463 EXPORT_SYMBOL_GPL(drm_gpuvm_bo_create);
1464
1465 static void
1466 drm_gpuvm_bo_destroy(struct kref *kref)
1467 {
1468         struct drm_gpuvm_bo *vm_bo = container_of(kref, struct drm_gpuvm_bo,
1469                                                   kref);
1470         struct drm_gpuvm *gpuvm = vm_bo->vm;
1471         const struct drm_gpuvm_ops *ops = gpuvm->ops;
1472         struct drm_gem_object *obj = vm_bo->obj;
1473         bool lock = !drm_gpuvm_resv_protected(gpuvm);
1474
1475         if (!lock)
1476                 drm_gpuvm_resv_assert_held(gpuvm);
1477
1478         drm_gpuvm_bo_list_del(vm_bo, extobj, lock);
1479         drm_gpuvm_bo_list_del(vm_bo, evict, lock);
1480
1481         drm_gem_gpuva_assert_lock_held(obj);
1482         list_del(&vm_bo->list.entry.gem);
1483
1484         if (ops && ops->vm_bo_free)
1485                 ops->vm_bo_free(vm_bo);
1486         else
1487                 kfree(vm_bo);
1488
1489         drm_gpuvm_put(gpuvm);
1490         drm_gem_object_put(obj);
1491 }
1492
1493 /**
1494  * drm_gpuvm_bo_put() - drop a struct drm_gpuvm_bo reference
1495  * @vm_bo: the &drm_gpuvm_bo to release the reference of
1496  *
1497  * This releases a reference to @vm_bo.
1498  *
1499  * If the reference count drops to zero, the &gpuvm_bo is destroyed, which
1500  * includes removing it from the GEMs gpuva list. Hence, if a call to this
1501  * function can potentially let the reference count drop to zero the caller must
1502  * hold the dma-resv or driver specific GEM gpuva lock.
1503  *
1504  * This function may only be called from non-atomic context.
1505  */
1506 void
1507 drm_gpuvm_bo_put(struct drm_gpuvm_bo *vm_bo)
1508 {
1509         might_sleep();
1510
1511         if (vm_bo)
1512                 kref_put(&vm_bo->kref, drm_gpuvm_bo_destroy);
1513 }
1514 EXPORT_SYMBOL_GPL(drm_gpuvm_bo_put);
1515
1516 static struct drm_gpuvm_bo *
1517 __drm_gpuvm_bo_find(struct drm_gpuvm *gpuvm,
1518                     struct drm_gem_object *obj)
1519 {
1520         struct drm_gpuvm_bo *vm_bo;
1521
1522         drm_gem_gpuva_assert_lock_held(obj);
1523         drm_gem_for_each_gpuvm_bo(vm_bo, obj)
1524                 if (vm_bo->vm == gpuvm)
1525                         return vm_bo;
1526
1527         return NULL;
1528 }
1529
1530 /**
1531  * drm_gpuvm_bo_find() - find the &drm_gpuvm_bo for the given
1532  * &drm_gpuvm and &drm_gem_object
1533  * @gpuvm: The &drm_gpuvm the @obj is mapped in.
1534  * @obj: The &drm_gem_object being mapped in the @gpuvm.
1535  *
1536  * Find the &drm_gpuvm_bo representing the combination of the given
1537  * &drm_gpuvm and &drm_gem_object. If found, increases the reference
1538  * count of the &drm_gpuvm_bo accordingly.
1539  *
1540  * Returns: a pointer to the &drm_gpuvm_bo on success, NULL on failure
1541  */
1542 struct drm_gpuvm_bo *
1543 drm_gpuvm_bo_find(struct drm_gpuvm *gpuvm,
1544                   struct drm_gem_object *obj)
1545 {
1546         struct drm_gpuvm_bo *vm_bo = __drm_gpuvm_bo_find(gpuvm, obj);
1547
1548         return vm_bo ? drm_gpuvm_bo_get(vm_bo) : NULL;
1549 }
1550 EXPORT_SYMBOL_GPL(drm_gpuvm_bo_find);
1551
1552 /**
1553  * drm_gpuvm_bo_obtain() - obtains and instance of the &drm_gpuvm_bo for the
1554  * given &drm_gpuvm and &drm_gem_object
1555  * @gpuvm: The &drm_gpuvm the @obj is mapped in.
1556  * @obj: The &drm_gem_object being mapped in the @gpuvm.
1557  *
1558  * Find the &drm_gpuvm_bo representing the combination of the given
1559  * &drm_gpuvm and &drm_gem_object. If found, increases the reference
1560  * count of the &drm_gpuvm_bo accordingly. If not found, allocates a new
1561  * &drm_gpuvm_bo.
1562  *
1563  * A new &drm_gpuvm_bo is added to the GEMs gpuva list.
1564  *
1565  * Returns: a pointer to the &drm_gpuvm_bo on success, an ERR_PTR on failure
1566  */
1567 struct drm_gpuvm_bo *
1568 drm_gpuvm_bo_obtain(struct drm_gpuvm *gpuvm,
1569                     struct drm_gem_object *obj)
1570 {
1571         struct drm_gpuvm_bo *vm_bo;
1572
1573         vm_bo = drm_gpuvm_bo_find(gpuvm, obj);
1574         if (vm_bo)
1575                 return vm_bo;
1576
1577         vm_bo = drm_gpuvm_bo_create(gpuvm, obj);
1578         if (!vm_bo)
1579                 return ERR_PTR(-ENOMEM);
1580
1581         drm_gem_gpuva_assert_lock_held(obj);
1582         list_add_tail(&vm_bo->list.entry.gem, &obj->gpuva.list);
1583
1584         return vm_bo;
1585 }
1586 EXPORT_SYMBOL_GPL(drm_gpuvm_bo_obtain);
1587
1588 /**
1589  * drm_gpuvm_bo_obtain_prealloc() - obtains and instance of the &drm_gpuvm_bo
1590  * for the given &drm_gpuvm and &drm_gem_object
1591  * @__vm_bo: A pre-allocated struct drm_gpuvm_bo.
1592  *
1593  * Find the &drm_gpuvm_bo representing the combination of the given
1594  * &drm_gpuvm and &drm_gem_object. If found, increases the reference
1595  * count of the found &drm_gpuvm_bo accordingly, while the @__vm_bo reference
1596  * count is decreased. If not found @__vm_bo is returned without further
1597  * increase of the reference count.
1598  *
1599  * A new &drm_gpuvm_bo is added to the GEMs gpuva list.
1600  *
1601  * Returns: a pointer to the found &drm_gpuvm_bo or @__vm_bo if no existing
1602  * &drm_gpuvm_bo was found
1603  */
1604 struct drm_gpuvm_bo *
1605 drm_gpuvm_bo_obtain_prealloc(struct drm_gpuvm_bo *__vm_bo)
1606 {
1607         struct drm_gpuvm *gpuvm = __vm_bo->vm;
1608         struct drm_gem_object *obj = __vm_bo->obj;
1609         struct drm_gpuvm_bo *vm_bo;
1610
1611         vm_bo = drm_gpuvm_bo_find(gpuvm, obj);
1612         if (vm_bo) {
1613                 drm_gpuvm_bo_put(__vm_bo);
1614                 return vm_bo;
1615         }
1616
1617         drm_gem_gpuva_assert_lock_held(obj);
1618         list_add_tail(&__vm_bo->list.entry.gem, &obj->gpuva.list);
1619
1620         return __vm_bo;
1621 }
1622 EXPORT_SYMBOL_GPL(drm_gpuvm_bo_obtain_prealloc);
1623
1624 /**
1625  * drm_gpuvm_bo_extobj_add() - adds the &drm_gpuvm_bo to its &drm_gpuvm's
1626  * extobj list
1627  * @vm_bo: The &drm_gpuvm_bo to add to its &drm_gpuvm's the extobj list.
1628  *
1629  * Adds the given @vm_bo to its &drm_gpuvm's extobj list if not on the list
1630  * already and if the corresponding &drm_gem_object is an external object,
1631  * actually.
1632  */
1633 void
1634 drm_gpuvm_bo_extobj_add(struct drm_gpuvm_bo *vm_bo)
1635 {
1636         struct drm_gpuvm *gpuvm = vm_bo->vm;
1637         bool lock = !drm_gpuvm_resv_protected(gpuvm);
1638
1639         if (!lock)
1640                 drm_gpuvm_resv_assert_held(gpuvm);
1641
1642         if (drm_gpuvm_is_extobj(gpuvm, vm_bo->obj))
1643                 drm_gpuvm_bo_list_add(vm_bo, extobj, lock);
1644 }
1645 EXPORT_SYMBOL_GPL(drm_gpuvm_bo_extobj_add);
1646
1647 /**
1648  * drm_gpuvm_bo_evict() - add / remove a &drm_gpuvm_bo to / from the &drm_gpuvms
1649  * evicted list
1650  * @vm_bo: the &drm_gpuvm_bo to add or remove
1651  * @evict: indicates whether the object is evicted
1652  *
1653  * Adds a &drm_gpuvm_bo to or removes it from the &drm_gpuvms evicted list.
1654  */
1655 void
1656 drm_gpuvm_bo_evict(struct drm_gpuvm_bo *vm_bo, bool evict)
1657 {
1658         struct drm_gpuvm *gpuvm = vm_bo->vm;
1659         struct drm_gem_object *obj = vm_bo->obj;
1660         bool lock = !drm_gpuvm_resv_protected(gpuvm);
1661
1662         dma_resv_assert_held(obj->resv);
1663         vm_bo->evicted = evict;
1664
1665         /* Can't add external objects to the evicted list directly if not using
1666          * internal spinlocks, since in this case the evicted list is protected
1667          * with the VM's common dma-resv lock.
1668          */
1669         if (drm_gpuvm_is_extobj(gpuvm, obj) && !lock)
1670                 return;
1671
1672         if (evict)
1673                 drm_gpuvm_bo_list_add(vm_bo, evict, lock);
1674         else
1675                 drm_gpuvm_bo_list_del_init(vm_bo, evict, lock);
1676 }
1677 EXPORT_SYMBOL_GPL(drm_gpuvm_bo_evict);
1678
1679 static int
1680 __drm_gpuva_insert(struct drm_gpuvm *gpuvm,
1681                    struct drm_gpuva *va)
1682 {
1683         struct rb_node *node;
1684         struct list_head *head;
1685
1686         if (drm_gpuva_it_iter_first(&gpuvm->rb.tree,
1687                                     GPUVA_START(va),
1688                                     GPUVA_LAST(va)))
1689                 return -EEXIST;
1690
1691         va->vm = gpuvm;
1692
1693         drm_gpuva_it_insert(va, &gpuvm->rb.tree);
1694
1695         node = rb_prev(&va->rb.node);
1696         if (node)
1697                 head = &(to_drm_gpuva(node))->rb.entry;
1698         else
1699                 head = &gpuvm->rb.list;
1700
1701         list_add(&va->rb.entry, head);
1702
1703         return 0;
1704 }
1705
1706 /**
1707  * drm_gpuva_insert() - insert a &drm_gpuva
1708  * @gpuvm: the &drm_gpuvm to insert the &drm_gpuva in
1709  * @va: the &drm_gpuva to insert
1710  *
1711  * Insert a &drm_gpuva with a given address and range into a
1712  * &drm_gpuvm.
1713  *
1714  * It is safe to use this function using the safe versions of iterating the GPU
1715  * VA space, such as drm_gpuvm_for_each_va_safe() and
1716  * drm_gpuvm_for_each_va_range_safe().
1717  *
1718  * Returns: 0 on success, negative error code on failure.
1719  */
1720 int
1721 drm_gpuva_insert(struct drm_gpuvm *gpuvm,
1722                  struct drm_gpuva *va)
1723 {
1724         u64 addr = va->va.addr;
1725         u64 range = va->va.range;
1726         int ret;
1727
1728         if (unlikely(!drm_gpuvm_range_valid(gpuvm, addr, range)))
1729                 return -EINVAL;
1730
1731         ret = __drm_gpuva_insert(gpuvm, va);
1732         if (likely(!ret))
1733                 /* Take a reference of the GPUVM for the successfully inserted
1734                  * drm_gpuva. We can't take the reference in
1735                  * __drm_gpuva_insert() itself, since we don't want to increse
1736                  * the reference count for the GPUVM's kernel_alloc_node.
1737                  */
1738                 drm_gpuvm_get(gpuvm);
1739
1740         return ret;
1741 }
1742 EXPORT_SYMBOL_GPL(drm_gpuva_insert);
1743
1744 static void
1745 __drm_gpuva_remove(struct drm_gpuva *va)
1746 {
1747         drm_gpuva_it_remove(va, &va->vm->rb.tree);
1748         list_del_init(&va->rb.entry);
1749 }
1750
1751 /**
1752  * drm_gpuva_remove() - remove a &drm_gpuva
1753  * @va: the &drm_gpuva to remove
1754  *
1755  * This removes the given &va from the underlaying tree.
1756  *
1757  * It is safe to use this function using the safe versions of iterating the GPU
1758  * VA space, such as drm_gpuvm_for_each_va_safe() and
1759  * drm_gpuvm_for_each_va_range_safe().
1760  */
1761 void
1762 drm_gpuva_remove(struct drm_gpuva *va)
1763 {
1764         struct drm_gpuvm *gpuvm = va->vm;
1765
1766         if (unlikely(va == &gpuvm->kernel_alloc_node)) {
1767                 drm_WARN(gpuvm->drm, 1,
1768                          "Can't destroy kernel reserved node.\n");
1769                 return;
1770         }
1771
1772         __drm_gpuva_remove(va);
1773         drm_gpuvm_put(va->vm);
1774 }
1775 EXPORT_SYMBOL_GPL(drm_gpuva_remove);
1776
1777 /**
1778  * drm_gpuva_link() - link a &drm_gpuva
1779  * @va: the &drm_gpuva to link
1780  * @vm_bo: the &drm_gpuvm_bo to add the &drm_gpuva to
1781  *
1782  * This adds the given &va to the GPU VA list of the &drm_gpuvm_bo and the
1783  * &drm_gpuvm_bo to the &drm_gem_object it is associated with.
1784  *
1785  * For every &drm_gpuva entry added to the &drm_gpuvm_bo an additional
1786  * reference of the latter is taken.
1787  *
1788  * This function expects the caller to protect the GEM's GPUVA list against
1789  * concurrent access using either the GEMs dma_resv lock or a driver specific
1790  * lock set through drm_gem_gpuva_set_lock().
1791  */
1792 void
1793 drm_gpuva_link(struct drm_gpuva *va, struct drm_gpuvm_bo *vm_bo)
1794 {
1795         struct drm_gem_object *obj = va->gem.obj;
1796         struct drm_gpuvm *gpuvm = va->vm;
1797
1798         if (unlikely(!obj))
1799                 return;
1800
1801         drm_WARN_ON(gpuvm->drm, obj != vm_bo->obj);
1802
1803         va->vm_bo = drm_gpuvm_bo_get(vm_bo);
1804
1805         drm_gem_gpuva_assert_lock_held(obj);
1806         list_add_tail(&va->gem.entry, &vm_bo->list.gpuva);
1807 }
1808 EXPORT_SYMBOL_GPL(drm_gpuva_link);
1809
1810 /**
1811  * drm_gpuva_unlink() - unlink a &drm_gpuva
1812  * @va: the &drm_gpuva to unlink
1813  *
1814  * This removes the given &va from the GPU VA list of the &drm_gem_object it is
1815  * associated with.
1816  *
1817  * This removes the given &va from the GPU VA list of the &drm_gpuvm_bo and
1818  * the &drm_gpuvm_bo from the &drm_gem_object it is associated with in case
1819  * this call unlinks the last &drm_gpuva from the &drm_gpuvm_bo.
1820  *
1821  * For every &drm_gpuva entry removed from the &drm_gpuvm_bo a reference of
1822  * the latter is dropped.
1823  *
1824  * This function expects the caller to protect the GEM's GPUVA list against
1825  * concurrent access using either the GEMs dma_resv lock or a driver specific
1826  * lock set through drm_gem_gpuva_set_lock().
1827  */
1828 void
1829 drm_gpuva_unlink(struct drm_gpuva *va)
1830 {
1831         struct drm_gem_object *obj = va->gem.obj;
1832         struct drm_gpuvm_bo *vm_bo = va->vm_bo;
1833
1834         if (unlikely(!obj))
1835                 return;
1836
1837         drm_gem_gpuva_assert_lock_held(obj);
1838         list_del_init(&va->gem.entry);
1839
1840         va->vm_bo = NULL;
1841         drm_gpuvm_bo_put(vm_bo);
1842 }
1843 EXPORT_SYMBOL_GPL(drm_gpuva_unlink);
1844
1845 /**
1846  * drm_gpuva_find_first() - find the first &drm_gpuva in the given range
1847  * @gpuvm: the &drm_gpuvm to search in
1848  * @addr: the &drm_gpuvas address
1849  * @range: the &drm_gpuvas range
1850  *
1851  * Returns: the first &drm_gpuva within the given range
1852  */
1853 struct drm_gpuva *
1854 drm_gpuva_find_first(struct drm_gpuvm *gpuvm,
1855                      u64 addr, u64 range)
1856 {
1857         u64 last = addr + range - 1;
1858
1859         return drm_gpuva_it_iter_first(&gpuvm->rb.tree, addr, last);
1860 }
1861 EXPORT_SYMBOL_GPL(drm_gpuva_find_first);
1862
1863 /**
1864  * drm_gpuva_find() - find a &drm_gpuva
1865  * @gpuvm: the &drm_gpuvm to search in
1866  * @addr: the &drm_gpuvas address
1867  * @range: the &drm_gpuvas range
1868  *
1869  * Returns: the &drm_gpuva at a given &addr and with a given &range
1870  */
1871 struct drm_gpuva *
1872 drm_gpuva_find(struct drm_gpuvm *gpuvm,
1873                u64 addr, u64 range)
1874 {
1875         struct drm_gpuva *va;
1876
1877         va = drm_gpuva_find_first(gpuvm, addr, range);
1878         if (!va)
1879                 goto out;
1880
1881         if (va->va.addr != addr ||
1882             va->va.range != range)
1883                 goto out;
1884
1885         return va;
1886
1887 out:
1888         return NULL;
1889 }
1890 EXPORT_SYMBOL_GPL(drm_gpuva_find);
1891
1892 /**
1893  * drm_gpuva_find_prev() - find the &drm_gpuva before the given address
1894  * @gpuvm: the &drm_gpuvm to search in
1895  * @start: the given GPU VA's start address
1896  *
1897  * Find the adjacent &drm_gpuva before the GPU VA with given &start address.
1898  *
1899  * Note that if there is any free space between the GPU VA mappings no mapping
1900  * is returned.
1901  *
1902  * Returns: a pointer to the found &drm_gpuva or NULL if none was found
1903  */
1904 struct drm_gpuva *
1905 drm_gpuva_find_prev(struct drm_gpuvm *gpuvm, u64 start)
1906 {
1907         if (!drm_gpuvm_range_valid(gpuvm, start - 1, 1))
1908                 return NULL;
1909
1910         return drm_gpuva_it_iter_first(&gpuvm->rb.tree, start - 1, start);
1911 }
1912 EXPORT_SYMBOL_GPL(drm_gpuva_find_prev);
1913
1914 /**
1915  * drm_gpuva_find_next() - find the &drm_gpuva after the given address
1916  * @gpuvm: the &drm_gpuvm to search in
1917  * @end: the given GPU VA's end address
1918  *
1919  * Find the adjacent &drm_gpuva after the GPU VA with given &end address.
1920  *
1921  * Note that if there is any free space between the GPU VA mappings no mapping
1922  * is returned.
1923  *
1924  * Returns: a pointer to the found &drm_gpuva or NULL if none was found
1925  */
1926 struct drm_gpuva *
1927 drm_gpuva_find_next(struct drm_gpuvm *gpuvm, u64 end)
1928 {
1929         if (!drm_gpuvm_range_valid(gpuvm, end, 1))
1930                 return NULL;
1931
1932         return drm_gpuva_it_iter_first(&gpuvm->rb.tree, end, end + 1);
1933 }
1934 EXPORT_SYMBOL_GPL(drm_gpuva_find_next);
1935
1936 /**
1937  * drm_gpuvm_interval_empty() - indicate whether a given interval of the VA space
1938  * is empty
1939  * @gpuvm: the &drm_gpuvm to check the range for
1940  * @addr: the start address of the range
1941  * @range: the range of the interval
1942  *
1943  * Returns: true if the interval is empty, false otherwise
1944  */
1945 bool
1946 drm_gpuvm_interval_empty(struct drm_gpuvm *gpuvm, u64 addr, u64 range)
1947 {
1948         return !drm_gpuva_find_first(gpuvm, addr, range);
1949 }
1950 EXPORT_SYMBOL_GPL(drm_gpuvm_interval_empty);
1951
1952 /**
1953  * drm_gpuva_map() - helper to insert a &drm_gpuva according to a
1954  * &drm_gpuva_op_map
1955  * @gpuvm: the &drm_gpuvm
1956  * @va: the &drm_gpuva to insert
1957  * @op: the &drm_gpuva_op_map to initialize @va with
1958  *
1959  * Initializes the @va from the @op and inserts it into the given @gpuvm.
1960  */
1961 void
1962 drm_gpuva_map(struct drm_gpuvm *gpuvm,
1963               struct drm_gpuva *va,
1964               struct drm_gpuva_op_map *op)
1965 {
1966         drm_gpuva_init_from_op(va, op);
1967         drm_gpuva_insert(gpuvm, va);
1968 }
1969 EXPORT_SYMBOL_GPL(drm_gpuva_map);
1970
1971 /**
1972  * drm_gpuva_remap() - helper to remap a &drm_gpuva according to a
1973  * &drm_gpuva_op_remap
1974  * @prev: the &drm_gpuva to remap when keeping the start of a mapping
1975  * @next: the &drm_gpuva to remap when keeping the end of a mapping
1976  * @op: the &drm_gpuva_op_remap to initialize @prev and @next with
1977  *
1978  * Removes the currently mapped &drm_gpuva and remaps it using @prev and/or
1979  * @next.
1980  */
1981 void
1982 drm_gpuva_remap(struct drm_gpuva *prev,
1983                 struct drm_gpuva *next,
1984                 struct drm_gpuva_op_remap *op)
1985 {
1986         struct drm_gpuva *va = op->unmap->va;
1987         struct drm_gpuvm *gpuvm = va->vm;
1988
1989         drm_gpuva_remove(va);
1990
1991         if (op->prev) {
1992                 drm_gpuva_init_from_op(prev, op->prev);
1993                 drm_gpuva_insert(gpuvm, prev);
1994         }
1995
1996         if (op->next) {
1997                 drm_gpuva_init_from_op(next, op->next);
1998                 drm_gpuva_insert(gpuvm, next);
1999         }
2000 }
2001 EXPORT_SYMBOL_GPL(drm_gpuva_remap);
2002
2003 /**
2004  * drm_gpuva_unmap() - helper to remove a &drm_gpuva according to a
2005  * &drm_gpuva_op_unmap
2006  * @op: the &drm_gpuva_op_unmap specifying the &drm_gpuva to remove
2007  *
2008  * Removes the &drm_gpuva associated with the &drm_gpuva_op_unmap.
2009  */
2010 void
2011 drm_gpuva_unmap(struct drm_gpuva_op_unmap *op)
2012 {
2013         drm_gpuva_remove(op->va);
2014 }
2015 EXPORT_SYMBOL_GPL(drm_gpuva_unmap);
2016
2017 static int
2018 op_map_cb(const struct drm_gpuvm_ops *fn, void *priv,
2019           u64 addr, u64 range,
2020           struct drm_gem_object *obj, u64 offset)
2021 {
2022         struct drm_gpuva_op op = {};
2023
2024         op.op = DRM_GPUVA_OP_MAP;
2025         op.map.va.addr = addr;
2026         op.map.va.range = range;
2027         op.map.gem.obj = obj;
2028         op.map.gem.offset = offset;
2029
2030         return fn->sm_step_map(&op, priv);
2031 }
2032
2033 static int
2034 op_remap_cb(const struct drm_gpuvm_ops *fn, void *priv,
2035             struct drm_gpuva_op_map *prev,
2036             struct drm_gpuva_op_map *next,
2037             struct drm_gpuva_op_unmap *unmap)
2038 {
2039         struct drm_gpuva_op op = {};
2040         struct drm_gpuva_op_remap *r;
2041
2042         op.op = DRM_GPUVA_OP_REMAP;
2043         r = &op.remap;
2044         r->prev = prev;
2045         r->next = next;
2046         r->unmap = unmap;
2047
2048         return fn->sm_step_remap(&op, priv);
2049 }
2050
2051 static int
2052 op_unmap_cb(const struct drm_gpuvm_ops *fn, void *priv,
2053             struct drm_gpuva *va, bool merge)
2054 {
2055         struct drm_gpuva_op op = {};
2056
2057         op.op = DRM_GPUVA_OP_UNMAP;
2058         op.unmap.va = va;
2059         op.unmap.keep = merge;
2060
2061         return fn->sm_step_unmap(&op, priv);
2062 }
2063
2064 static int
2065 __drm_gpuvm_sm_map(struct drm_gpuvm *gpuvm,
2066                    const struct drm_gpuvm_ops *ops, void *priv,
2067                    u64 req_addr, u64 req_range,
2068                    struct drm_gem_object *req_obj, u64 req_offset)
2069 {
2070         struct drm_gpuva *va, *next;
2071         u64 req_end = req_addr + req_range;
2072         int ret;
2073
2074         if (unlikely(!drm_gpuvm_range_valid(gpuvm, req_addr, req_range)))
2075                 return -EINVAL;
2076
2077         drm_gpuvm_for_each_va_range_safe(va, next, gpuvm, req_addr, req_end) {
2078                 struct drm_gem_object *obj = va->gem.obj;
2079                 u64 offset = va->gem.offset;
2080                 u64 addr = va->va.addr;
2081                 u64 range = va->va.range;
2082                 u64 end = addr + range;
2083                 bool merge = !!va->gem.obj;
2084
2085                 if (addr == req_addr) {
2086                         merge &= obj == req_obj &&
2087                                  offset == req_offset;
2088
2089                         if (end == req_end) {
2090                                 ret = op_unmap_cb(ops, priv, va, merge);
2091                                 if (ret)
2092                                         return ret;
2093                                 break;
2094                         }
2095
2096                         if (end < req_end) {
2097                                 ret = op_unmap_cb(ops, priv, va, merge);
2098                                 if (ret)
2099                                         return ret;
2100                                 continue;
2101                         }
2102
2103                         if (end > req_end) {
2104                                 struct drm_gpuva_op_map n = {
2105                                         .va.addr = req_end,
2106                                         .va.range = range - req_range,
2107                                         .gem.obj = obj,
2108                                         .gem.offset = offset + req_range,
2109                                 };
2110                                 struct drm_gpuva_op_unmap u = {
2111                                         .va = va,
2112                                         .keep = merge,
2113                                 };
2114
2115                                 ret = op_remap_cb(ops, priv, NULL, &n, &u);
2116                                 if (ret)
2117                                         return ret;
2118                                 break;
2119                         }
2120                 } else if (addr < req_addr) {
2121                         u64 ls_range = req_addr - addr;
2122                         struct drm_gpuva_op_map p = {
2123                                 .va.addr = addr,
2124                                 .va.range = ls_range,
2125                                 .gem.obj = obj,
2126                                 .gem.offset = offset,
2127                         };
2128                         struct drm_gpuva_op_unmap u = { .va = va };
2129
2130                         merge &= obj == req_obj &&
2131                                  offset + ls_range == req_offset;
2132                         u.keep = merge;
2133
2134                         if (end == req_end) {
2135                                 ret = op_remap_cb(ops, priv, &p, NULL, &u);
2136                                 if (ret)
2137                                         return ret;
2138                                 break;
2139                         }
2140
2141                         if (end < req_end) {
2142                                 ret = op_remap_cb(ops, priv, &p, NULL, &u);
2143                                 if (ret)
2144                                         return ret;
2145                                 continue;
2146                         }
2147
2148                         if (end > req_end) {
2149                                 struct drm_gpuva_op_map n = {
2150                                         .va.addr = req_end,
2151                                         .va.range = end - req_end,
2152                                         .gem.obj = obj,
2153                                         .gem.offset = offset + ls_range +
2154                                                       req_range,
2155                                 };
2156
2157                                 ret = op_remap_cb(ops, priv, &p, &n, &u);
2158                                 if (ret)
2159                                         return ret;
2160                                 break;
2161                         }
2162                 } else if (addr > req_addr) {
2163                         merge &= obj == req_obj &&
2164                                  offset == req_offset +
2165                                            (addr - req_addr);
2166
2167                         if (end == req_end) {
2168                                 ret = op_unmap_cb(ops, priv, va, merge);
2169                                 if (ret)
2170                                         return ret;
2171                                 break;
2172                         }
2173
2174                         if (end < req_end) {
2175                                 ret = op_unmap_cb(ops, priv, va, merge);
2176                                 if (ret)
2177                                         return ret;
2178                                 continue;
2179                         }
2180
2181                         if (end > req_end) {
2182                                 struct drm_gpuva_op_map n = {
2183                                         .va.addr = req_end,
2184                                         .va.range = end - req_end,
2185                                         .gem.obj = obj,
2186                                         .gem.offset = offset + req_end - addr,
2187                                 };
2188                                 struct drm_gpuva_op_unmap u = {
2189                                         .va = va,
2190                                         .keep = merge,
2191                                 };
2192
2193                                 ret = op_remap_cb(ops, priv, NULL, &n, &u);
2194                                 if (ret)
2195                                         return ret;
2196                                 break;
2197                         }
2198                 }
2199         }
2200
2201         return op_map_cb(ops, priv,
2202                          req_addr, req_range,
2203                          req_obj, req_offset);
2204 }
2205
2206 static int
2207 __drm_gpuvm_sm_unmap(struct drm_gpuvm *gpuvm,
2208                      const struct drm_gpuvm_ops *ops, void *priv,
2209                      u64 req_addr, u64 req_range)
2210 {
2211         struct drm_gpuva *va, *next;
2212         u64 req_end = req_addr + req_range;
2213         int ret;
2214
2215         if (unlikely(!drm_gpuvm_range_valid(gpuvm, req_addr, req_range)))
2216                 return -EINVAL;
2217
2218         drm_gpuvm_for_each_va_range_safe(va, next, gpuvm, req_addr, req_end) {
2219                 struct drm_gpuva_op_map prev = {}, next = {};
2220                 bool prev_split = false, next_split = false;
2221                 struct drm_gem_object *obj = va->gem.obj;
2222                 u64 offset = va->gem.offset;
2223                 u64 addr = va->va.addr;
2224                 u64 range = va->va.range;
2225                 u64 end = addr + range;
2226
2227                 if (addr < req_addr) {
2228                         prev.va.addr = addr;
2229                         prev.va.range = req_addr - addr;
2230                         prev.gem.obj = obj;
2231                         prev.gem.offset = offset;
2232
2233                         prev_split = true;
2234                 }
2235
2236                 if (end > req_end) {
2237                         next.va.addr = req_end;
2238                         next.va.range = end - req_end;
2239                         next.gem.obj = obj;
2240                         next.gem.offset = offset + (req_end - addr);
2241
2242                         next_split = true;
2243                 }
2244
2245                 if (prev_split || next_split) {
2246                         struct drm_gpuva_op_unmap unmap = { .va = va };
2247
2248                         ret = op_remap_cb(ops, priv,
2249                                           prev_split ? &prev : NULL,
2250                                           next_split ? &next : NULL,
2251                                           &unmap);
2252                         if (ret)
2253                                 return ret;
2254                 } else {
2255                         ret = op_unmap_cb(ops, priv, va, false);
2256                         if (ret)
2257                                 return ret;
2258                 }
2259         }
2260
2261         return 0;
2262 }
2263
2264 /**
2265  * drm_gpuvm_sm_map() - creates the &drm_gpuva_op split/merge steps
2266  * @gpuvm: the &drm_gpuvm representing the GPU VA space
2267  * @req_addr: the start address of the new mapping
2268  * @req_range: the range of the new mapping
2269  * @req_obj: the &drm_gem_object to map
2270  * @req_offset: the offset within the &drm_gem_object
2271  * @priv: pointer to a driver private data structure
2272  *
2273  * This function iterates the given range of the GPU VA space. It utilizes the
2274  * &drm_gpuvm_ops to call back into the driver providing the split and merge
2275  * steps.
2276  *
2277  * Drivers may use these callbacks to update the GPU VA space right away within
2278  * the callback. In case the driver decides to copy and store the operations for
2279  * later processing neither this function nor &drm_gpuvm_sm_unmap is allowed to
2280  * be called before the &drm_gpuvm's view of the GPU VA space was
2281  * updated with the previous set of operations. To update the
2282  * &drm_gpuvm's view of the GPU VA space drm_gpuva_insert(),
2283  * drm_gpuva_destroy_locked() and/or drm_gpuva_destroy_unlocked() should be
2284  * used.
2285  *
2286  * A sequence of callbacks can contain map, unmap and remap operations, but
2287  * the sequence of callbacks might also be empty if no operation is required,
2288  * e.g. if the requested mapping already exists in the exact same way.
2289  *
2290  * There can be an arbitrary amount of unmap operations, a maximum of two remap
2291  * operations and a single map operation. The latter one represents the original
2292  * map operation requested by the caller.
2293  *
2294  * Returns: 0 on success or a negative error code
2295  */
2296 int
2297 drm_gpuvm_sm_map(struct drm_gpuvm *gpuvm, void *priv,
2298                  u64 req_addr, u64 req_range,
2299                  struct drm_gem_object *req_obj, u64 req_offset)
2300 {
2301         const struct drm_gpuvm_ops *ops = gpuvm->ops;
2302
2303         if (unlikely(!(ops && ops->sm_step_map &&
2304                        ops->sm_step_remap &&
2305                        ops->sm_step_unmap)))
2306                 return -EINVAL;
2307
2308         return __drm_gpuvm_sm_map(gpuvm, ops, priv,
2309                                   req_addr, req_range,
2310                                   req_obj, req_offset);
2311 }
2312 EXPORT_SYMBOL_GPL(drm_gpuvm_sm_map);
2313
2314 /**
2315  * drm_gpuvm_sm_unmap() - creates the &drm_gpuva_ops to split on unmap
2316  * @gpuvm: the &drm_gpuvm representing the GPU VA space
2317  * @priv: pointer to a driver private data structure
2318  * @req_addr: the start address of the range to unmap
2319  * @req_range: the range of the mappings to unmap
2320  *
2321  * This function iterates the given range of the GPU VA space. It utilizes the
2322  * &drm_gpuvm_ops to call back into the driver providing the operations to
2323  * unmap and, if required, split existent mappings.
2324  *
2325  * Drivers may use these callbacks to update the GPU VA space right away within
2326  * the callback. In case the driver decides to copy and store the operations for
2327  * later processing neither this function nor &drm_gpuvm_sm_map is allowed to be
2328  * called before the &drm_gpuvm's view of the GPU VA space was updated
2329  * with the previous set of operations. To update the &drm_gpuvm's view
2330  * of the GPU VA space drm_gpuva_insert(), drm_gpuva_destroy_locked() and/or
2331  * drm_gpuva_destroy_unlocked() should be used.
2332  *
2333  * A sequence of callbacks can contain unmap and remap operations, depending on
2334  * whether there are actual overlapping mappings to split.
2335  *
2336  * There can be an arbitrary amount of unmap operations and a maximum of two
2337  * remap operations.
2338  *
2339  * Returns: 0 on success or a negative error code
2340  */
2341 int
2342 drm_gpuvm_sm_unmap(struct drm_gpuvm *gpuvm, void *priv,
2343                    u64 req_addr, u64 req_range)
2344 {
2345         const struct drm_gpuvm_ops *ops = gpuvm->ops;
2346
2347         if (unlikely(!(ops && ops->sm_step_remap &&
2348                        ops->sm_step_unmap)))
2349                 return -EINVAL;
2350
2351         return __drm_gpuvm_sm_unmap(gpuvm, ops, priv,
2352                                     req_addr, req_range);
2353 }
2354 EXPORT_SYMBOL_GPL(drm_gpuvm_sm_unmap);
2355
2356 static struct drm_gpuva_op *
2357 gpuva_op_alloc(struct drm_gpuvm *gpuvm)
2358 {
2359         const struct drm_gpuvm_ops *fn = gpuvm->ops;
2360         struct drm_gpuva_op *op;
2361
2362         if (fn && fn->op_alloc)
2363                 op = fn->op_alloc();
2364         else
2365                 op = kzalloc(sizeof(*op), GFP_KERNEL);
2366
2367         if (unlikely(!op))
2368                 return NULL;
2369
2370         return op;
2371 }
2372
2373 static void
2374 gpuva_op_free(struct drm_gpuvm *gpuvm,
2375               struct drm_gpuva_op *op)
2376 {
2377         const struct drm_gpuvm_ops *fn = gpuvm->ops;
2378
2379         if (fn && fn->op_free)
2380                 fn->op_free(op);
2381         else
2382                 kfree(op);
2383 }
2384
2385 static int
2386 drm_gpuva_sm_step(struct drm_gpuva_op *__op,
2387                   void *priv)
2388 {
2389         struct {
2390                 struct drm_gpuvm *vm;
2391                 struct drm_gpuva_ops *ops;
2392         } *args = priv;
2393         struct drm_gpuvm *gpuvm = args->vm;
2394         struct drm_gpuva_ops *ops = args->ops;
2395         struct drm_gpuva_op *op;
2396
2397         op = gpuva_op_alloc(gpuvm);
2398         if (unlikely(!op))
2399                 goto err;
2400
2401         memcpy(op, __op, sizeof(*op));
2402
2403         if (op->op == DRM_GPUVA_OP_REMAP) {
2404                 struct drm_gpuva_op_remap *__r = &__op->remap;
2405                 struct drm_gpuva_op_remap *r = &op->remap;
2406
2407                 r->unmap = kmemdup(__r->unmap, sizeof(*r->unmap),
2408                                    GFP_KERNEL);
2409                 if (unlikely(!r->unmap))
2410                         goto err_free_op;
2411
2412                 if (__r->prev) {
2413                         r->prev = kmemdup(__r->prev, sizeof(*r->prev),
2414                                           GFP_KERNEL);
2415                         if (unlikely(!r->prev))
2416                                 goto err_free_unmap;
2417                 }
2418
2419                 if (__r->next) {
2420                         r->next = kmemdup(__r->next, sizeof(*r->next),
2421                                           GFP_KERNEL);
2422                         if (unlikely(!r->next))
2423                                 goto err_free_prev;
2424                 }
2425         }
2426
2427         list_add_tail(&op->entry, &ops->list);
2428
2429         return 0;
2430
2431 err_free_unmap:
2432         kfree(op->remap.unmap);
2433 err_free_prev:
2434         kfree(op->remap.prev);
2435 err_free_op:
2436         gpuva_op_free(gpuvm, op);
2437 err:
2438         return -ENOMEM;
2439 }
2440
2441 static const struct drm_gpuvm_ops gpuvm_list_ops = {
2442         .sm_step_map = drm_gpuva_sm_step,
2443         .sm_step_remap = drm_gpuva_sm_step,
2444         .sm_step_unmap = drm_gpuva_sm_step,
2445 };
2446
2447 /**
2448  * drm_gpuvm_sm_map_ops_create() - creates the &drm_gpuva_ops to split and merge
2449  * @gpuvm: the &drm_gpuvm representing the GPU VA space
2450  * @req_addr: the start address of the new mapping
2451  * @req_range: the range of the new mapping
2452  * @req_obj: the &drm_gem_object to map
2453  * @req_offset: the offset within the &drm_gem_object
2454  *
2455  * This function creates a list of operations to perform splitting and merging
2456  * of existent mapping(s) with the newly requested one.
2457  *
2458  * The list can be iterated with &drm_gpuva_for_each_op and must be processed
2459  * in the given order. It can contain map, unmap and remap operations, but it
2460  * also can be empty if no operation is required, e.g. if the requested mapping
2461  * already exists is the exact same way.
2462  *
2463  * There can be an arbitrary amount of unmap operations, a maximum of two remap
2464  * operations and a single map operation. The latter one represents the original
2465  * map operation requested by the caller.
2466  *
2467  * Note that before calling this function again with another mapping request it
2468  * is necessary to update the &drm_gpuvm's view of the GPU VA space. The
2469  * previously obtained operations must be either processed or abandoned. To
2470  * update the &drm_gpuvm's view of the GPU VA space drm_gpuva_insert(),
2471  * drm_gpuva_destroy_locked() and/or drm_gpuva_destroy_unlocked() should be
2472  * used.
2473  *
2474  * After the caller finished processing the returned &drm_gpuva_ops, they must
2475  * be freed with &drm_gpuva_ops_free.
2476  *
2477  * Returns: a pointer to the &drm_gpuva_ops on success, an ERR_PTR on failure
2478  */
2479 struct drm_gpuva_ops *
2480 drm_gpuvm_sm_map_ops_create(struct drm_gpuvm *gpuvm,
2481                             u64 req_addr, u64 req_range,
2482                             struct drm_gem_object *req_obj, u64 req_offset)
2483 {
2484         struct drm_gpuva_ops *ops;
2485         struct {
2486                 struct drm_gpuvm *vm;
2487                 struct drm_gpuva_ops *ops;
2488         } args;
2489         int ret;
2490
2491         ops = kzalloc(sizeof(*ops), GFP_KERNEL);
2492         if (unlikely(!ops))
2493                 return ERR_PTR(-ENOMEM);
2494
2495         INIT_LIST_HEAD(&ops->list);
2496
2497         args.vm = gpuvm;
2498         args.ops = ops;
2499
2500         ret = __drm_gpuvm_sm_map(gpuvm, &gpuvm_list_ops, &args,
2501                                  req_addr, req_range,
2502                                  req_obj, req_offset);
2503         if (ret)
2504                 goto err_free_ops;
2505
2506         return ops;
2507
2508 err_free_ops:
2509         drm_gpuva_ops_free(gpuvm, ops);
2510         return ERR_PTR(ret);
2511 }
2512 EXPORT_SYMBOL_GPL(drm_gpuvm_sm_map_ops_create);
2513
2514 /**
2515  * drm_gpuvm_sm_unmap_ops_create() - creates the &drm_gpuva_ops to split on
2516  * unmap
2517  * @gpuvm: the &drm_gpuvm representing the GPU VA space
2518  * @req_addr: the start address of the range to unmap
2519  * @req_range: the range of the mappings to unmap
2520  *
2521  * This function creates a list of operations to perform unmapping and, if
2522  * required, splitting of the mappings overlapping the unmap range.
2523  *
2524  * The list can be iterated with &drm_gpuva_for_each_op and must be processed
2525  * in the given order. It can contain unmap and remap operations, depending on
2526  * whether there are actual overlapping mappings to split.
2527  *
2528  * There can be an arbitrary amount of unmap operations and a maximum of two
2529  * remap operations.
2530  *
2531  * Note that before calling this function again with another range to unmap it
2532  * is necessary to update the &drm_gpuvm's view of the GPU VA space. The
2533  * previously obtained operations must be processed or abandoned. To update the
2534  * &drm_gpuvm's view of the GPU VA space drm_gpuva_insert(),
2535  * drm_gpuva_destroy_locked() and/or drm_gpuva_destroy_unlocked() should be
2536  * used.
2537  *
2538  * After the caller finished processing the returned &drm_gpuva_ops, they must
2539  * be freed with &drm_gpuva_ops_free.
2540  *
2541  * Returns: a pointer to the &drm_gpuva_ops on success, an ERR_PTR on failure
2542  */
2543 struct drm_gpuva_ops *
2544 drm_gpuvm_sm_unmap_ops_create(struct drm_gpuvm *gpuvm,
2545                               u64 req_addr, u64 req_range)
2546 {
2547         struct drm_gpuva_ops *ops;
2548         struct {
2549                 struct drm_gpuvm *vm;
2550                 struct drm_gpuva_ops *ops;
2551         } args;
2552         int ret;
2553
2554         ops = kzalloc(sizeof(*ops), GFP_KERNEL);
2555         if (unlikely(!ops))
2556                 return ERR_PTR(-ENOMEM);
2557
2558         INIT_LIST_HEAD(&ops->list);
2559
2560         args.vm = gpuvm;
2561         args.ops = ops;
2562
2563         ret = __drm_gpuvm_sm_unmap(gpuvm, &gpuvm_list_ops, &args,
2564                                    req_addr, req_range);
2565         if (ret)
2566                 goto err_free_ops;
2567
2568         return ops;
2569
2570 err_free_ops:
2571         drm_gpuva_ops_free(gpuvm, ops);
2572         return ERR_PTR(ret);
2573 }
2574 EXPORT_SYMBOL_GPL(drm_gpuvm_sm_unmap_ops_create);
2575
2576 /**
2577  * drm_gpuvm_prefetch_ops_create() - creates the &drm_gpuva_ops to prefetch
2578  * @gpuvm: the &drm_gpuvm representing the GPU VA space
2579  * @addr: the start address of the range to prefetch
2580  * @range: the range of the mappings to prefetch
2581  *
2582  * This function creates a list of operations to perform prefetching.
2583  *
2584  * The list can be iterated with &drm_gpuva_for_each_op and must be processed
2585  * in the given order. It can contain prefetch operations.
2586  *
2587  * There can be an arbitrary amount of prefetch operations.
2588  *
2589  * After the caller finished processing the returned &drm_gpuva_ops, they must
2590  * be freed with &drm_gpuva_ops_free.
2591  *
2592  * Returns: a pointer to the &drm_gpuva_ops on success, an ERR_PTR on failure
2593  */
2594 struct drm_gpuva_ops *
2595 drm_gpuvm_prefetch_ops_create(struct drm_gpuvm *gpuvm,
2596                               u64 addr, u64 range)
2597 {
2598         struct drm_gpuva_ops *ops;
2599         struct drm_gpuva_op *op;
2600         struct drm_gpuva *va;
2601         u64 end = addr + range;
2602         int ret;
2603
2604         ops = kzalloc(sizeof(*ops), GFP_KERNEL);
2605         if (!ops)
2606                 return ERR_PTR(-ENOMEM);
2607
2608         INIT_LIST_HEAD(&ops->list);
2609
2610         drm_gpuvm_for_each_va_range(va, gpuvm, addr, end) {
2611                 op = gpuva_op_alloc(gpuvm);
2612                 if (!op) {
2613                         ret = -ENOMEM;
2614                         goto err_free_ops;
2615                 }
2616
2617                 op->op = DRM_GPUVA_OP_PREFETCH;
2618                 op->prefetch.va = va;
2619                 list_add_tail(&op->entry, &ops->list);
2620         }
2621
2622         return ops;
2623
2624 err_free_ops:
2625         drm_gpuva_ops_free(gpuvm, ops);
2626         return ERR_PTR(ret);
2627 }
2628 EXPORT_SYMBOL_GPL(drm_gpuvm_prefetch_ops_create);
2629
2630 /**
2631  * drm_gpuvm_bo_unmap_ops_create() - creates the &drm_gpuva_ops to unmap a GEM
2632  * @vm_bo: the &drm_gpuvm_bo abstraction
2633  *
2634  * This function creates a list of operations to perform unmapping for every
2635  * GPUVA attached to a GEM.
2636  *
2637  * The list can be iterated with &drm_gpuva_for_each_op and consists out of an
2638  * arbitrary amount of unmap operations.
2639  *
2640  * After the caller finished processing the returned &drm_gpuva_ops, they must
2641  * be freed with &drm_gpuva_ops_free.
2642  *
2643  * It is the callers responsibility to protect the GEMs GPUVA list against
2644  * concurrent access using the GEMs dma_resv lock.
2645  *
2646  * Returns: a pointer to the &drm_gpuva_ops on success, an ERR_PTR on failure
2647  */
2648 struct drm_gpuva_ops *
2649 drm_gpuvm_bo_unmap_ops_create(struct drm_gpuvm_bo *vm_bo)
2650 {
2651         struct drm_gpuva_ops *ops;
2652         struct drm_gpuva_op *op;
2653         struct drm_gpuva *va;
2654         int ret;
2655
2656         drm_gem_gpuva_assert_lock_held(vm_bo->obj);
2657
2658         ops = kzalloc(sizeof(*ops), GFP_KERNEL);
2659         if (!ops)
2660                 return ERR_PTR(-ENOMEM);
2661
2662         INIT_LIST_HEAD(&ops->list);
2663
2664         drm_gpuvm_bo_for_each_va(va, vm_bo) {
2665                 op = gpuva_op_alloc(vm_bo->vm);
2666                 if (!op) {
2667                         ret = -ENOMEM;
2668                         goto err_free_ops;
2669                 }
2670
2671                 op->op = DRM_GPUVA_OP_UNMAP;
2672                 op->unmap.va = va;
2673                 list_add_tail(&op->entry, &ops->list);
2674         }
2675
2676         return ops;
2677
2678 err_free_ops:
2679         drm_gpuva_ops_free(vm_bo->vm, ops);
2680         return ERR_PTR(ret);
2681 }
2682 EXPORT_SYMBOL_GPL(drm_gpuvm_bo_unmap_ops_create);
2683
2684 /**
2685  * drm_gpuva_ops_free() - free the given &drm_gpuva_ops
2686  * @gpuvm: the &drm_gpuvm the ops were created for
2687  * @ops: the &drm_gpuva_ops to free
2688  *
2689  * Frees the given &drm_gpuva_ops structure including all the ops associated
2690  * with it.
2691  */
2692 void
2693 drm_gpuva_ops_free(struct drm_gpuvm *gpuvm,
2694                    struct drm_gpuva_ops *ops)
2695 {
2696         struct drm_gpuva_op *op, *next;
2697
2698         drm_gpuva_for_each_op_safe(op, next, ops) {
2699                 list_del(&op->entry);
2700
2701                 if (op->op == DRM_GPUVA_OP_REMAP) {
2702                         kfree(op->remap.prev);
2703                         kfree(op->remap.next);
2704                         kfree(op->remap.unmap);
2705                 }
2706
2707                 gpuva_op_free(gpuvm, op);
2708         }
2709
2710         kfree(ops);
2711 }
2712 EXPORT_SYMBOL_GPL(drm_gpuva_ops_free);
2713
2714 MODULE_DESCRIPTION("DRM GPUVM");
2715 MODULE_LICENSE("GPL");
This page took 0.190729 seconds and 4 git commands to generate.