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

Reply via email to