Merge tag 'amd-drm-next-5.14-2021-05-19' of https://gitlab.freedesktop.org/agd5f...
[sfrench/cifs-2.6.git] / drivers / gpu / drm / amd / amdgpu / amdgpu_vm.c
index 4a3e3f72e12774bfd7ec951d5a17d2d6d7b50918..edc63d3e087ec3c845c051142d4fd46e4ddf3af9 100644 (file)
@@ -38,6 +38,7 @@
 #include "amdgpu_gmc.h"
 #include "amdgpu_xgmi.h"
 #include "amdgpu_dma_buf.h"
+#include "kfd_svm.h"
 
 /**
  * DOC: GPUVM
@@ -850,35 +851,60 @@ static int amdgpu_vm_clear_bo(struct amdgpu_device *adev,
 }
 
 /**
- * amdgpu_vm_bo_param - fill in parameters for PD/PT allocation
+ * amdgpu_vm_pt_create - create bo for PD/PT
  *
  * @adev: amdgpu_device pointer
  * @vm: requesting vm
  * @level: the page table level
  * @immediate: use a immediate update
- * @bp: resulting BO allocation parameters
+ * @bo: pointer to the buffer object pointer
  */
-static void amdgpu_vm_bo_param(struct amdgpu_device *adev, struct amdgpu_vm *vm,
+static int amdgpu_vm_pt_create(struct amdgpu_device *adev,
+                              struct amdgpu_vm *vm,
                               int level, bool immediate,
-                              struct amdgpu_bo_param *bp)
+                              struct amdgpu_bo **bo)
 {
-       memset(bp, 0, sizeof(*bp));
+       struct amdgpu_bo_param bp;
+       int r;
 
-       bp->size = amdgpu_vm_bo_size(adev, level);
-       bp->byte_align = AMDGPU_GPU_PAGE_SIZE;
-       bp->domain = AMDGPU_GEM_DOMAIN_VRAM;
-       bp->domain = amdgpu_bo_get_preferred_pin_domain(adev, bp->domain);
-       bp->flags = AMDGPU_GEM_CREATE_VRAM_CONTIGUOUS |
+       memset(&bp, 0, sizeof(bp));
+
+       bp.size = amdgpu_vm_bo_size(adev, level);
+       bp.byte_align = AMDGPU_GPU_PAGE_SIZE;
+       bp.domain = AMDGPU_GEM_DOMAIN_VRAM;
+       bp.domain = amdgpu_bo_get_preferred_pin_domain(adev, bp.domain);
+       bp.flags = AMDGPU_GEM_CREATE_VRAM_CONTIGUOUS |
                AMDGPU_GEM_CREATE_CPU_GTT_USWC;
-       bp->bo_ptr_size = sizeof(struct amdgpu_bo);
+       bp.bo_ptr_size = sizeof(struct amdgpu_bo);
        if (vm->use_cpu_for_update)
-               bp->flags |= AMDGPU_GEM_CREATE_CPU_ACCESS_REQUIRED;
-       else if (!vm->root.base.bo || vm->root.base.bo->shadow)
-               bp->flags |= AMDGPU_GEM_CREATE_SHADOW;
-       bp->type = ttm_bo_type_kernel;
-       bp->no_wait_gpu = immediate;
+               bp.flags |= AMDGPU_GEM_CREATE_CPU_ACCESS_REQUIRED;
+
+       bp.type = ttm_bo_type_kernel;
+       bp.no_wait_gpu = immediate;
        if (vm->root.base.bo)
-               bp->resv = vm->root.base.bo->tbo.base.resv;
+               bp.resv = vm->root.base.bo->tbo.base.resv;
+
+       r = amdgpu_bo_create(adev, &bp, bo);
+       if (r)
+               return r;
+
+       if (vm->is_compute_context && (adev->flags & AMD_IS_APU))
+               return 0;
+
+       if (!bp.resv)
+               WARN_ON(dma_resv_lock((*bo)->tbo.base.resv,
+                                     NULL));
+       r = amdgpu_bo_create_shadow(adev, bp.size, *bo);
+
+       if (!bp.resv)
+               dma_resv_unlock((*bo)->tbo.base.resv);
+
+       if (r) {
+               amdgpu_bo_unref(bo);
+               return r;
+       }
+
+       return 0;
 }
 
 /**
@@ -901,7 +927,6 @@ static int amdgpu_vm_alloc_pts(struct amdgpu_device *adev,
                               bool immediate)
 {
        struct amdgpu_vm_pt *entry = cursor->entry;
-       struct amdgpu_bo_param bp;
        struct amdgpu_bo *pt;
        int r;
 
@@ -919,9 +944,7 @@ static int amdgpu_vm_alloc_pts(struct amdgpu_device *adev,
        if (entry->base.bo)
                return 0;
 
-       amdgpu_vm_bo_param(adev, vm, cursor->level, immediate, &bp);
-
-       r = amdgpu_bo_create(adev, &bp, &pt);
+       r = amdgpu_vm_pt_create(adev, vm, cursor->level, immediate, &pt);
        if (r)
                return r;
 
@@ -1593,15 +1616,15 @@ static int amdgpu_vm_update_ptes(struct amdgpu_vm_update_params *params,
  * Returns:
  * 0 for success, -EINVAL for failure.
  */
