Skip to contentSkip to conversation

drm/amdgpu: add functions to create bo at the specified position

PATCH NAK Horace Chen 2 participants 4 messages Sep 28, 2017 – Sep 29, 2017 2 messages not in the archive

Subsystems (2)
lore
Share & tools
lore
#0 lore raw

PATCH 1/2 drm/amdgpu: add functions to create bo at the specified position

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.

---
 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(-)
drivers/gpu/drm/amd/amdgpu/amdgpu_object.c +127 -2
index 6982bae..0695160 100644
@@ -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;
drivers/gpu/drm/amd/amdgpu/amdgpu_object.h +6 -0
index 39b6bf6..0f34ba77 100644
@@ -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);
Signature · 6 lines
2.7.4

_______________________________________________
amd-gfx mailing list
[email protected]
https://lists.freedesktop.org/mailman/listinfo/amd-gfx

A message that is not in the archive (sent off-list or not yet received): 1506587791-6549-1-git-send-email-horace.chen-5C7GfCeVMHo@public.gmane.org

#2 lore raw

PATCH 2/2 drm/amdgpu: Reserve shared memory on VRAM for SR-IOV

SR-IOV need to reserve a piece of shared VRAM to exchange data betweem PF and VF. The start address and size of the shared mem are passed to guest through VBIOS structure VRAM_UsageByFirmware.

VRAM_UsageByFirmware is a general feature in VBIOS, it indicates that VBIOS need to reserve a piece of memory on the VRAM.

---
 drivers/gpu/drm/amd/amdgpu/amdgpu.h          | 14 +++++++
 drivers/gpu/drm/amd/amdgpu/amdgpu_atombios.c | 18 ++++++++-
 drivers/gpu/drm/amd/amdgpu/amdgpu_device.c   | 57 ++++++++++++++++++++++++++++
 drivers/gpu/drm/amd/amdgpu/amdgpu_ttm.c      |  9 +++++
 4 files changed, 97 insertions(+), 1 deletion(-)
drivers/gpu/drm/amd/amdgpu/amdgpu.h +14 -0
index a5b0b67..b802858 100644
@@ -1380,6 +1380,18 @@ struct amdgpu_atcs {
 };
 
 /*
+ * Firmware VRAM reservation
+ */
+struct amdgpu_fw_vram_usage {
+	u64 start_offset;
+	u64 size;
+	struct amdgpu_bo *reserved_bo;
+	volatile uint32_t *va;
+};
+
+int amdgpu_fw_reserve_vram_init(struct amdgpu_device *adev);
+
+/*
  * CGS
  */
 struct cgs_device *amdgpu_cgs_create_device(struct amdgpu_device *adev);
@@ -1588,6 +1600,8 @@ struct amdgpu_device {
 	struct delayed_work     late_init_work;
 
 	struct amdgpu_virt	virt;
+	/* firmware VRAM reservation */
+	struct amdgpu_fw_vram_usage fw_vram_usage;
 
 	/* link all shadow bo */
 	struct list_head                shadow_list;
drivers/gpu/drm/amd/amdgpu/amdgpu_atombios.c +17 -1
index ce44358..f66d33e 100644
@@ -1807,6 +1807,8 @@ int amdgpu_atombios_allocate_fb_scratch(struct amdgpu_device *adev)
 	uint16_t data_offset;
 	int usage_bytes = 0;
 	struct _ATOM_VRAM_USAGE_BY_FIRMWARE *firmware_usage;
+	u64 start_addr;
+	u64 size;
 
 	if (amdgpu_atom_parse_data_header(ctx, index, NULL, NULL, NULL, &data_offset)) {
 		firmware_usage = (struct _ATOM_VRAM_USAGE_BY_FIRMWARE *)(ctx->bios + data_offset);
@@ -1815,7 +1817,21 @@ int amdgpu_atombios_allocate_fb_scratch(struct amdgpu_device *adev)
 			  le32_to_cpu(firmware_usage->asFirmwareVramReserveInfo[0].ulStartAddrUsedByFirmware),
 			  le16_to_cpu(firmware_usage->asFirmwareVramReserveInfo[0].usFirmwareUseInKb));
 
-		usage_bytes = le16_to_cpu(firmware_usage->asFirmwareVramReserveInfo[0].usFirmwareUseInKb) * 1024;
+		start_addr = firmware_usage->asFirmwareVramReserveInfo[0].ulStartAddrUsedByFirmware;
+		size = firmware_usage->asFirmwareVramReserveInfo[0].usFirmwareUseInKb;
+
+		if ((uint32_t)(start_addr & ATOM_VRAM_OPERATION_FLAGS_MASK) ==
+			(uint32_t)(ATOM_VRAM_BLOCK_SRIOV_MSG_SHARE_RESERVATION <<
+			ATOM_VRAM_OPERATION_FLAGS_SHIFT)) {
+			/* Firmware request VRAM reservation for SR-IOV */
+			adev->fw_vram_usage.start_offset = (start_addr &
+				(~ATOM_VRAM_OPERATION_FLAGS_MASK)) << 10;
+			adev->fw_vram_usage.size = size << 10;
+			/* Use the default scratch size */
+			usage_bytes = 0;
+		} else {
+			usage_bytes = le16_to_cpu(firmware_usage->asFirmwareVramReserveInfo[0].usFirmwareUseInKb) * 1024;
+		}
 	}
 	ctx->scratch_size_bytes = 0;
 	if (usage_bytes == 0)
