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
