aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
Diffstat (limited to 'amdgpu/amdgpu_vamgr.c')
-rw-r--r--amdgpu/amdgpu_vamgr.c180
1 files changed, 78 insertions, 102 deletions
diff --git a/amdgpu/amdgpu_vamgr.c b/amdgpu/amdgpu_vamgr.c
index 8a707cbc..1de9f952 100644
--- a/amdgpu/amdgpu_vamgr.c
+++ b/amdgpu/amdgpu_vamgr.c
@@ -21,10 +21,6 @@
21 * 21 *
22 */ 22 */
23 23
24#ifdef HAVE_CONFIG_H
25#include "config.h"
26#endif
27
28#include <stdlib.h> 24#include <stdlib.h>
29#include <string.h> 25#include <string.h>
30#include <errno.h> 26#include <errno.h>
@@ -34,25 +30,33 @@
34#include "util_math.h" 30#include "util_math.h"
35 31
36int amdgpu_va_range_query(amdgpu_device_handle dev, 32int amdgpu_va_range_query(amdgpu_device_handle dev,
37 enum amdgpu_gpu_va_range type, uint64_t *start, uint64_t *end) 33 enum amdgpu_gpu_va_range type,
34 uint64_t *start, uint64_t *end)
38{ 35{
39 if (type == amdgpu_gpu_va_range_general) { 36 if (type != amdgpu_gpu_va_range_general)
40 *start = dev->dev_info.virtual_address_offset; 37 return -EINVAL;
41 *end = dev->dev_info.virtual_address_max; 38
42 return 0; 39 *start = dev->dev_info.virtual_address_offset;
43 } 40 *end = dev->dev_info.virtual_address_max;
44 return -EINVAL; 41 return 0;
45} 42}
46 43
47drm_private void amdgpu_vamgr_init(struct amdgpu_bo_va_mgr *mgr, uint64_t start, 44drm_private void amdgpu_vamgr_init(struct amdgpu_bo_va_mgr *mgr, uint64_t start,
48 uint64_t max, uint64_t alignment) 45 uint64_t max, uint64_t alignment)
49{ 46{
50 mgr->va_offset = start; 47 struct amdgpu_bo_va_hole *n;
48
51 mgr->va_max = max; 49 mgr->va_max = max;
52 mgr->va_alignment = alignment; 50 mgr->va_alignment = alignment;
53 51
54 list_inithead(&mgr->va_holes); 52 list_inithead(&mgr->va_holes);
55 pthread_mutex_init(&mgr->bo_va_mutex, NULL); 53 pthread_mutex_init(&mgr->bo_va_mutex, NULL);
54 pthread_mutex_lock(&mgr->bo_va_mutex);
55 n = calloc(1, sizeof(struct amdgpu_bo_va_hole));
56 n->size = mgr->va_max - start;
57 n->offset = start;
58 list_add(&n->list, &mgr->va_holes);
59 pthread_mutex_unlock(&mgr->bo_va_mutex);
56} 60}
57 61
58drm_private void amdgpu_vamgr_deinit(struct amdgpu_bo_va_mgr *mgr) 62drm_private void amdgpu_vamgr_deinit(struct amdgpu_bo_va_mgr *mgr)
@@ -65,13 +69,14 @@ drm_private void amdgpu_vamgr_deinit(struct amdgpu_bo_va_mgr *mgr)
65 pthread_mutex_destroy(&mgr->bo_va_mutex); 69 pthread_mutex_destroy(&mgr->bo_va_mutex);
66} 70}
67 71
68drm_private uint64_t 72static drm_private uint64_t
69amdgpu_vamgr_find_va(struct amdgpu_bo_va_mgr *mgr, uint64_t size, 73amdgpu_vamgr_find_va(struct amdgpu_bo_va_mgr *mgr, uint64_t size,
70 uint64_t alignment, uint64_t base_required) 74 uint64_t alignment, uint64_t base_required)
71{ 75{
72 struct amdgpu_bo_va_hole *hole, *n; 76 struct amdgpu_bo_va_hole *hole, *n;
73 uint64_t offset = 0, waste = 0; 77 uint64_t offset = 0, waste = 0;
74 78
79
75 alignment = MAX2(alignment, mgr->va_alignment); 80 alignment = MAX2(alignment, mgr->va_alignment);
76 size = ALIGN(size, mgr->va_alignment); 81 size = ALIGN(size, mgr->va_alignment);
77 82
@@ -79,12 +84,10 @@ amdgpu_vamgr_find_va(struct amdgpu_bo_va_mgr *mgr, uint64_t size,
79 return AMDGPU_INVALID_VA_ADDRESS; 84 return AMDGPU_INVALID_VA_ADDRESS;
80 85
81 pthread_mutex_lock(&mgr->bo_va_mutex); 86 pthread_mutex_lock(&mgr->bo_va_mutex);
82 /* TODO: using more appropriate way to track the holes */ 87 LIST_FOR_EACH_ENTRY_SAFE_REV(hole, n, &mgr->va_holes, list) {
83 /* first look for a hole */
84 LIST_FOR_EACH_ENTRY_SAFE(hole, n, &mgr->va_holes, list) {
85 if (base_required) { 88 if (base_required) {
86 if(hole->offset > base_required || 89 if (hole->offset > base_required ||
87 (hole->offset + hole->size) < (base_required + size)) 90 (hole->offset + hole->size) < (base_required + size))
88 continue; 91 continue;
89 waste = base_required - hole->offset; 92 waste = base_required - hole->offset;
90 offset = base_required; 93 offset = base_required;
@@ -123,41 +126,14 @@ amdgpu_vamgr_find_va(struct amdgpu_bo_va_mgr *mgr, uint64_t size,
123 } 126 }
124 } 127 }
125 128
126 if (base_required) {
127 if (base_required < mgr->va_offset) {
128 pthread_mutex_unlock(&mgr->bo_va_mutex);
129 return AMDGPU_INVALID_VA_ADDRESS;
130 }
131 offset = mgr->va_offset;
132 waste = base_required - mgr->va_offset;
133 } else {
134 offset = mgr->va_offset;
135 waste = offset % alignment;
136 waste = waste ? alignment - waste : 0;
137 }
138
139 if (offset + waste + size > mgr->va_max) {
140 pthread_mutex_unlock(&mgr->bo_va_mutex);
141 return AMDGPU_INVALID_VA_ADDRESS;
142 }
143
144 if (waste) {
145 n = calloc(1, sizeof(struct amdgpu_bo_va_hole));
146 n->size = waste;
147 n->offset = offset;
148 list_add(&n->list, &mgr->va_holes);
149 }
150
151 offset += waste;
152 mgr->va_offset += size + waste;
153 pthread_mutex_unlock(&mgr->bo_va_mutex); 129 pthread_mutex_unlock(&mgr->bo_va_mutex);
154 return offset; 130 return AMDGPU_INVALID_VA_ADDRESS;
155} 131}
156 132
157drm_private void 133static drm_private void
158amdgpu_vamgr_free_va(struct amdgpu_bo_va_mgr *mgr, uint64_t va, uint64_t size) 134amdgpu_vamgr_free_va(struct amdgpu_bo_va_mgr *mgr, uint64_t va, uint64_t size)
159{ 135{
160 struct amdgpu_bo_va_hole *hole; 136 struct amdgpu_bo_va_hole *hole, *next;
161 137
162 if (va == AMDGPU_INVALID_VA_ADDRESS) 138 if (va == AMDGPU_INVALID_VA_ADDRESS)
163 return; 139 return;
@@ -165,61 +141,47 @@ amdgpu_vamgr_free_va(struct amdgpu_bo_va_mgr *mgr, uint64_t va, uint64_t size)
165 size = ALIGN(size, mgr->va_alignment); 141 size = ALIGN(size, mgr->va_alignment);
166 142
167 pthread_mutex_lock(&mgr->bo_va_mutex); 143 pthread_mutex_lock(&mgr->bo_va_mutex);
168 if ((va + size) == mgr->va_offset) { 144 hole = container_of(&mgr->va_holes, hole, list);
169 mgr->va_offset = va; 145 LIST_FOR_EACH_ENTRY(next, &mgr->va_holes, list) {
170 /* Delete uppermost hole if it reaches the new top */ 146 if (next->offset < va)
171 if (!LIST_IS_EMPTY(&mgr->va_holes)) { 147 break;
172 hole = container_of(mgr->va_holes.next, hole, list); 148 hole = next;
173 if ((hole->offset + hole->size) == va) { 149 }
174 mgr->va_offset = hole->offset; 150
151 if (&hole->list != &mgr->va_holes) {
152 /* Grow upper hole if it's adjacent */
153 if (hole->offset == (va + size)) {
154 hole->offset = va;
155 hole->size += size;
156 /* Merge lower hole if it's adjacent */
157 if (next != hole &&
158 &next->list != &mgr->va_holes &&
159 (next->offset + next->size) == va) {
160 next->size += hole->size;
175 list_del(&hole->list); 161 list_del(&hole->list);
176 free(hole); 162 free(hole);
177 } 163 }
178 }
179 } else {
180 struct amdgpu_bo_va_hole *next;
181
182 hole = container_of(&mgr->va_holes, hole, list);
183 LIST_FOR_EACH_ENTRY(next, &mgr->va_holes, list) {
184 if (next->offset < va)
185 break;
186 hole = next;
187 }
188
189 if (&hole->list != &mgr->va_holes) {
190 /* Grow upper hole if it's adjacent */
191 if (hole->offset == (va + size)) {
192 hole->offset = va;
193 hole->size += size;
194 /* Merge lower hole if it's adjacent */
195 if (next != hole
196 && &next->list != &mgr->va_holes
197 && (next->offset + next->size) == va) {
198 next->size += hole->size;
199 list_del(&hole->list);
200 free(hole);
201 }
202 goto out;
203 }
204 }
205
206 /* Grow lower hole if it's adjacent */
207 if (next != hole && &next->list != &mgr->va_holes &&
208 (next->offset + next->size) == va) {
209 next->size += size;
210 goto out; 164 goto out;
211 } 165 }
166 }
212 167
213 /* FIXME on allocation failure we just lose virtual address space 168 /* Grow lower hole if it's adjacent */
214 * maybe print a warning 169 if (next != hole && &next->list != &mgr->va_holes &&
215 */ 170 (next->offset + next->size) == va) {
216 next = calloc(1, sizeof(struct amdgpu_bo_va_hole)); 171 next->size += size;
217 if (next) { 172 goto out;
218 next->size = size; 173 }
219 next->offset = va; 174
220 list_add(&next->list, &hole->list); 175 /* FIXME on allocation failure we just lose virtual address space
221 } 176 * maybe print a warning
177 */
178 next = calloc(1, sizeof(struct amdgpu_bo_va_hole));
179 if (next) {
180 next->size = size;
181 next->offset = va;
182 list_add(&next->list, &hole->list);
222 } 183 }
184
223out: 185out:
224 pthread_mutex_unlock(&mgr->bo_va_mutex); 186 pthread_mutex_unlock(&mgr->bo_va_mutex);
225} 187}
@@ -235,10 +197,21 @@ int amdgpu_va_range_alloc(amdgpu_device_handle dev,
235{ 197{
236 struct amdgpu_bo_va_mgr *vamgr; 198 struct amdgpu_bo_va_mgr *vamgr;
237 199
238 if (flags & AMDGPU_VA_RANGE_32_BIT) 200 /* Clear the flag when the high VA manager is not initialized */
239 vamgr = dev->vamgr_32; 201 if (flags & AMDGPU_VA_RANGE_HIGH && !dev->vamgr_high_32.va_max)
240 else 202 flags &= ~AMDGPU_VA_RANGE_HIGH;
241 vamgr = dev->vamgr; 203
204 if (flags & AMDGPU_VA_RANGE_HIGH) {
205 if (flags & AMDGPU_VA_RANGE_32_BIT)
206 vamgr = &dev->vamgr_high_32;
207 else
208 vamgr = &dev->vamgr_high;
209 } else {
210 if (flags & AMDGPU_VA_RANGE_32_BIT)
211 vamgr = &dev->vamgr_32;
212 else
213 vamgr = &dev->vamgr;
214 }
242 215
243 va_base_alignment = MAX2(va_base_alignment, vamgr->va_alignment); 216 va_base_alignment = MAX2(va_base_alignment, vamgr->va_alignment);
244 size = ALIGN(size, vamgr->va_alignment); 217 size = ALIGN(size, vamgr->va_alignment);
@@ -249,7 +222,10 @@ int amdgpu_va_range_alloc(amdgpu_device_handle dev,
249 if (!(flags & AMDGPU_VA_RANGE_32_BIT) && 222 if (!(flags & AMDGPU_VA_RANGE_32_BIT) &&
250 (*va_base_allocated == AMDGPU_INVALID_VA_ADDRESS)) { 223 (*va_base_allocated == AMDGPU_INVALID_VA_ADDRESS)) {
251 /* fallback to 32bit address */ 224 /* fallback to 32bit address */
252 vamgr = dev->vamgr_32; 225 if (flags & AMDGPU_VA_RANGE_HIGH)
226 vamgr = &dev->vamgr_high_32;
227 else
228 vamgr = &dev->vamgr_32;
253 *va_base_allocated = amdgpu_vamgr_find_va(vamgr, size, 229 *va_base_allocated = amdgpu_vamgr_find_va(vamgr, size,
254 va_base_alignment, va_base_required); 230 va_base_alignment, va_base_required);
255 } 231 }