Commit d25e35bc authored by Ramesh Errabolu's avatar Ramesh Errabolu Committed by Alex Deucher
Browse files

drm/amdgpu: Pin MMIO/DOORBELL BO's in GTT domain



MMIO/DOORBELL BOs encode control data and should be pinned in GTT
domain before enabling PCIe connected peer devices in accessing it

Signed-off-by: default avatarRamesh Errabolu <Ramesh.Errabolu@amd.com>
Reviewed-by: default avatarFelix Kuehling <Felix.Kuehling@amd.com>
Signed-off-by: default avatarAlex Deucher <alexander.deucher@amd.com>
parent f441dd33
Loading
Loading
Loading
Loading
+69 −0
Original line number Diff line number Diff line
@@ -1295,6 +1295,55 @@ static int init_kfd_vm(struct amdgpu_vm *vm, void **process_info,
	return ret;
}

/**
 * amdgpu_amdkfd_gpuvm_pin_bo() - Pins a BO using following criteria
 * @bo: Handle of buffer object being pinned
 * @domain: Domain into which BO should be pinned
 *
 *   - USERPTR BOs are UNPINNABLE and will return error
 *   - All other BO types (GTT, VRAM, MMIO and DOORBELL) will have their
 *     PIN count incremented. It is valid to PIN a BO multiple times
 *
 * Return: ZERO if successful in pinning, Non-Zero in case of error.
 */
static int amdgpu_amdkfd_gpuvm_pin_bo(struct amdgpu_bo *bo, u32 domain)
{
	int ret = 0;

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

	ret = amdgpu_bo_pin_restricted(bo, domain, 0, 0);
	if (ret)
		pr_err("Error in Pinning BO to domain: %d\n", domain);

	amdgpu_bo_sync_wait(bo, AMDGPU_FENCE_OWNER_KFD, false);
	amdgpu_bo_unreserve(bo);

	return ret;
}

/**
 * amdgpu_amdkfd_gpuvm_unpin_bo() - Unpins BO using following criteria
 * @bo: Handle of buffer object being unpinned
 *
 *   - Is a illegal request for USERPTR BOs and is ignored
 *   - All other BO types (GTT, VRAM, MMIO and DOORBELL) will have their
 *     PIN count decremented. Calls to UNPIN must balance calls to PIN
 */
void amdgpu_amdkfd_gpuvm_unpin_bo(struct amdgpu_bo *bo)
{
	int ret = 0;

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

	amdgpu_bo_unpin(bo);
	amdgpu_bo_unreserve(bo);
}

int amdgpu_amdkfd_gpuvm_acquire_process_vm(struct amdgpu_device *adev,
					   struct file *filp, u32 pasid,
					   void **process_info,
@@ -1521,10 +1570,22 @@ int amdgpu_amdkfd_gpuvm_alloc_memory_of_gpu(
	if (offset)
		*offset = amdgpu_bo_mmap_offset(bo);

	if (flags & (KFD_IOC_ALLOC_MEM_FLAGS_DOORBELL |
			KFD_IOC_ALLOC_MEM_FLAGS_MMIO_REMAP)) {
		ret = amdgpu_amdkfd_gpuvm_pin_bo(bo, AMDGPU_GEM_DOMAIN_GTT);
		if (ret) {
			pr_err("Pinning MMIO/DOORBELL BO during ALLOC FAILED\n");
			goto err_pin_bo;
		}
		bo->allowed_domains = AMDGPU_GEM_DOMAIN_GTT;
		bo->preferred_domains = AMDGPU_GEM_DOMAIN_GTT;
	}

	return 0;

allocate_init_user_pages_failed:
	remove_kgd_mem_from_kfd_bo_list(*mem, avm->process_info);
err_pin_bo:
	drm_vma_node_revoke(&gobj->vma_node, drm_priv);
err_node_allow:
	drm_gem_object_put(gobj);
@@ -1557,6 +1618,14 @@ int amdgpu_amdkfd_gpuvm_free_memory_of_gpu(
	bool is_imported = false;

	mutex_lock(&mem->lock);

	/* Unpin MMIO/DOORBELL BO's that were pinnned during allocation */
	if (mem->alloc_flags &
	    (KFD_IOC_ALLOC_MEM_FLAGS_DOORBELL |
	     KFD_IOC_ALLOC_MEM_FLAGS_MMIO_REMAP)) {
		amdgpu_amdkfd_gpuvm_unpin_bo(mem->bo);
	}

	mapped_to_gpu_memory = mem->mapped_to_gpu_memory;
	is_imported = mem->is_imported;
	mutex_unlock(&mem->lock);