[PATCH 2/3] drm/amdgpu: add functions to create bo at the specified position

Horace Chen horace.chen at amd.com
Wed Sep 27 09:23:50 UTC 2017


 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 | 118 ++++++++++++++++++++++++++++-
 drivers/gpu/drm/amd/amdgpu/amdgpu_object.h |   6 ++
 2 files changed, 122 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..8ea7fec 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,11 @@ static int amdgpu_bo_do_create(struct amdgpu_device *adev,
 	u64 initial_bytes_moved, bytes_moved;
 	size_t acc_size;
 	int r;
+	int i;
 
 	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 +369,23 @@ 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 only && start_addr in GPU 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) {
+		/*change it to offset */
+		start_addr -= adev->mc.vram_start;
+		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 +438,100 @@ static int amdgpu_bo_do_create(struct amdgpu_device *adev,
 	return r;
 }
 
+/**
+ * amdgpu_bo_create_vram_specified -
+ *    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_specified(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_specified - free BO for specified vram
+ *
+ * @bo: amdgpu BO to free
+ * @gpu_addr : gpu address
+ * @cpu_addr : cpu address if mapped
+ *
+ * unmaps and unpin a BO for specified vram.
+ */
+void amdgpu_bo_free_vram_specified(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 +541,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 +571,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..8742583 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_specified(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_specified(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



More information about the amd-gfx mailing list