diff options
Diffstat (limited to 'meta-amd-bsp/recipes-kernel/linux/linux-yocto-4.14.71/1826-drm-amdgpu-Add-PASID-management.patch')
-rw-r--r-- | meta-amd-bsp/recipes-kernel/linux/linux-yocto-4.14.71/1826-drm-amdgpu-Add-PASID-management.patch | 272 |
1 files changed, 272 insertions, 0 deletions
diff --git a/meta-amd-bsp/recipes-kernel/linux/linux-yocto-4.14.71/1826-drm-amdgpu-Add-PASID-management.patch b/meta-amd-bsp/recipes-kernel/linux/linux-yocto-4.14.71/1826-drm-amdgpu-Add-PASID-management.patch new file mode 100644 index 00000000..2b80ada7 --- /dev/null +++ b/meta-amd-bsp/recipes-kernel/linux/linux-yocto-4.14.71/1826-drm-amdgpu-Add-PASID-management.patch @@ -0,0 +1,272 @@ +From 670f96c2472dd566da7199af606ba1e4190a5126 Mon Sep 17 00:00:00 2001 +From: Felix Kuehling <Felix.Kuehling@amd.com> +Date: Fri, 25 Aug 2017 20:40:26 -0400 +Subject: [PATCH 1826/4131] drm/amdgpu: Add PASID management + +Allows assigning a PASID to a VM for identifying VMs involved in page +faults. The global PASID manager is also exported in the KFD +interface so that AMDGPU and KFD can share the PASID space. + +PASIDs of different sizes can be requested. On APUs, the PASID size +is deterined by the capabilities of the IOMMU. So KFD must be able +to allocate PASIDs in a smaller range. + +Signed-off-by: Felix Kuehling <Felix.Kuehling@amd.com> +Acked-by: Alex Deucher <alexander.deucher@amd.com> +Reviewed-by: Oded Gabbay <oded.gabbay@gmail.com> + + Conflicts: + drivers/gpu/drm/amd/amdgpu/amdgpu_amdkfd_gfx_v7.c + drivers/gpu/drm/amd/amdgpu/amdgpu_amdkfd_gfx_v8.c + drivers/gpu/drm/amd/amdgpu/amdgpu_vm.c + drivers/gpu/drm/amd/amdgpu/amdgpu_vm.h + drivers/gpu/drm/amd/include/kgd_kfd_interface.h + +Change-Id: I5b7c3832bd620655a67618bcf201feca1261ce44 +--- + drivers/gpu/drm/amd/amdgpu/amdgpu_amdkfd_gfx_v7.c | 2 + + drivers/gpu/drm/amd/amdgpu/amdgpu_amdkfd_gfx_v8.c | 2 + + drivers/gpu/drm/amd/amdgpu/amdgpu_kms.c | 2 +- + drivers/gpu/drm/amd/amdgpu/amdgpu_vm.c | 75 ++++++++++++++++++++++- + drivers/gpu/drm/amd/amdgpu/amdgpu_vm.h | 14 ++++- + drivers/gpu/drm/amd/include/kgd_kfd_interface.h | 6 ++ + 6 files changed, 97 insertions(+), 4 deletions(-) + +diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_amdkfd_gfx_v7.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_amdkfd_gfx_v7.c +index 66c79d7..d636861 100644 +--- a/drivers/gpu/drm/amd/amdgpu/amdgpu_amdkfd_gfx_v7.c ++++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_amdkfd_gfx_v7.c +@@ -193,6 +193,8 @@ static const struct kfd2kgd_calls kfd2kgd = { + .destroy_process_vm = amdgpu_amdkfd_gpuvm_destroy_process_vm, + .get_process_page_dir = amdgpu_amdkfd_gpuvm_get_process_page_dir, + .open_graphic_handle = open_graphic_handle, ++ .alloc_pasid = amdgpu_vm_alloc_pasid, ++ .free_pasid = amdgpu_vm_free_pasid, + .program_sh_mem_settings = kgd_program_sh_mem_settings, + .set_pasid_vmid_mapping = kgd_set_pasid_vmid_mapping, + .init_pipeline = kgd_init_pipeline, +diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_amdkfd_gfx_v8.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_amdkfd_gfx_v8.c +index 9d9965d..c08909c 100644 +--- a/drivers/gpu/drm/amd/amdgpu/amdgpu_amdkfd_gfx_v8.c ++++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_amdkfd_gfx_v8.c +@@ -167,6 +167,8 @@ static const struct kfd2kgd_calls kfd2kgd = { + .destroy_process_gpumem = destroy_process_gpumem, + .get_process_page_dir = amdgpu_amdkfd_gpuvm_get_process_page_dir, + .open_graphic_handle = open_graphic_handle, ++ .alloc_pasid = amdgpu_vm_alloc_pasid, ++ .free_pasid = amdgpu_vm_free_pasid, + .program_sh_mem_settings = kgd_program_sh_mem_settings, + .set_pasid_vmid_mapping = kgd_set_pasid_vmid_mapping, + .init_pipeline = kgd_init_pipeline, +diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_kms.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_kms.c +index fdb9d85..9f5a111 100644 +--- a/drivers/gpu/drm/amd/amdgpu/amdgpu_kms.c ++++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_kms.c +@@ -869,7 +869,7 @@ int amdgpu_driver_open_kms(struct drm_device *dev, struct drm_file *file_priv) + } + + r = amdgpu_vm_init(adev, &fpriv->vm, +- AMDGPU_VM_CONTEXT_GFX); ++ AMDGPU_VM_CONTEXT_GFX, 0); + if (r) { + kfree(fpriv); + goto out_suspend; +diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_vm.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_vm.c +index 65ab94d..b930ffa 100644 +--- a/drivers/gpu/drm/amd/amdgpu/amdgpu_vm.c ++++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_vm.c +@@ -33,12 +33,59 @@ + #if LINUX_VERSION_CODE >= KERNEL_VERSION(3, 7, 0) + #include <linux/interval_tree_generic.h> + #endif ++#include <linux/idr.h> + #include <drm/drmP.h> + #include <drm/amdgpu_drm.h> + #include "amdgpu.h" + #include "amdgpu_trace.h" + + /* ++ * PASID manager ++ * ++ * PASIDs are global address space identifiers that can be shared ++ * between the GPU, an IOMMU and the driver. VMs on different devices ++ * may use the same PASID if they share the same address ++ * space. Therefore PASIDs are allocated using a global IDA. VMs are ++ * looked up from the PASID per amdgpu_device. ++ */ ++static DEFINE_IDA(amdgpu_vm_pasid_ida); ++ ++/** ++ * amdgpu_vm_alloc_pasid - Allocate a PASID ++ * @bits: Maximum width of the PASID in bits, must be at least 1 ++ * ++ * Allocates a PASID of the given width while keeping smaller PASIDs ++ * available if possible. ++ * ++ * Returns a positive integer on success. Returns %-EINVAL if bits==0. ++ * Returns %-ENOSPC if no PASID was available. Returns %-ENOMEM on ++ * memory allocation failure. ++ */ ++int amdgpu_vm_alloc_pasid(unsigned int bits) ++{ ++ int pasid = -EINVAL; ++ ++ for (bits = min(bits, 31U); bits > 0; bits--) { ++ pasid = ida_simple_get(&amdgpu_vm_pasid_ida, ++ 1U << (bits - 1), 1U << bits, ++ GFP_KERNEL); ++ if (pasid != -ENOSPC) ++ break; ++ } ++ ++ return pasid; ++} ++ ++/** ++ * amdgpu_vm_free_pasid - Free a PASID ++ * @pasid: PASID to free ++ */ ++void amdgpu_vm_free_pasid(unsigned int pasid) ++{ ++ ida_simple_remove(&amdgpu_vm_pasid_ida, pasid); ++} ++ ++/* + * GPUVM + * GPUVM is similar to the legacy gart on older asics, however + * rather than there being a single global gart table +@@ -2556,7 +2603,7 @@ void amdgpu_vm_adjust_size(struct amdgpu_device *adev, uint64_t vm_size, uint32_ + * Init @vm fields. + */ + int amdgpu_vm_init(struct amdgpu_device *adev, struct amdgpu_vm *vm, +- int vm_context) ++ int vm_context, unsigned int pasid) + { + const unsigned align = min(AMDGPU_VM_PTB_ALIGN_SIZE, + AMDGPU_VM_PTE_COUNT(adev) * 8); +@@ -2654,6 +2701,19 @@ int amdgpu_vm_init(struct amdgpu_device *adev, struct amdgpu_vm *vm, + mutex_unlock(&id_mgr->lock); + } + ++ if (pasid) { ++ unsigned long flags; ++ ++ spin_lock_irqsave(&adev->vm_manager.pasid_lock, flags); ++ r = idr_alloc(&adev->vm_manager.pasid_idr, vm, pasid, pasid + 1, ++ GFP_ATOMIC); ++ spin_unlock_irqrestore(&adev->vm_manager.pasid_lock, flags); ++ if (r < 0) ++ goto error_free_root; ++ ++ vm->pasid = pasid; ++ } ++ + return 0; + + error_free_root: +@@ -2729,6 +2789,14 @@ void amdgpu_vm_fini(struct amdgpu_device *adev, struct amdgpu_vm *vm) + mutex_unlock(&id_mgr->lock); + } + ++ if (vm->pasid) { ++ unsigned long flags; ++ ++ spin_lock_irqsave(&adev->vm_manager.pasid_lock, flags); ++ idr_remove(&adev->vm_manager.pasid_idr, vm->pasid); ++ spin_unlock_irqrestore(&adev->vm_manager.pasid_lock, flags); ++ } ++ + amd_sched_entity_fini(vm->entity.sched, &vm->entity); + + if (!RB_EMPTY_ROOT(&vm->va)) { +@@ -2808,6 +2876,8 @@ void amdgpu_vm_manager_init(struct amdgpu_device *adev) + #endif + + adev->vm_manager.n_compute_vms = 0; ++ idr_init(&adev->vm_manager.pasid_idr); ++ spin_lock_init(&adev->vm_manager.pasid_lock); + } + + /** +@@ -2821,6 +2891,9 @@ void amdgpu_vm_manager_fini(struct amdgpu_device *adev) + { + unsigned i, j; + ++ WARN_ON(!idr_is_empty(&adev->vm_manager.pasid_idr)); ++ idr_destroy(&adev->vm_manager.pasid_idr); ++ + for (i = 0; i < AMDGPU_MAX_VMHUBS; ++i) { + struct amdgpu_vm_id_manager *id_mgr = + &adev->vm_manager.id_mgr[i]; +diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_vm.h b/drivers/gpu/drm/amd/amdgpu/amdgpu_vm.h +index 8792e86..8772ee7 100644 +--- a/drivers/gpu/drm/amd/amdgpu/amdgpu_vm.h ++++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_vm.h +@@ -25,6 +25,7 @@ + #define __AMDGPU_VM_H__ + + #include <linux/rbtree.h> ++#include <linux/idr.h> + + #include "gpu_scheduler.h" + #include "amdgpu_sync.h" +@@ -148,8 +149,9 @@ struct amdgpu_vm { + /* Scheduler entity for page table updates */ + struct amd_sched_entity entity; + +- /* client id */ ++ /* client id and PASID (TODO: replace client_id with PASID) */ + u64 client_id; ++ unsigned int pasid; + /* dedicated to vm */ + struct amdgpu_vm_id *reserved_vmid[AMDGPU_MAX_VMHUBS]; + +@@ -225,12 +227,20 @@ struct amdgpu_vm_manager { + int vm_update_mode; + /* Number of Compute VMs, used for detecting Compute activity */ + unsigned n_compute_vms; ++ ++ /* PASID to VM mapping, will be used in interrupt context to ++ * look up VM of a page fault ++ */ ++ struct idr pasid_idr; ++ spinlock_t pasid_lock; + }; + ++int amdgpu_vm_alloc_pasid(unsigned int bits); ++void amdgpu_vm_free_pasid(unsigned int pasid); + void amdgpu_vm_manager_init(struct amdgpu_device *adev); + void amdgpu_vm_manager_fini(struct amdgpu_device *adev); + int amdgpu_vm_init(struct amdgpu_device *adev, struct amdgpu_vm *vm, +- int vm_context); ++ int vm_context, unsigned int pasid); + void amdgpu_vm_fini(struct amdgpu_device *adev, struct amdgpu_vm *vm); + void amdgpu_vm_get_pd_bo(struct amdgpu_vm *vm, + struct list_head *validated, +diff --git a/drivers/gpu/drm/amd/include/kgd_kfd_interface.h b/drivers/gpu/drm/amd/include/kgd_kfd_interface.h +index ed60c5d..20e9369 100644 +--- a/drivers/gpu/drm/amd/include/kgd_kfd_interface.h ++++ b/drivers/gpu/drm/amd/include/kgd_kfd_interface.h +@@ -185,6 +185,9 @@ struct tile_config { + * + * @get_max_engine_clock_in_mhz: Retrieves maximum GPU clock in MHz + * ++ * @alloc_pasid: Allocate a PASID ++ * @free_pasid: Free a PASID ++ * + * @program_sh_mem_settings: A function that should initiate the memory + * properties such as main aperture memory type (cache / non cached) and + * secondary aperture base address, size and memory type. +@@ -273,6 +276,9 @@ struct kfd2kgd_calls { + + int (*open_graphic_handle)(struct kgd_dev *kgd, uint64_t va, void *vm, int fd, uint32_t handle, struct kgd_mem **mem); + ++ int (*alloc_pasid)(unsigned int bits); ++ void (*free_pasid)(unsigned int pasid); ++ + /* Register access functions */ + void (*program_sh_mem_settings)(struct kgd_dev *kgd, uint32_t vmid, + uint32_t sh_mem_config, uint32_t sh_mem_ape1_base, +-- +2.7.4 + |