AMD General

A new VRAM allocation needs to meet:

        adev->kfd.vram_used + vram_needed <= vram_available

kfd.vram_used already includes BOs that are later pinned.
Pinning does not consume extra VRAM. Subtracting vram_pin_size without adding 
back kfd.vram_pinned counts those bytes twice and causes fake-OOM while VRAM is 
still free.

Add kfd.vram_pinned so reserve_mem_limit() matches get_available_memory().

kfd.vram_pinned is only updated in gpuvm_pin_bo(). dma-buf pin and vmap call 
amdgpu_bo_pin() only, so the counter stays zero and those BOs are still charged 
twice. Update the counter on first pin and last unpin in dma-buf pin/vmap and 
gpuvm_pin_bo.

Signed-off-by: Zhen Han <[email protected]>
---
v3:
- update kfd.vram_pinned from dma-buf pin/vmap and gpuvm_pin_bo
  on first pin / last unpin in amdgpu_dma_buf.c
v2:
- keep vram_pin_size; add kfd.vram_pinned in reserve_mem_limit (Mukul Joshi)
- leave get_available_memory unchanged
- drop former 2/2 pin/unpin changes in amdgpu_object.c (Christian König)

 drivers/gpu/drm/amd/amdgpu/amdgpu_amdkfd.h    |  2 +
 .../gpu/drm/amd/amdgpu/amdgpu_amdkfd_gpuvm.c  | 38 +++++++++++++++----
 drivers/gpu/drm/amd/amdgpu/amdgpu_dma_buf.c   | 22 ++++++++++-
 3 files changed, 53 insertions(+), 9 deletions(-)

diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_amdkfd.h 
b/drivers/gpu/drm/amd/amdgpu/amdgpu_amdkfd.h
index 4541542a28df..9ebae5ffd2ed 100644
--- a/drivers/gpu/drm/amd/amdgpu/amdgpu_amdkfd.h
+++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_amdkfd.h
@@ -378,6 +378,8 @@ void amdgpu_amdkfd_gpuvm_put_bo_ref(struct amdgpu_bo *bo);
  * Return: ZERO if successful in pinning, Non-Zero in case of error.
  */
 int amdgpu_amdkfd_gpuvm_pin_bo(struct amdgpu_bo *bo, u32 domain);