drivers/gpu/drm/amd/amdgpu/amdgpu_device.c +57 -0

69 lines not on this page · raw message

drivers/gpu/drm/amd/amdgpu/amdgpu_ttm.c +9 -0
index 1086f03..a5253cf 100644
@@ -1256,6 +1256,15 @@ int amdgpu_ttm_init(struct amdgpu_device *adev)
 	/* Change the size here instead of the init above so only lpfn is affected */
 	amdgpu_ttm_set_active_vram_size(adev, adev->mc.visible_vram_size);
 
+	/*
+	 *The reserved vram for firmware must be pinned to the specified
+	 *place on the VRAM, so reserve it early.
+	 */
+	r = amdgpu_fw_reserve_vram_init(adev);
+	if (r) {
+		return r;
+	}
+
 	r = amdgpu_bo_create_kernel(adev, adev->mc.stolen_size, PAGE_SIZE,
 				    AMDGPU_GEM_DOMAIN_VRAM,
 				    &adev->stolen_vga_memory,
Signature · 6 lines
2.7.4

_______________________________________________
amd-gfx mailing list
[email protected]
https://lists.freedesktop.org/mailman/listinfo/amd-gfx
#3 lore raw
In reply to a message not in the archive

NAK, please use the existing functionality for that.

Using amdgpu_bo_do_create() with domain=0 will just create the amdgpu_bo structure without allocating any backing memory.

This BO can then pinned to the desired VRAM location using amdgpu_bo_pin().

Regards,
Christian.

Am 28.09.2017 um 10:36 schrieb Horace Chen:

Quoted 200 lines

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.

---
  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(-)
drivers/gpu/drm/amd/amdgpu/amdgpu_object.c +127 -2
index 6982bae..0695160 100644
@@ -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;
drivers/gpu/drm/amd/amdgpu/amdgpu_object.h +0 -0
index 39b6bf6..0f34ba77 100644
@@ -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,

drivers/gpu/drm/amd/amdgpu/amdgpu_object.h int amdgpu_bo_create_kernel(struct amdgpu_device *adev, · line 216

Quoted 10 lines
drivers/gpu/drm/amd/amdgpu/amdgpu_object.h +6 -0
  			   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);

_______________________________________________
amd-gfx mailing list
[email protected]
https://lists.freedesktop.org/mailman/listinfo/amd-gfx

A message that is not in the archive (sent off-list or not yet received): 6e0444b5-b9e4-4611-149a-d0355d197c46-Re5JQEeQqe8AvxtiuMwx3w@public.gmane.org

author NAK
#5 lore raw

OK. I have tried, it worked without any failure.
Thanks Christian.

Regards,
Horace.
-----Original Message-----
From: Christian König [mailto:[email protected]]
Sent: Thursday, September 28, 2017 10:01 PM
To: Chen, Horace <[email protected]>; [email protected]
Cc: Deucher, Alexander <[email protected]>
Subject: Re: [PATCH 1/2] drm/amdgpu: add functions to create bo at the specified position

NAK, please use the existing functionality for that.

Using amdgpu_bo_do_create() with domain=0 will just create the amdgpu_bo structure without allocating any backing memory.

This BO can then pinned to the desired VRAM location using amdgpu_bo_pin().

Regards,
Christian.

Am 28.09.2017 um 10:36 schrieb Horace Chen:

Quoted 200 lines

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.

---
  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(-)
drivers/gpu/drm/amd/amdgpu/amdgpu_object.c +127 -2
index 6982bae..0695160 100644
@@ -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;
drivers/gpu/drm/amd/amdgpu/amdgpu_object.h +0 -0
index 39b6bf6..0f34ba77 100644
@@ -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,

drivers/gpu/drm/amd/amdgpu/amdgpu_object.h int amdgpu_bo_create_kernel(struct amdgpu_device *adev, · line 216

Quoted 10 lines
drivers/gpu/drm/amd/amdgpu/amdgpu_object.h +6 -0
  			   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);

_______________________________________________
amd-gfx mailing list
[email protected]
https://lists.freedesktop.org/mailman/listinfo/amd-gfx