two helper functions for allocating and freeing kernel-internal
GTT (Graphics Translation Table) buffer objects, intended for use by
the SPM ring buffer allocation path.
amdgpu_bo_alloc_gtt_mem():
Allocates a TTM kernel BO of the requested size in GTT domain,
PAGE_SIZE aligned. The bo_ptr_size is set to sizeof(struct amdgpu_bo).
After creation the BO is reserved, pinned to GTT, GART-bound via
amdgpu_ttm_alloc_gart(), and kernel-mapped via amdgpu_bo_kmap().
On success, the caller receives the opaque BO handle (*mem_obj),
the GPU virtual address (*gpu_addr), and the kernel virtual address
(*cpu_ptr). All intermediate steps are rolled back cleanly on any
failure via a chained goto error path.
Two optional flags control BO creation:
- mqd_gfx9=true: sets AMDGPU_GEM_CREATE_CP_MQD_GFX9, required for
GFX9 MQD-compatible allocations.
- is_uswc_mode=true: sets AMDGPU_GEM_CREATE_CPU_GTT_USWC, enabling
uncached speculative write-combining CPU access to the GTT buffer.
amdgpu_bo_free_gtt_mem():
Reverses the allocation by reserving the BO, unmapping (kunmap),
unpinning, unreserving, and dropping the last reference (unref).
Handles NULL gracefully and logs an error if reservation fails.
Signed-off-by: James Zhu <[email protected]>
---
drivers/gpu/drm/amd/amdgpu/amdgpu_object.c | 97 ++++++++++++++++++++++
drivers/gpu/drm/amd/amdgpu/amdgpu_object.h | 5 +-
drivers/gpu/drm/amd/amdgpu/amdgpu_vm.h | 1 -
3 files changed, 101 insertions(+), 2 deletions(-)
diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_object.c
b/drivers/gpu/drm/amd/amdgpu/amdgpu_object.c
index 1fb956400696..993171979896 100644
--- a/drivers/gpu/drm/amd/amdgpu/amdgpu_object.c
+++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_object.c
@@ -1696,4 +1696,101 @@ u64 amdgpu_bo_print_info(int id, struct amdgpu_bo *bo,
struct seq_file *m)
return size;
}
+
+int amdgpu_bo_alloc_gtt_mem(struct amdgpu_device *adev, size_t size,
+ void **mem_obj, uint64_t *gpu_addr,
+ void **cpu_ptr, bool mqd_gfx9, bool
is_uswc_mode)
+{
+ struct amdgpu_bo *bo = NULL;
+ struct amdgpu_bo_param bp;
+ int r;
+ void *cpu_ptr_tmp = NULL;
+
+ memset(&bp, 0, sizeof(bp));
+ bp.size = size;
+ bp.byte_align = PAGE_SIZE;
+ bp.domain = AMDGPU_GEM_DOMAIN_GTT;
+ if (is_uswc_mode)
+ bp.flags = AMDGPU_GEM_CREATE_CPU_GTT_USWC;
+ else
+ bp.flags = 0;
+ bp.type = ttm_bo_type_kernel;
+ bp.resv = NULL;
+ bp.bo_ptr_size = sizeof(struct amdgpu_bo);
+
+ if (mqd_gfx9)
+ bp.flags |= AMDGPU_GEM_CREATE_CP_MQD_GFX9;
+
+ r = amdgpu_bo_create(adev, &bp, &bo);
+ if (r) {
+ dev_err(adev->dev,
+ "failed to allocate BO for amdgpu (%d)\n", r);
+ return r;
+ }
+
+ /* map the buffer */
+ r = amdgpu_bo_reserve(bo, true);
+ if (r) {
+ dev_err(adev->dev, "(%d) failed to reserve bo for amdgpu\n", r);
+ goto allocate_mem_reserve_bo_failed;
+ }
+
+ r = amdgpu_bo_pin(bo, AMDGPU_GEM_DOMAIN_GTT);
+ if (r) {
+ dev_err(adev->dev, "(%d) failed to pin bo for amdgpu\n", r);
+ goto allocate_mem_pin_bo_failed;
+ }
+
+ r = amdgpu_ttm_alloc_gart(&bo->tbo);
+ if (r) {
+ dev_err(adev->dev, "%p bind failed\n", bo);
+ goto allocate_mem_kmap_bo_failed;
+ }
+
+ r = amdgpu_bo_kmap(bo, &cpu_ptr_tmp);
+ if (r) {
+ dev_err(adev->dev,
+ "(%d) failed to map bo to GTT for amdgpu", r);
+ goto allocate_mem_kmap_bo_failed;
+ }
+
+ *mem_obj = bo;
+ *gpu_addr = amdgpu_bo_gpu_offset(bo);
+ *cpu_ptr = cpu_ptr_tmp;
+
+ amdgpu_bo_unreserve(bo);
+
+ return 0;
+
+allocate_mem_kmap_bo_failed:
+ amdgpu_bo_unpin(bo);
+allocate_mem_pin_bo_failed:
+ amdgpu_bo_unreserve(bo);
+allocate_mem_reserve_bo_failed:
+ amdgpu_bo_unref(&bo);
+
+ return r;
+}
+
+void amdgpu_bo_free_gtt_mem(struct amdgpu_device *adev, void **mem_obj)
+{
+ struct amdgpu_bo **bo = (struct amdgpu_bo **) mem_obj;
+ int r;
+
+ if (!bo || !*bo)
+ return;
+
+ r = amdgpu_bo_reserve(*bo, true);
+ if (r) {
+ dev_err(adev->dev,
+ "(%d) failed to reserve bo to free", r);
+ return;
+ }
+
+ amdgpu_bo_kunmap(*bo);
+ amdgpu_bo_unpin(*bo);
+ amdgpu_bo_unreserve(*bo);
+ amdgpu_bo_unref(bo);
+}
+
#endif
diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_object.h
b/drivers/gpu/drm/amd/amdgpu/amdgpu_object.h
index 912c9afaf9e1..0102d43b2edc 100644
--- a/drivers/gpu/drm/amd/amdgpu/amdgpu_object.h
+++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_object.h
@@ -353,5 +353,8 @@ void amdgpu_debugfs_sa_init(struct amdgpu_device *adev);
bool amdgpu_bo_support_uswc(u64 bo_flags);
-
+int amdgpu_bo_alloc_gtt_mem(struct amdgpu_device *adev, size_t size,
+ void **mem_obj, uint64_t *gpu_addr,
+ void **cpu_ptr, bool mqd_gfx9, bool
is_uswc_mode);
+void amdgpu_bo_free_gtt_mem(struct amdgpu_device *adev, void **mem_obj);
#endif
diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_vm.h
b/drivers/gpu/drm/amd/amdgpu/amdgpu_vm.h
index 1a3a7229de56..7b88693eb6f4 100644
--- a/drivers/gpu/drm/amd/amdgpu/amdgpu_vm.h
+++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_vm.h
@@ -720,5 +720,4 @@ void amdgpu_vm_print_task_info(struct amdgpu_device *adev,
list_for_each_entry(mapping, &(bo_va)->valids, list)
#define amdgpu_vm_bo_va_for_each_invalid_mapping(bo_va, mapping) \
list_for_each_entry(mapping, &(bo_va)->invalids, list)
-
#endif
--
2.34.1