aboutsummaryrefslogtreecommitdiffstats
path: root/meta-amd-bsp/recipes-kernel/linux/linux-yocto-4.14.71/1826-drm-amdgpu-Add-PASID-management.patch
diff options
context:
space:
mode:
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.patch272
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
+