+void amdgpu_amdkfd_account_vram_pin(struct amdgpu_bo *bo); void
+amdgpu_amdkfd_account_vram_unpin(struct amdgpu_bo *bo);

 /**
  * amdgpu_amdkfd_gpuvm_unpin_bo() - Unpins BO using following criteria diff 
--git a/drivers/gpu/drm/amd/amdgpu/amdgpu_amdkfd_gpuvm.c 
b/drivers/gpu/drm/amd/amdgpu/amdgpu_amdkfd_gpuvm.c
index 89958d0f7e59..191985dbc569 100644
--- a/drivers/gpu/drm/amd/amdgpu/amdgpu_amdkfd_gpuvm.c
+++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_amdkfd_gpuvm.c
@@ -237,7 +237,8 @@ int amdgpu_amdkfd_reserve_mem_limit(struct amdgpu_device 
*adev,
        if (adev && xcp_id >= 0 && (!adev->apu_prefer_gtt || 
adev->gmc.is_app_apu)) {
                uint64_t vram_available =
                        vram_size - reserved_for_pt - reserved_for_ras -
-                       atomic64_read(&adev->vram_pin_size);
+                       atomic64_read(&adev->vram_pin_size) +
+                       atomic64_read(&adev->kfd.vram_pinned);
                if (adev->kfd.vram_used[xcp_id] + vram_needed > vram_available) 
{
                        ret = -ENOMEM;
                        goto release;
@@ -1584,6 +1585,28 @@ static int init_kfd_vm(struct amdgpu_vm *vm, void 
**process_info,
        return ret;
 }

+void amdgpu_amdkfd_account_vram_pin(struct amdgpu_bo *bo) {
+       if (!bo->kfd_bo || !bo->tbo.resource)
+               return;
+       if (bo->tbo.resource->mem_type != TTM_PL_VRAM)
+               return;
+
+       atomic64_add(amdgpu_bo_size(bo),
+                    &amdgpu_ttm_adev(bo->tbo.bdev)->kfd.vram_pinned);
+}
+
+void amdgpu_amdkfd_account_vram_unpin(struct amdgpu_bo *bo) {
+       if (!bo->kfd_bo || !bo->tbo.resource)
+               return;
+       if (bo->tbo.resource->mem_type != TTM_PL_VRAM)
+               return;
+
+       atomic64_sub(amdgpu_bo_size(bo),
+                    &amdgpu_ttm_adev(bo->tbo.bdev)->kfd.vram_pinned);
+}
+
 /**
  * amdgpu_amdkfd_gpuvm_pin_bo() - Pins a BO using following criteria
  * @bo: Handle of buffer object being pinned @@ -1598,11 +1621,14 @@ static 
int init_kfd_vm(struct amdgpu_vm *vm, void **process_info,  int 
amdgpu_amdkfd_gpuvm_pin_bo(struct amdgpu_bo *bo, u32 domain)  {
        int ret = 0;
+       bool first_pin;

        ret = amdgpu_bo_reserve(bo, false);
        if (unlikely(ret))
                return ret;

+       first_pin = !bo->tbo.pin_count;
+
        if (bo->flags & AMDGPU_GEM_CREATE_VRAM_CONTIGUOUS) {
                /*
                 * If bo is not contiguous on VRAM, move to system memory first 
to ensure @@ -1626,9 +1652,8 @@ int amdgpu_amdkfd_gpuvm_pin_bo(struct amdgpu_bo 
*bo, u32 domain)

        amdgpu_bo_sync_wait(bo, AMDGPU_FENCE_OWNER_KFD, false);

-       if (!ret && bo->tbo.resource->mem_type == TTM_PL_VRAM)
-                atomic64_add(amdgpu_bo_size(bo),
-                        &amdgpu_ttm_adev(bo->tbo.bdev)->kfd.vram_pinned);
+       if (!ret && first_pin)
+               amdgpu_amdkfd_account_vram_pin(bo);

 out:
        amdgpu_bo_unreserve(bo);
@@ -1653,9 +1678,8 @@ void amdgpu_amdkfd_gpuvm_unpin_bo(struct amdgpu_bo *bo)

        amdgpu_bo_unpin(bo);

-       if (bo->tbo.resource->mem_type == TTM_PL_VRAM)
-               atomic64_sub(amdgpu_bo_size(bo),
-                       &amdgpu_ttm_adev(bo->tbo.bdev)->kfd.vram_pinned);
+       if (!bo->tbo.pin_count)
+               amdgpu_amdkfd_account_vram_unpin(bo);

        amdgpu_bo_unreserve(bo);
 }
diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_dma_buf.c 
b/drivers/gpu/drm/amd/amdgpu/amdgpu_dma_buf.c
index 79828c6f694b..e2674540761d 100644
--- a/drivers/gpu/drm/amd/amdgpu/amdgpu_dma_buf.c
+++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_dma_buf.c
@@ -303,6 +303,8 @@ static int amdgpu_dma_buf_pin(struct dma_buf_attachment 
*attach)
        struct dma_buf *dmabuf = attach->dmabuf;
        struct amdgpu_bo *bo = gem_to_amdgpu_bo(dmabuf->priv);
        u32 domains = bo->allowed_domains;
+       bool first_pin;
+       int r;

        dma_resv_assert_held(dmabuf->resv);

@@ -328,7 +330,12 @@ static int amdgpu_dma_buf_pin(struct dma_buf_attachment 
*attach)
        if (WARN_ON(!domains))
                return -EINVAL;

-       return amdgpu_bo_pin(bo, domains);
+       first_pin = !bo->tbo.pin_count;
+       r = amdgpu_bo_pin(bo, domains);
+       if (!r && first_pin)
+               amdgpu_amdkfd_account_vram_pin(bo);
+
+       return r;
 }

 /**
@@ -344,6 +351,8 @@ static void amdgpu_dma_buf_unpin(struct dma_buf_attachment 
*attach)
        struct amdgpu_bo *bo = gem_to_amdgpu_bo(obj);

        amdgpu_bo_unpin(bo);
+       if (!bo->tbo.pin_count)
+               amdgpu_amdkfd_account_vram_unpin(bo);
 }
 #endif

@@ -516,6 +525,7 @@ static int amdgpu_dma_buf_vmap(struct dma_buf *dma_buf, 
struct iosys_map *map)  {
        struct drm_gem_object *obj = dma_buf->priv;
        struct amdgpu_bo *bo = gem_to_amdgpu_bo(obj);
+       bool first_pin;
        int ret;

        /*
@@ -523,12 +533,18 @@ static int amdgpu_dma_buf_vmap(struct dma_buf *dma_buf, 
struct iosys_map *map)
         * domain is not that important as long as it's mapable. Using
         * GTT and VRAM should be compatible with most use cases.
         */
+       first_pin = !bo->tbo.pin_count;
        ret = amdgpu_bo_pin(bo, AMDGPU_GEM_DOMAIN_GTT | AMDGPU_GEM_DOMAIN_VRAM);
        if (ret)
                return ret;
+       if (first_pin)
+               amdgpu_amdkfd_account_vram_pin(bo);
        ret = drm_gem_dmabuf_vmap(dma_buf, map);
-       if (ret)
+       if (ret) {
                amdgpu_bo_unpin(bo);
+               if (!bo->tbo.pin_count)
+                       amdgpu_amdkfd_account_vram_unpin(bo);
+       }

        return ret;
 }
@@ -540,6 +556,8 @@ static void amdgpu_dma_buf_vunmap(struct dma_buf *dma_buf, 
struct iosys_map *map

        drm_gem_dmabuf_vunmap(dma_buf, map);
        amdgpu_bo_unpin(bo);
+       if (!bo->tbo.pin_count)
+               amdgpu_amdkfd_account_vram_unpin(bo);
 }
 #endif

--
2.43.7

Reply via email to