aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/gpu/drm/radeon/radeon_kfd.c
diff options
context:
space:
mode:
authorOded Gabbay <oded.gabbay@amd.com>2014-10-26 14:52:55 -0400
committerOded Gabbay <oded.gabbay@amd.com>2015-01-09 15:26:07 -0500
commitceae881bfa4906db895f2e30872e737a49246830 (patch)
treeb51233145329a66f072f331d3dd655efce47bb6b /drivers/gpu/drm/radeon/radeon_kfd.c
parente27ade73fd38055bd6b374ff86fcd02c0f22b3f3 (diff)
drm/radeon: Impl. new gtt allocate/free functions
This patch adds the implementation of the gtt interface functions. The allocate function will allocate a single bo, pin and map it to kernel memory. It will return the gpu address and cpu ptr as arguments. v2: The bulk of the allocations in the GART is for MQDs. MQDs represent active user-mode queues, which are on the current runlist. It is important to remember that active queues doesn't necessarily mean scheduled/running queues, especially if there is over-subscription of queues or more than a single HSA process. Because the scheduling of the user-mode queues is done by the CP firmware, amdkfd doesn't have any indication if the queue is scheduled or not. If the CP will try to schedule a queue, and its MQD is not present, this will probably stuck the CP permanently, as it will load garbage from the GART (the address of the MQD is given to the CP inside the runlist packet). In addition, there are a couple of small allocations which also should always be pinned - runlist packets (2 packets) and HPDs. runlist packets can be quite large, depending on number of processes and queues. This new allocate function represents the short/mid-term solution of limiting the total memory consumption to around 4MB by default. The long-term solution is to create a mechanism through which radeon/ttm can ask amdkfd to clear GART/VRAM memory due to memory pressure. Then, amdkfd will preempt the running queues and wait until the memory pressure is over. After that, amdkfd will reschedule the queues. Signed-off-by: Oded Gabbay <oded.gabbay@amd.com> Reviewed-by: Alexey Skidanov <Alexey.skidanov@amd.com> Reviewed-by: Alex Deucher <alexander.deucher@amd.com>
Diffstat (limited to 'drivers/gpu/drm/radeon/radeon_kfd.c')
-rw-r--r--drivers/gpu/drm/radeon/radeon_kfd.c85
1 files changed, 85 insertions, 0 deletions
diff --git a/drivers/gpu/drm/radeon/radeon_kfd.c b/drivers/gpu/drm/radeon/radeon_kfd.c
index 0291681a6ff5..2d604ed16b7d 100644
--- a/drivers/gpu/drm/radeon/radeon_kfd.c
+++ b/drivers/gpu/drm/radeon/radeon_kfd.c
@@ -37,6 +37,8 @@ struct kgd_mem {
37 struct radeon_sa_bo *sa_bo; 37 struct radeon_sa_bo *sa_bo;
38 uint64_t gpu_addr; 38 uint64_t gpu_addr;
39 void *ptr; 39 void *ptr;
40 struct radeon_bo *bo;
41 void *cpu_ptr;
40}; 42};
41 43
42static int init_sa_manager(struct kgd_dev *kgd, unsigned int size); 44static int init_sa_manager(struct kgd_dev *kgd, unsigned int size);
@@ -47,6 +49,12 @@ static int allocate_mem(struct kgd_dev *kgd, size_t size, size_t alignment,
47 49
48static void free_mem(struct kgd_dev *kgd, struct kgd_mem *mem); 50static void free_mem(struct kgd_dev *kgd, struct kgd_mem *mem);
49 51
52static int alloc_gtt_mem(struct kgd_dev *kgd, size_t size,
53 void **mem_obj, uint64_t *gpu_addr,
54 void **cpu_ptr);
55
56static void free_gtt_mem(struct kgd_dev *kgd, void *mem_obj);
57
50static uint64_t get_vmem_size(struct kgd_dev *kgd); 58static uint64_t get_vmem_size(struct kgd_dev *kgd);
51static uint64_t get_gpu_clock_counter(struct kgd_dev *kgd); 59static uint64_t get_gpu_clock_counter(struct kgd_dev *kgd);
52 60
@@ -87,6 +95,8 @@ static const struct kfd2kgd_calls kfd2kgd = {
87 .fini_sa_manager = fini_sa_manager, 95 .fini_sa_manager = fini_sa_manager,
88 .allocate_mem = allocate_mem, 96 .allocate_mem = allocate_mem,
89 .free_mem = free_mem, 97 .free_mem = free_mem,
98 .init_gtt_mem_allocation = alloc_gtt_mem,
99 .free_gtt_mem = free_gtt_mem,
90 .get_vmem_size = get_vmem_size, 100 .get_vmem_size = get_vmem_size,
91 .get_gpu_clock_counter = get_gpu_clock_counter, 101 .get_gpu_clock_counter = get_gpu_clock_counter,
92 .get_max_engine_clock_in_mhz = get_max_engine_clock_in_mhz, 102 .get_max_engine_clock_in_mhz = get_max_engine_clock_in_mhz,
@@ -272,6 +282,81 @@ static void free_mem(struct kgd_dev *kgd, struct kgd_mem *mem)
272 kfree(mem); 282 kfree(mem);
273} 283}
274 284
285static int alloc_gtt_mem(struct kgd_dev *kgd, size_t size,
286 void **mem_obj, uint64_t *gpu_addr,
287 void **cpu_ptr)
288{
289 struct radeon_device *rdev = (struct radeon_device *)kgd;
290 struct kgd_mem **mem = (struct kgd_mem **) mem_obj;
291 int r;
292
293 BUG_ON(kgd == NULL);
294 BUG_ON(gpu_addr == NULL);
295 BUG_ON(cpu_ptr == NULL);
296
297 *mem = kmalloc(sizeof(struct kgd_mem), GFP_KERNEL);
298 if ((*mem) == NULL)
299 return -ENOMEM;
300
301 r = radeon_bo_create(rdev, size, PAGE_SIZE, true, RADEON_GEM_DOMAIN_GTT,
302 RADEON_GEM_GTT_WC, NULL, NULL, &(*mem)->bo);
303 if (r) {
304 dev_err(rdev->dev,
305 "failed to allocate BO for amdkfd (%d)\n", r);
306 return r;
307 }
308
309 /* map the buffer */
310 r = radeon_bo_reserve((*mem)->bo, true);
311 if (r) {
312 dev_err(rdev->dev, "(%d) failed to reserve bo for amdkfd\n", r);
313 goto allocate_mem_reserve_bo_failed;
314 }
315
316 r = radeon_bo_pin((*mem)->bo, RADEON_GEM_DOMAIN_GTT,
317 &(*mem)->gpu_addr);
318 if (r) {
319 dev_err(rdev->dev, "(%d) failed to pin bo for amdkfd\n", r);
320 goto allocate_mem_pin_bo_failed;
321 }
322 *gpu_addr = (*mem)->gpu_addr;
323
324 r = radeon_bo_kmap((*mem)->bo, &(*mem)->cpu_ptr);
325 if (r) {
326 dev_err(rdev->dev,
327 "(%d) failed to map bo to kernel for amdkfd\n", r);
328 goto allocate_mem_kmap_bo_failed;
329 }
330 *cpu_ptr = (*mem)->cpu_ptr;
331
332 radeon_bo_unreserve((*mem)->bo);
333
334 return 0;
335
336allocate_mem_kmap_bo_failed:
337 radeon_bo_unpin((*mem)->bo);
338allocate_mem_pin_bo_failed:
339 radeon_bo_unreserve((*mem)->bo);
340allocate_mem_reserve_bo_failed:
341 radeon_bo_unref(&(*mem)->bo);
342
343 return r;
344}
345
346static void free_gtt_mem(struct kgd_dev *kgd, void *mem_obj)
347{
348 struct kgd_mem *mem = (struct kgd_mem *) mem_obj;
349
350 BUG_ON(mem == NULL);
351
352 radeon_bo_reserve(mem->bo, true);
353 radeon_bo_kunmap(mem->bo);
354 radeon_bo_unpin(mem->bo);
355 radeon_bo_unreserve(mem->bo);
356 radeon_bo_unref(&(mem->bo));
357 kfree(mem);
358}
359
275static uint64_t get_vmem_size(struct kgd_dev *kgd) 360static uint64_t get_vmem_size(struct kgd_dev *kgd)
276{ 361{
277 struct radeon_device *rdev = (struct radeon_device *)kgd; 362 struct radeon_device *rdev = (struct radeon_device *)kgd;