Drop pm_runtime_get_sync() from open/close KMS to prevent unnecessary
resumes. Instead, the PM reference will only be held if the GPU is
currently awake.

Introduce delayed virtual memory hardware initialization through a
powered_init and root_cleared flag. The powered_init flag handles
initializing the VM domain in GTT/VRAM and moving a GTT domain based VM
into a VRAM domain. The root_cleared flag handles the initial root PD
clearing.

Handling is done through the modified amdgpu_vm_validate() and
amdgpu_vm_pt_create() functions.

Signed-off-by: Shahyan Soltani <[email protected]>
---
 drivers/gpu/drm/amd/amdgpu/amdgpu_kms.c    | 16 +++++++---------
 drivers/gpu/drm/amd/amdgpu/amdgpu_ualink.c |  2 +-
 drivers/gpu/drm/amd/amdgpu/amdgpu_vm.c     | 19 ++++++++++++-------
 drivers/gpu/drm/amd/amdgpu/amdgpu_vm.h     |  7 ++++++-
 drivers/gpu/drm/amd/amdgpu/amdgpu_vm_pt.c  |  7 ++++++-
 5 files changed, 32 insertions(+), 19 deletions(-)

diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_kms.c 
b/drivers/gpu/drm/amd/amdgpu/amdgpu_kms.c
index f34150d20a2f..958d235abb11 100644
--- a/drivers/gpu/drm/amd/amdgpu/amdgpu_kms.c
+++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_kms.c
@@ -1488,9 +1488,7 @@ int amdgpu_driver_open_kms(struct drm_device *dev, struct 
drm_file *file_priv)
 
        file_priv->driver_priv = NULL;
 
-       r = pm_runtime_get_sync(dev->dev);
-       if (r < 0)
-               goto pm_put;
+       int pm_ref = pm_runtime_get_if_active(dev->dev);
 
        fpriv = kzalloc(sizeof(*fpriv), GFP_KERNEL);
        if (unlikely(!fpriv)) {
@@ -1504,7 +1502,7 @@ int amdgpu_driver_open_kms(struct drm_device *dev, struct 
drm_file *file_priv)
 
        amdgpu_debugfs_vm_init(file_priv);
 
-       r = amdgpu_vm_init(adev, &fpriv->vm, fpriv->xcp_id);
+       r = amdgpu_vm_init(adev, &fpriv->vm, fpriv->xcp_id, !!pm_ref);
        if (r)
                goto error_pasid;
 
@@ -1569,9 +1567,8 @@ int amdgpu_driver_open_kms(struct drm_device *dev, struct 
drm_file *file_priv)
        kfree(fpriv);
 
 out_suspend:
-pm_put:
-       pm_runtime_put_autosuspend(dev->dev);
-
+       if (pm_ref > 0)
+               pm_runtime_put_autosuspend(dev->dev);
        return r;
 }
 
