diff options
Diffstat (limited to 'amdgpu/amdgpu_vamgr.c')
-rw-r--r-- | amdgpu/amdgpu_vamgr.c | 180 |
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 | ||
36 | int amdgpu_va_range_query(amdgpu_device_handle dev, | 32 | int 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 | ||
47 | drm_private void amdgpu_vamgr_init(struct amdgpu_bo_va_mgr *mgr, uint64_t start, | 44 | drm_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 | ||
58 | drm_private void amdgpu_vamgr_deinit(struct amdgpu_bo_va_mgr *mgr) | 62 | drm_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 | ||
68 | drm_private uint64_t | 72 | static drm_private uint64_t |
69 | amdgpu_vamgr_find_va(struct amdgpu_bo_va_mgr *mgr, uint64_t size, | 73 | amdgpu_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 | ||
157 | drm_private void | 133 | static drm_private void |
158 | amdgpu_vamgr_free_va(struct amdgpu_bo_va_mgr *mgr, uint64_t va, uint64_t size) | 134 | amdgpu_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 | |||
223 | out: | 185 | out: |
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 | } |