1 | /* |
2 | * Copyright 2011 Red Hat Inc. |
3 | * All Rights Reserved. |
4 | * |
5 | * Permission is hereby granted, free of charge, to any person obtaining a |
6 | * copy of this software and associated documentation files (the |
7 | * "Software"), to deal in the Software without restriction, including |
8 | * without limitation the rights to use, copy, modify, merge, publish, |
9 | * distribute, sub license, and/or sell copies of the Software, and to |
10 | * permit persons to whom the Software is furnished to do so, subject to |
11 | * the following conditions: |
12 | * |
13 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR |
14 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, |
15 | * FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. IN NO EVENT SHALL |
16 | * THE COPYRIGHT HOLDERS, AUTHORS AND/OR ITS SUPPLIERS BE LIABLE FOR ANY CLAIM, |
17 | * DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR |
18 | * OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE |
19 | * USE OR OTHER DEALINGS IN THE SOFTWARE. |
20 | * |
21 | * The above copyright notice and this permission notice (including the |
22 | * next paragraph) shall be included in all copies or substantial portions |
23 | * of the Software. |
24 | * |
25 | */ |
26 | /* |
27 | * Authors: |
28 | * Jerome Glisse <glisse@freedesktop.org> |
29 | */ |
30 | /* Algorithm: |
31 | * |
32 | * We store the last allocated bo in "hole", we always try to allocate |
33 | * after the last allocated bo. Principle is that in a linear GPU ring |
34 | * progression was is after last is the oldest bo we allocated and thus |
35 | * the first one that should no longer be in use by the GPU. |
36 | * |
37 | * If it's not the case we skip over the bo after last to the closest |
38 | * done bo if such one exist. If none exist and we are not asked to |
39 | * block we report failure to allocate. |
40 | * |
41 | * If we are asked to block we wait on all the oldest fence of all |
42 | * rings. We just wait for any of those fence to complete. |
43 | */ |
44 | |
45 | #include "amdgpu.h" |
46 | |
47 | int amdgpu_sa_bo_manager_init(struct amdgpu_device *adev, |
48 | struct amdgpu_sa_manager *sa_manager, |
49 | unsigned int size, u32 suballoc_align, u32 domain) |
50 | { |
51 | int r; |
52 | |
53 | r = amdgpu_bo_create_kernel(adev, size, AMDGPU_GPU_PAGE_SIZE, domain, |
54 | bo_ptr: &sa_manager->bo, gpu_addr: &sa_manager->gpu_addr, |
55 | cpu_addr: &sa_manager->cpu_ptr); |
56 | if (r) { |
57 | dev_err(adev->dev, "(%d) failed to allocate bo for manager\n" , r); |
58 | return r; |
59 | } |
60 | |
61 | memset(sa_manager->cpu_ptr, 0, size); |
62 | drm_suballoc_manager_init(sa_manager: &sa_manager->base, size, align: suballoc_align); |
63 | return r; |
64 | } |
65 | |
66 | void amdgpu_sa_bo_manager_fini(struct amdgpu_device *adev, |
67 | struct amdgpu_sa_manager *sa_manager) |
68 | { |
69 | if (sa_manager->bo == NULL) { |
70 | dev_err(adev->dev, "no bo for sa manager\n" ); |
71 | return; |
72 | } |
73 | |
74 | drm_suballoc_manager_fini(sa_manager: &sa_manager->base); |
75 | |
76 | amdgpu_bo_free_kernel(bo: &sa_manager->bo, gpu_addr: &sa_manager->gpu_addr, cpu_addr: &sa_manager->cpu_ptr); |
77 | } |
78 | |
79 | int amdgpu_sa_bo_new(struct amdgpu_sa_manager *sa_manager, |
80 | struct drm_suballoc **sa_bo, |
81 | unsigned int size) |
82 | { |
83 | struct drm_suballoc *sa = drm_suballoc_new(sa_manager: &sa_manager->base, size, |
84 | GFP_KERNEL, intr: false, align: 0); |
85 | |
86 | if (IS_ERR(ptr: sa)) { |
87 | *sa_bo = NULL; |
88 | |
89 | return PTR_ERR(ptr: sa); |
90 | } |
91 | |
92 | *sa_bo = sa; |
93 | return 0; |
94 | } |
95 | |
96 | void amdgpu_sa_bo_free(struct amdgpu_device *adev, struct drm_suballoc **sa_bo, |
97 | struct dma_fence *fence) |
98 | { |
99 | if (sa_bo == NULL || *sa_bo == NULL) { |
100 | return; |
101 | } |
102 | |
103 | drm_suballoc_free(sa: *sa_bo, fence); |
104 | *sa_bo = NULL; |
105 | } |
106 | |
107 | #if defined(CONFIG_DEBUG_FS) |
108 | |
109 | void amdgpu_sa_bo_dump_debug_info(struct amdgpu_sa_manager *sa_manager, |
110 | struct seq_file *m) |
111 | { |
112 | struct drm_printer p = drm_seq_file_printer(f: m); |
113 | |
114 | drm_suballoc_dump_debug_info(sa_manager: &sa_manager->base, p: &p, suballoc_base: sa_manager->gpu_addr); |
115 | } |
116 | #endif |
117 | |