Add two function to create and free bo at the specified position on the VRAM. Add a new parameter to amdgpu_bo_do_create to tell the start address of the special bo. If the start address is located in the GPU MC address space, the placement will be set to the exact place according to the size and start address. Otherwise the start address will be ingored. Signed-off-by: Horace Chen <horace.chen at amd.com> --- drivers/gpu/drm/amd/amdgpu/amdgpu_object.c | 129 ++++++++++++++++++++++++++++- drivers/gpu/drm/amd/amdgpu/amdgpu_object.h | 6 ++ 2 files changed, 133 insertions(+), 2 deletions(-) diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_object.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_object.c index 6982bae..0695160 100644 --- a/drivers/gpu/drm/amd/amdgpu/amdgpu_object.c +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_object.c @@ -284,6 +284,7 @@ void amdgpu_bo_free_kernel(struct amdgpu_bo **bo, u64 *gpu_addr, } static int amdgpu_bo_do_create(struct amdgpu_device *adev, + u64 start_addr, unsigned long size, int byte_align, bool kernel, u32 domain, u64 flags, struct sg_table *sg, @@ -297,9 +298,12 @@ static int amdgpu_bo_do_create(struct amdgpu_device *adev, u64 initial_bytes_moved, bytes_moved; size_t acc_size; int r; + int i; + bool vram_restricted = false; page_align = roundup(byte_align, PAGE_SIZE) >> PAGE_SHIFT; size = ALIGN(size, PAGE_SIZE); + start_addr = ALIGN(start_addr, PAGE_SIZE); if (kernel) { type = ttm_bo_type_kernel; @@ -366,6 +370,32 @@ static int amdgpu_bo_do_create(struct amdgpu_device *adev, bo->tbo.bdev = &adev->mman.bdev; amdgpu_ttm_placement_from_domain(bo, domain); + /* + * if domain is VRAM && start_addr in vram address space, + * set the place to the specified place + */ + if ((domain == AMDGPU_GEM_DOMAIN_VRAM) && + start_addr >= adev->mc.vram_start && + (start_addr + size) < adev->mc.vram_end) { + start_addr -= adev->mc.vram_start; + vram_restricted = true; + } else if ((domain == AMDGPU_GEM_DOMAIN_GTT) && + start_addr >= adev->mc.gart_start && + (start_addr + size) < adev->mc.gart_end) { + /* if in gart address space */ + start_addr -= adev->mc.gart_start; + vram_restricted = true; + } + + if (vram_restricted) { + for (i = 0; i < bo->placement.num_placement; ++i) { + bo->placements[i].fpfn = + start_addr >> PAGE_SHIFT; + bo->placements[i].lpfn = + (start_addr + size) >> PAGE_SHIFT; + } + } + initial_bytes_moved = atomic64_read(&adev->num_bytes_moved); /* Kernel allocation are uninterruptible */ r = ttm_bo_init_reserved(&adev->mman.bdev, &bo->tbo, size, type, @@ -418,6 +448,101 @@ static int amdgpu_bo_do_create(struct amdgpu_device *adev, return r; } +/** + * amdgpu_bo_create_vram_restricted_kernel - + * create BO at the specified place on the VRAM. + * + * @adev: amdgpu device object + * @offset: start offset of the new BO + * @size: size for the new BO + * @byte_align: alignment for the new BO + * @flags: addition flags for the BO + * @bo_ptr: resulting BO + * @gpu_addr: GPU addr of the pinned BO + * @cpu_addr: optional CPU address mapping + * + * Allocates and pins a BO at the specified place on the VRAM. + * + * Returns 0 on success, negative error code otherwise. + */ +int amdgpu_bo_create_vram_restricted_kernel(struct amdgpu_device *adev, + u64 offset, unsigned long size, int byte_align, + u64 flags, struct amdgpu_bo **bo_ptr, + u64 *gpu_addr, void **cpu_addr) +{ + int r; + u64 start_addr = offset + adev->mc.vram_start; + /* specified memory must be in contiguous*/ + flags |= AMDGPU_GEM_CREATE_VRAM_CONTIGUOUS; + + r = amdgpu_bo_do_create(adev, start_addr, size, byte_align, true, + AMDGPU_GEM_DOMAIN_VRAM, flags, NULL, NULL, 0, bo_ptr); + if (r) + return r; + + r = amdgpu_bo_reserve(*bo_ptr, false); + if (r) + goto error_reserve; + r = amdgpu_bo_pin_restricted(*bo_ptr, + AMDGPU_GEM_DOMAIN_VRAM, offset, (offset + size), + gpu_addr); + if (r) + goto error_pin; + if (cpu_addr) { + r = amdgpu_bo_kmap(*bo_ptr, + cpu_addr); + if (r) + goto error_kmap; + } + + amdgpu_bo_unreserve(*bo_ptr); + + return r; +error_kmap: + amdgpu_bo_unpin(*bo_ptr); +error_pin: + amdgpu_bo_unreserve(*bo_ptr); +error_reserve: + amdgpu_bo_unref(bo_ptr); + if (cpu_addr) + *cpu_addr = NULL; + if (gpu_addr) + *gpu_addr = 0; + return r; +} + +/** + * amdgpu_bo_free_vram_restricted_kernel - free BO for restricted vram + * + * @bo: amdgpu BO to free + * @gpu_addr : gpu address + * @cpu_addr : cpu address if mapped + * + * unmaps and unpin a BO which created by + * amdgpu_bo_create_vram_restricted_kernel. + */ +void amdgpu_bo_free_vram_restricted_kernel(struct amdgpu_bo **bo, u64 *gpu_addr, + void **cpu_addr) +{ + if (*bo == NULL) + return; + + if (likely(amdgpu_bo_reserve(*bo, true) == 0)) { + if (cpu_addr) + amdgpu_bo_kunmap(*bo); + amdgpu_bo_unpin(*bo); + amdgpu_bo_unreserve(*bo); + } + amdgpu_bo_unref(bo); + + if (gpu_addr) + *gpu_addr = 0; + + if (cpu_addr) + *cpu_addr = NULL; +} + + static int amdgpu_bo_create_shadow(struct amdgpu_device *adev, unsigned long size, int byte_align, struct amdgpu_bo *bo) @@ -427,7 +552,7 @@ static int amdgpu_bo_create_shadow(struct amdgpu_device *adev, if (bo->shadow) return 0; - r = amdgpu_bo_do_create(adev, size, byte_align, true, + r = amdgpu_bo_do_create(adev, 0, size, byte_align, true, AMDGPU_GEM_DOMAIN_GTT, AMDGPU_GEM_CREATE_CPU_GTT_USWC | AMDGPU_GEM_CREATE_SHADOW, @@ -457,7 +582,7 @@ int amdgpu_bo_create(struct amdgpu_device *adev, uint64_t parent_flags = flags & ~AMDGPU_GEM_CREATE_SHADOW; int r; - r = amdgpu_bo_do_create(adev, size, byte_align, kernel, domain, + r = amdgpu_bo_do_create(adev, 0, size, byte_align, kernel, domain, parent_flags, sg, resv, init_value, bo_ptr); if (r) return r; diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_object.h b/drivers/gpu/drm/amd/amdgpu/amdgpu_object.h index 39b6bf6..0f34ba77 100644 --- a/drivers/gpu/drm/amd/amdgpu/amdgpu_object.h +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_object.h @@ -205,6 +205,12 @@ int amdgpu_bo_create_kernel(struct amdgpu_device *adev, u64 *gpu_addr, void **cpu_addr); void amdgpu_bo_free_kernel(struct amdgpu_bo **bo, u64 *gpu_addr, void **cpu_addr); +int amdgpu_bo_create_vram_restricted_kernel(struct amdgpu_device *adev, + u64 offset, unsigned long size, int byte_align, + u64 flags, struct amdgpu_bo **bo_ptr, + u64 *gpu_addr, void **cpu_addr); +void amdgpu_bo_free_vram_restricted_kernel(struct amdgpu_bo **bo, u64 *gpu_addr, + void **cpu_addr); int amdgpu_bo_kmap(struct amdgpu_bo *bo, void **ptr); void *amdgpu_bo_kptr(struct amdgpu_bo *bo); void amdgpu_bo_kunmap(struct amdgpu_bo *bo); -- 2.7.4