-static int amdgpu_vm_bo_update_mapping(struct amdgpu_device *adev,
-                                      struct amdgpu_device *bo_adev,
-                                      struct amdgpu_vm *vm, bool immediate,
-                                      bool unlocked, struct dma_resv *resv,
-                                      uint64_t start, uint64_t last,
-                                      uint64_t flags, uint64_t offset,
-                                      struct drm_mm_node *nodes,
-                                      dma_addr_t *pages_addr,
-                                      struct dma_fence **fence)
+int amdgpu_vm_bo_update_mapping(struct amdgpu_device *adev,
+                               struct amdgpu_device *bo_adev,
+                               struct amdgpu_vm *vm, bool immediate,
+                               bool unlocked, struct dma_resv *resv,
+                               uint64_t start, uint64_t last,
+                               uint64_t flags, uint64_t offset,
+                               struct drm_mm_node *nodes,
+                               dma_addr_t *pages_addr,
+                               struct dma_fence **fence)
 {
        struct amdgpu_vm_update_params params;
        enum amdgpu_sync_mode sync_mode;
@@ -2818,7 +2841,6 @@ long amdgpu_vm_wait_idle(struct amdgpu_vm *vm, long timeout)
  *
  * @adev: amdgpu_device pointer
  * @vm: requested vm
- * @vm_context: Indicates if it GFX or Compute context
  * @pasid: Process address space identifier
  *
  * Init @vm fields.
@@ -2826,10 +2848,8 @@ long amdgpu_vm_wait_idle(struct amdgpu_vm *vm, long timeout)
  * Returns:
  * 0 for success, error for failure.
  */
-int amdgpu_vm_init(struct amdgpu_device *adev, struct amdgpu_vm *vm,
-                  int vm_context, u32 pasid)
+int amdgpu_vm_init(struct amdgpu_device *adev, struct amdgpu_vm *vm, u32 pasid)
 {
-       struct amdgpu_bo_param bp;
        struct amdgpu_bo *root;
        int r, i;
 
@@ -2861,16 +2881,9 @@ int amdgpu_vm_init(struct amdgpu_device *adev, struct amdgpu_vm *vm,
        vm->pte_support_ats = false;
        vm->is_compute_context = false;
 
-       if (vm_context == AMDGPU_VM_CONTEXT_COMPUTE) {
-               vm->use_cpu_for_update = !!(adev->vm_manager.vm_update_mode &
-                                               AMDGPU_VM_USE_CPU_FOR_COMPUTE);
+       vm->use_cpu_for_update = !!(adev->vm_manager.vm_update_mode &
+                                   AMDGPU_VM_USE_CPU_FOR_GFX);
 
-               if (adev->asic_type == CHIP_RAVEN)
-                       vm->pte_support_ats = true;
-       } else {
-               vm->use_cpu_for_update = !!(adev->vm_manager.vm_update_mode &
-                                               AMDGPU_VM_USE_CPU_FOR_GFX);
-       }
        DRM_DEBUG_DRIVER("VM update mode is %s\n",
                         vm->use_cpu_for_update ? "CPU" : "SDMA");
        WARN_ONCE((vm->use_cpu_for_update &&
@@ -2887,10 +2900,8 @@ int amdgpu_vm_init(struct amdgpu_device *adev, struct amdgpu_vm *vm,
        mutex_init(&vm->eviction_lock);
        vm->evicting = false;
 
-       amdgpu_vm_bo_param(adev, vm, adev->vm_manager.root_level, false, &bp);
-       if (vm_context == AMDGPU_VM_CONTEXT_COMPUTE)
-               bp.flags &= ~AMDGPU_GEM_CREATE_SHADOW;
-       r = amdgpu_bo_create(adev, &bp, &root);
+       r = amdgpu_vm_pt_create(adev, vm, adev->vm_manager.root_level,
+                               false, &root);
        if (r)
                goto error_free_delayed;
 
@@ -3349,6 +3360,7 @@ void amdgpu_vm_set_task_info(struct amdgpu_vm *vm)
 bool amdgpu_vm_handle_fault(struct amdgpu_device *adev, u32 pasid,
                            uint64_t addr)
 {
+       bool is_compute_context = false;
        struct amdgpu_bo *root;
        uint64_t value, flags;
        struct amdgpu_vm *vm;
@@ -3356,15 +3368,25 @@ bool amdgpu_vm_handle_fault(struct amdgpu_device *adev, u32 pasid,
 
        spin_lock(&adev->vm_manager.pasid_lock);
        vm = idr_find(&adev->vm_manager.pasid_idr, pasid);
-       if (vm)
+       if (vm) {
                root = amdgpu_bo_ref(vm->root.base.bo);
-       else
+               is_compute_context = vm->is_compute_context;
+       } else {
                root = NULL;
+       }
        spin_unlock(&adev->vm_manager.pasid_lock);
 
        if (!root)
                return false;
 
+       addr /= AMDGPU_GPU_PAGE_SIZE;
+
+       if (is_compute_context &&
+           !svm_range_restore_pages(adev, pasid, addr)) {
+               amdgpu_bo_unref(&root);
+               return true;
+       }
+
        r = amdgpu_bo_reserve(root, true);
        if (r)
                goto error_unref;
@@ -3378,18 +3400,16 @@ bool amdgpu_vm_handle_fault(struct amdgpu_device *adev, u32 pasid,
        if (!vm)
                goto error_unlock;
 
-       addr /= AMDGPU_GPU_PAGE_SIZE;
        flags = AMDGPU_PTE_VALID | AMDGPU_PTE_SNOOPED |
                AMDGPU_PTE_SYSTEM;
 
-       if (vm->is_compute_context) {
+       if (is_compute_context) {
                /* Intentionally setting invalid PTE flag
                 * combination to force a no-retry-fault
                 */
                flags = AMDGPU_PTE_EXECUTABLE | AMDGPU_PDE_PTE |
                        AMDGPU_PTE_TF;
                value = 0;
-
        } else if (amdgpu_vm_fault_stop == AMDGPU_VM_FAULT_STOP_NEVER) {
                /* Redirect the access to the dummy page */
                value = adev->dummy_page_addr;