@@ -1596,7 +1593,7 @@ void amdgpu_driver_postclose_kms(struct drm_device *dev,
        if (!fpriv)
                return;
 
-       pm_runtime_get_sync(dev->dev);
+       int pm_ref = pm_runtime_get_if_active(dev->dev);
 
        if (amdgpu_device_ip_get_ip_block(adev, AMD_IP_BLOCK_TYPE_UVD) != NULL)
                amdgpu_uvd_free_handles(adev, file_priv);
@@ -1635,7 +1632,8 @@ void amdgpu_driver_postclose_kms(struct drm_device *dev,
        kfree(fpriv);
        file_priv->driver_priv = NULL;
 
-       pm_runtime_put_autosuspend(dev->dev);
+       if (pm_ref > 0)
+               pm_runtime_put_autosuspend(dev->dev);
 }
 
 
diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_ualink.c 
b/drivers/gpu/drm/amd/amdgpu/amdgpu_ualink.c
index 17888cf54447..7b3851649d30 100644
--- a/drivers/gpu/drm/amd/amdgpu/amdgpu_ualink.c
+++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_ualink.c
@@ -4163,7 +4163,7 @@ int amdgpu_ualink_manager_start(struct amdgpu_device 
*adev)
 {
        int i, r;
 
-       r = amdgpu_vm_init(adev, &adev->ualink.npa_vm, 0);
+       r = amdgpu_vm_init(adev, &adev->ualink.npa_vm, 0, true);
        if (r)
                goto out;
 
diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_vm.c 
b/drivers/gpu/drm/amd/amdgpu/amdgpu_vm.c
index 7d3659ef11e5..39c13a4b45fa 100644
--- a/drivers/gpu/drm/amd/amdgpu/amdgpu_vm.c
+++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_vm.c
@@ -594,13 +594,14 @@ int amdgpu_vm_validate(struct amdgpu_device *adev, struct 
amdgpu_vm *vm,
        int r;
 
        dma_resv_assert_held(vm->root.bo->tbo.base.resv);
-       if (vm->generation != new_vm_generation) {
+       if (vm->generation != new_vm_generation || !vm->powered_init) {
                vm->generation = new_vm_generation;
                amdgpu_vm_bo_reset_state_machine(vm);
                amdgpu_vm_fini_entities(vm);
                r = amdgpu_vm_init_entities(adev, vm);
                if (r)
                        return r;
+               vm->powered_init = true;
        }
 
        list_for_each_entry_safe(bo_base, tmp, &vm->kernel.evicted, vm_status) {
@@ -620,6 +621,13 @@ int amdgpu_vm_validate(struct amdgpu_device *adev, struct 
amdgpu_vm *vm,
        scoped_guard(mutex, &vm->eviction_lock)
                vm->evicting = false;
 
+       if (!vm->root_cleared) {
+               r = amdgpu_vm_pt_clear(adev, vm, to_amdgpu_bo_vm(vm->root.bo), 
false);
+               if (r)
+                       return r;
+               vm->root_cleared = true;
+       }
+
        list_for_each_entry_safe(bo_base, tmp, &vm->always_valid.evicted,
                                 vm_status) {
                r = validate(param, bo_base->bo);
@@ -2604,7 +2612,7 @@ void amdgpu_vm_set_task_info(struct amdgpu_vm *vm)
  * 0 for success, error for failure.
  */
 int amdgpu_vm_init(struct amdgpu_device *adev, struct amdgpu_vm *vm,
-                  int32_t xcp_id)
+                  int32_t xcp_id, bool device_active)
 {
        struct amdgpu_bo *root_bo;
        struct amdgpu_bo_vm *root;
@@ -2628,6 +2636,8 @@ int amdgpu_vm_init(struct amdgpu_device *adev, struct 
amdgpu_vm *vm,
 
        ttm_lru_bulk_move_init(&vm->lru_bulk_move);
 
+       vm->powered_init = device_active;
+       vm->root_cleared = false;
        vm->is_compute_context = false;
        vm->need_tlb_fence = amdgpu_userq_enabled(&adev->ddev);
 
@@ -2648,7 +2658,6 @@ int amdgpu_vm_init(struct amdgpu_device *adev, struct 
amdgpu_vm *vm,
        vm->last_update = dma_fence_get_stub();
        vm->last_unlocked = dma_fence_get_stub();
        vm->last_tlb_flush = dma_fence_get_stub();
-       vm->generation = amdgpu_vm_generation(adev, NULL);
 
        mutex_init(&vm->eviction_lock);
        vm->evicting = false;
@@ -2671,10 +2680,6 @@ int amdgpu_vm_init(struct amdgpu_device *adev, struct 
amdgpu_vm *vm,
        if (r)
                goto error_free_root;
 
-       r = amdgpu_vm_pt_clear(adev, vm, root, false);
-       if (r)
-               goto error_free_root;
-
        r = amdgpu_vm_create_task_info(vm);
        if (r)
                dev_dbg(adev->dev, "Failed to create task info for VM\n");
diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_vm.h 
b/drivers/gpu/drm/amd/amdgpu/amdgpu_vm.h
index 8e478d3bda1a..a40d57a1ae83 100644
--- a/drivers/gpu/drm/amd/amdgpu/amdgpu_vm.h
+++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_vm.h
@@ -372,6 +372,10 @@ struct amdgpu_vm {
        bool                    is_npa;
        /* Flag to indicate if VM needs a TLB fence (KFD or KGD) */
        bool                    need_tlb_fence;
+       /* Flag to indicate if VM during initialization holds a runtime 
reference */
+       bool                    powered_init;
+       /* Flag to indicate if VM has been cleared through SDMA at least once */
+       bool                    root_cleared;
 
        /* Memory partition number, -1 means any partition */
        int8_t                  mem_id;
@@ -432,7 +436,8 @@ void amdgpu_vm_manager_init(struct amdgpu_device *adev);
 void amdgpu_vm_manager_fini(struct amdgpu_device *adev);
 
 long amdgpu_vm_wait_idle(struct amdgpu_vm *vm, long timeout);
-int amdgpu_vm_init(struct amdgpu_device *adev, struct amdgpu_vm *vm, int32_t 
xcp_id);
+int amdgpu_vm_init(struct amdgpu_device *adev, struct amdgpu_vm *vm, int32_t 
xcp_id,
+                  bool device_active);
 int amdgpu_vm_make_compute(struct amdgpu_device *adev, struct amdgpu_vm *vm);
 int amdgpu_vm_make_npa(struct amdgpu_device *adev, struct amdgpu_vm *vm);
 void amdgpu_vm_fini(struct amdgpu_device *adev, struct amdgpu_vm *vm);
diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_vm_pt.c 
b/drivers/gpu/drm/amd/amdgpu/amdgpu_vm_pt.c
index c03327f1242d..54f0b62fde6f 100644
--- a/drivers/gpu/drm/amd/amdgpu/amdgpu_vm_pt.c
+++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_vm_pt.c
@@ -456,7 +456,7 @@ int amdgpu_vm_pt_create(struct amdgpu_device *adev, struct 
amdgpu_vm *vm,
        bp.size = amdgpu_vm_pt_size(adev, level);
        bp.byte_align = AMDGPU_GPU_PAGE_SIZE;
 
-       if (!adev->gmc.is_app_apu)
+       if (!adev->gmc.is_app_apu && vm->powered_init)
                bp.domain = AMDGPU_GEM_DOMAIN_VRAM;
        else
                bp.domain = AMDGPU_GEM_DOMAIN_GTT;
@@ -486,6 +486,11 @@ int amdgpu_vm_pt_create(struct amdgpu_device *adev, struct 
amdgpu_vm *vm,
        if (r)
                return r;
 
+       if (bp.domain == AMDGPU_GEM_DOMAIN_GTT && !adev->gmc.is_app_apu) {
+               (*vmbo)->bo.preferred_domains = AMDGPU_GEM_DOMAIN_VRAM;
+               (*vmbo)->bo.allowed_domains = AMDGPU_GEM_DOMAIN_GTT | 
AMDGPU_GEM_DOMAIN_VRAM;
+       }
+
        /* Assumes that reservation is shared with the VM root and that the
         * reservation is locked
         */
-- 
2.55.0

Reply via email to