diff options
Diffstat (limited to 'common/recipes-kernel/linux/linux-yocto-4.19.8/0923-drm-amdgpu-move-IV-prescreening-into-the-GMC-code.patch')
-rw-r--r-- | common/recipes-kernel/linux/linux-yocto-4.19.8/0923-drm-amdgpu-move-IV-prescreening-into-the-GMC-code.patch | 397 |
1 files changed, 397 insertions, 0 deletions
diff --git a/common/recipes-kernel/linux/linux-yocto-4.19.8/0923-drm-amdgpu-move-IV-prescreening-into-the-GMC-code.patch b/common/recipes-kernel/linux/linux-yocto-4.19.8/0923-drm-amdgpu-move-IV-prescreening-into-the-GMC-code.patch new file mode 100644 index 00000000..a32c2d61 --- /dev/null +++ b/common/recipes-kernel/linux/linux-yocto-4.19.8/0923-drm-amdgpu-move-IV-prescreening-into-the-GMC-code.patch @@ -0,0 +1,397 @@ +From 6d0a0747e877b9493cd60d01af13d053fa182824 Mon Sep 17 00:00:00 2001 +From: =?UTF-8?q?Christian=20K=C3=B6nig?= <christian.koenig@amd.com> +Date: Wed, 26 Sep 2018 11:50:09 +0200 +Subject: [PATCH 0923/2940] drm/amdgpu: move IV prescreening into the GMC code +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit + +The GMC/VM subsystem is causing the faults, so move the handling here as +well. + +Signed-off-by: Christian König <christian.koenig@amd.com> +Reviewed-by: Felix Kuehling <Felix.Kuehling@amd.com> +Acked-by: Alex Deucher <alexander.deucher@amd.com> +Signed-off-by: Alex Deucher <alexander.deucher@amd.com> +--- + drivers/gpu/drm/amd/amdgpu/amdgpu_ih.h | 2 - + drivers/gpu/drm/amd/amdgpu/amdgpu_irq.c | 4 -- + drivers/gpu/drm/amd/amdgpu/cik_ih.c | 13 ---- + drivers/gpu/drm/amd/amdgpu/cz_ih.c | 13 ---- + drivers/gpu/drm/amd/amdgpu/gmc_v9_0.c | 59 ++++++++++++++++++ + drivers/gpu/drm/amd/amdgpu/iceland_ih.c | 13 ---- + drivers/gpu/drm/amd/amdgpu/si_ih.c | 14 ----- + drivers/gpu/drm/amd/amdgpu/tonga_ih.c | 13 ---- + drivers/gpu/drm/amd/amdgpu/vega10_ih.c | 82 ------------------------- + 9 files changed, 59 insertions(+), 154 deletions(-) + +diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_ih.h b/drivers/gpu/drm/amd/amdgpu/amdgpu_ih.h +index 9ce8c93ec19b..f877bb78d10a 100644 +--- a/drivers/gpu/drm/amd/amdgpu/amdgpu_ih.h ++++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_ih.h +@@ -51,14 +51,12 @@ struct amdgpu_ih_ring { + struct amdgpu_ih_funcs { + /* ring read/write ptr handling, called from interrupt context */ + u32 (*get_wptr)(struct amdgpu_device *adev); +- bool (*prescreen_iv)(struct amdgpu_device *adev); + void (*decode_iv)(struct amdgpu_device *adev, + struct amdgpu_iv_entry *entry); + void (*set_rptr)(struct amdgpu_device *adev); + }; + + #define amdgpu_ih_get_wptr(adev) (adev)->irq.ih_funcs->get_wptr((adev)) +-#define amdgpu_ih_prescreen_iv(adev) (adev)->irq.ih_funcs->prescreen_iv((adev)) + #define amdgpu_ih_decode_iv(adev, iv) (adev)->irq.ih_funcs->decode_iv((adev), (iv)) + #define amdgpu_ih_set_rptr(adev) (adev)->irq.ih_funcs->set_rptr((adev)) + +diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_irq.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_irq.c +index 6b6524f04ce0..4590c7042ba7 100644 +--- a/drivers/gpu/drm/amd/amdgpu/amdgpu_irq.c ++++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_irq.c +@@ -145,10 +145,6 @@ static void amdgpu_irq_callback(struct amdgpu_device *adev, + u32 ring_index = ih->rptr >> 2; + struct amdgpu_iv_entry entry; + +- /* Prescreening of high-frequency interrupts */ +- if (!amdgpu_ih_prescreen_iv(adev)) +- return; +- + /* Before dispatching irq to IP blocks, send it to amdkfd */ + amdgpu_amdkfd_interrupt(adev, (const void *) &ih->ring[ring_index]); + +diff --git a/drivers/gpu/drm/amd/amdgpu/cik_ih.c b/drivers/gpu/drm/amd/amdgpu/cik_ih.c +index 3e6c8c4067cb..8a8b4967a101 100644 +--- a/drivers/gpu/drm/amd/amdgpu/cik_ih.c ++++ b/drivers/gpu/drm/amd/amdgpu/cik_ih.c +@@ -228,18 +228,6 @@ static u32 cik_ih_get_wptr(struct amdgpu_device *adev) + * [127:96] - reserved + */ + +-/** +- * cik_ih_prescreen_iv - prescreen an interrupt vector +- * +- * @adev: amdgpu_device pointer +- * +- * Returns true if the interrupt vector should be further processed. +- */ +-static bool cik_ih_prescreen_iv(struct amdgpu_device *adev) +-{ +- return true; +-} +- + /** + * cik_ih_decode_iv - decode an interrupt vector + * +@@ -445,7 +433,6 @@ static const struct amd_ip_funcs cik_ih_ip_funcs = { + + static const struct amdgpu_ih_funcs cik_ih_funcs = { + .get_wptr = cik_ih_get_wptr, +- .prescreen_iv = cik_ih_prescreen_iv, + .decode_iv = cik_ih_decode_iv, + .set_rptr = cik_ih_set_rptr + }; +diff --git a/drivers/gpu/drm/amd/amdgpu/cz_ih.c b/drivers/gpu/drm/amd/amdgpu/cz_ih.c +index 447b3cbc47e5..9d3ea298e116 100644 +--- a/drivers/gpu/drm/amd/amdgpu/cz_ih.c ++++ b/drivers/gpu/drm/amd/amdgpu/cz_ih.c +@@ -207,18 +207,6 @@ static u32 cz_ih_get_wptr(struct amdgpu_device *adev) + return (wptr & adev->irq.ih.ptr_mask); + } + +-/** +- * cz_ih_prescreen_iv - prescreen an interrupt vector +- * +- * @adev: amdgpu_device pointer +- * +- * Returns true if the interrupt vector should be further processed. +- */ +-static bool cz_ih_prescreen_iv(struct amdgpu_device *adev) +-{ +- return true; +-} +- + /** + * cz_ih_decode_iv - decode an interrupt vector + * +@@ -426,7 +414,6 @@ static const struct amd_ip_funcs cz_ih_ip_funcs = { + + static const struct amdgpu_ih_funcs cz_ih_funcs = { + .get_wptr = cz_ih_get_wptr, +- .prescreen_iv = cz_ih_prescreen_iv, + .decode_iv = cz_ih_decode_iv, + .set_rptr = cz_ih_set_rptr + }; +diff --git a/drivers/gpu/drm/amd/amdgpu/gmc_v9_0.c b/drivers/gpu/drm/amd/amdgpu/gmc_v9_0.c +index 3014d50855b1..286e2cdc7de7 100644 +--- a/drivers/gpu/drm/amd/amdgpu/gmc_v9_0.c ++++ b/drivers/gpu/drm/amd/amdgpu/gmc_v9_0.c +@@ -244,6 +244,62 @@ static int gmc_v9_0_vm_fault_interrupt_state(struct amdgpu_device *adev, + return 0; + } + ++/** ++ * vega10_ih_prescreen_iv - prescreen an interrupt vector ++ * ++ * @adev: amdgpu_device pointer ++ * ++ * Returns true if the interrupt vector should be further processed. ++ */ ++static bool gmc_v9_0_prescreen_iv(struct amdgpu_device *adev, ++ struct amdgpu_iv_entry *entry, ++ uint64_t addr) ++{ ++ struct amdgpu_vm *vm; ++ u64 key; ++ int r; ++ ++ /* No PASID, can't identify faulting process */ ++ if (!entry->pasid) ++ return true; ++ ++ /* Not a retry fault */ ++ if (!(entry->src_data[1] & 0x80)) ++ return true; ++ ++ /* Track retry faults in per-VM fault FIFO. */ ++ spin_lock(&adev->vm_manager.pasid_lock); ++ vm = idr_find(&adev->vm_manager.pasid_idr, entry->pasid); ++ if (!vm) { ++ /* VM not found, process it normally */ ++ spin_unlock(&adev->vm_manager.pasid_lock); ++ return true; ++ } ++ ++ key = AMDGPU_VM_FAULT(entry->pasid, addr); ++ r = amdgpu_vm_add_fault(vm->fault_hash, key); ++ ++ /* Hash table is full or the fault is already being processed, ++ * ignore further page faults ++ */ ++ if (r != 0) { ++ spin_unlock(&adev->vm_manager.pasid_lock); ++ return false; ++ } ++ /* No locking required with single writer and single reader */ ++ r = kfifo_put(&vm->faults, key); ++ if (!r) { ++ /* FIFO is full. Ignore it until there is space */ ++ amdgpu_vm_clear_fault(vm->fault_hash, key); ++ spin_unlock(&adev->vm_manager.pasid_lock); ++ return false; ++ } ++ ++ spin_unlock(&adev->vm_manager.pasid_lock); ++ /* It's the first fault for this address, process it normally */ ++ return true; ++} ++ + static int gmc_v9_0_process_interrupt(struct amdgpu_device *adev, + struct amdgpu_irq_src *source, + struct amdgpu_iv_entry *entry) +@@ -255,6 +311,9 @@ static int gmc_v9_0_process_interrupt(struct amdgpu_device *adev, + addr = (u64)entry->src_data[0] << 12; + addr |= ((u64)entry->src_data[1] & 0xf) << 44; + ++ if (!gmc_v9_0_prescreen_iv(adev, entry, addr)) ++ return 1; /* This also prevents sending it to KFD */ ++ + if (!amdgpu_sriov_vf(adev)) { + status = RREG32(hub->vm_l2_pro_fault_status); + WREG32_P(hub->vm_l2_pro_fault_cntl, 1, ~1); +diff --git a/drivers/gpu/drm/amd/amdgpu/iceland_ih.c b/drivers/gpu/drm/amd/amdgpu/iceland_ih.c +index 2b94a6d1550e..a3984d10b604 100644 +--- a/drivers/gpu/drm/amd/amdgpu/iceland_ih.c ++++ b/drivers/gpu/drm/amd/amdgpu/iceland_ih.c +@@ -207,18 +207,6 @@ static u32 iceland_ih_get_wptr(struct amdgpu_device *adev) + return (wptr & adev->irq.ih.ptr_mask); + } + +-/** +- * iceland_ih_prescreen_iv - prescreen an interrupt vector +- * +- * @adev: amdgpu_device pointer +- * +- * Returns true if the interrupt vector should be further processed. +- */ +-static bool iceland_ih_prescreen_iv(struct amdgpu_device *adev) +-{ +- return true; +-} +- + /** + * iceland_ih_decode_iv - decode an interrupt vector + * +@@ -424,7 +412,6 @@ static const struct amd_ip_funcs iceland_ih_ip_funcs = { + + static const struct amdgpu_ih_funcs iceland_ih_funcs = { + .get_wptr = iceland_ih_get_wptr, +- .prescreen_iv = iceland_ih_prescreen_iv, + .decode_iv = iceland_ih_decode_iv, + .set_rptr = iceland_ih_set_rptr + }; +diff --git a/drivers/gpu/drm/amd/amdgpu/si_ih.c b/drivers/gpu/drm/amd/amdgpu/si_ih.c +index b3d7d9f83202..2938fb9f17cc 100644 +--- a/drivers/gpu/drm/amd/amdgpu/si_ih.c ++++ b/drivers/gpu/drm/amd/amdgpu/si_ih.c +@@ -118,19 +118,6 @@ static u32 si_ih_get_wptr(struct amdgpu_device *adev) + return (wptr & adev->irq.ih.ptr_mask); + } + +-/** +- * si_ih_prescreen_iv - prescreen an interrupt vector +- * +- * @adev: amdgpu_device pointer +- * +- * Returns true if the interrupt vector should be further processed. +- */ +-static bool si_ih_prescreen_iv(struct amdgpu_device *adev) +-{ +- /* Process all interrupts */ +- return true; +-} +- + static void si_ih_decode_iv(struct amdgpu_device *adev, + struct amdgpu_iv_entry *entry) + { +@@ -301,7 +288,6 @@ static const struct amd_ip_funcs si_ih_ip_funcs = { + + static const struct amdgpu_ih_funcs si_ih_funcs = { + .get_wptr = si_ih_get_wptr, +- .prescreen_iv = si_ih_prescreen_iv, + .decode_iv = si_ih_decode_iv, + .set_rptr = si_ih_set_rptr + }; +diff --git a/drivers/gpu/drm/amd/amdgpu/tonga_ih.c b/drivers/gpu/drm/amd/amdgpu/tonga_ih.c +index 9d7b43da6acc..15da06ddeb75 100644 +--- a/drivers/gpu/drm/amd/amdgpu/tonga_ih.c ++++ b/drivers/gpu/drm/amd/amdgpu/tonga_ih.c +@@ -218,18 +218,6 @@ static u32 tonga_ih_get_wptr(struct amdgpu_device *adev) + return (wptr & adev->irq.ih.ptr_mask); + } + +-/** +- * tonga_ih_prescreen_iv - prescreen an interrupt vector +- * +- * @adev: amdgpu_device pointer +- * +- * Returns true if the interrupt vector should be further processed. +- */ +-static bool tonga_ih_prescreen_iv(struct amdgpu_device *adev) +-{ +- return true; +-} +- + /** + * tonga_ih_decode_iv - decode an interrupt vector + * +@@ -490,7 +478,6 @@ static const struct amd_ip_funcs tonga_ih_ip_funcs = { + + static const struct amdgpu_ih_funcs tonga_ih_funcs = { + .get_wptr = tonga_ih_get_wptr, +- .prescreen_iv = tonga_ih_prescreen_iv, + .decode_iv = tonga_ih_decode_iv, + .set_rptr = tonga_ih_set_rptr + }; +diff --git a/drivers/gpu/drm/amd/amdgpu/vega10_ih.c b/drivers/gpu/drm/amd/amdgpu/vega10_ih.c +index f0814a8ccb1c..2c250b01a903 100644 +--- a/drivers/gpu/drm/amd/amdgpu/vega10_ih.c ++++ b/drivers/gpu/drm/amd/amdgpu/vega10_ih.c +@@ -219,87 +219,6 @@ static u32 vega10_ih_get_wptr(struct amdgpu_device *adev) + return (wptr & adev->irq.ih.ptr_mask); + } + +-/** +- * vega10_ih_prescreen_iv - prescreen an interrupt vector +- * +- * @adev: amdgpu_device pointer +- * +- * Returns true if the interrupt vector should be further processed. +- */ +-static bool vega10_ih_prescreen_iv(struct amdgpu_device *adev) +-{ +- u32 ring_index = adev->irq.ih.rptr >> 2; +- u32 dw0, dw3, dw4, dw5; +- u16 pasid; +- u64 addr, key; +- struct amdgpu_vm *vm; +- int r; +- +- dw0 = le32_to_cpu(adev->irq.ih.ring[ring_index + 0]); +- dw3 = le32_to_cpu(adev->irq.ih.ring[ring_index + 3]); +- dw4 = le32_to_cpu(adev->irq.ih.ring[ring_index + 4]); +- dw5 = le32_to_cpu(adev->irq.ih.ring[ring_index + 5]); +- +- /* Filter retry page faults, let only the first one pass. If +- * there are too many outstanding faults, ignore them until +- * some faults get cleared. +- */ +- switch (dw0 & 0xff) { +- case SOC15_IH_CLIENTID_VMC: +- case SOC15_IH_CLIENTID_UTCL2: +- break; +- default: +- /* Not a VM fault */ +- return true; +- } +- +- pasid = dw3 & 0xffff; +- /* No PASID, can't identify faulting process */ +- if (!pasid) +- return true; +- +- /* Not a retry fault */ +- if (!(dw5 & 0x80)) +- return true; +- +- /* Track retry faults in per-VM fault FIFO. */ +- spin_lock(&adev->vm_manager.pasid_lock); +- vm = idr_find(&adev->vm_manager.pasid_idr, pasid); +- addr = ((u64)(dw5 & 0xf) << 44) | ((u64)dw4 << 12); +- key = AMDGPU_VM_FAULT(pasid, addr); +- if (!vm) { +- /* VM not found, process it normally */ +- spin_unlock(&adev->vm_manager.pasid_lock); +- return true; +- } else { +- r = amdgpu_vm_add_fault(vm->fault_hash, key); +- +- /* Hash table is full or the fault is already being processed, +- * ignore further page faults +- */ +- if (r != 0) { +- spin_unlock(&adev->vm_manager.pasid_lock); +- goto ignore_iv; +- } +- } +- /* No locking required with single writer and single reader */ +- r = kfifo_put(&vm->faults, key); +- if (!r) { +- /* FIFO is full. Ignore it until there is space */ +- amdgpu_vm_clear_fault(vm->fault_hash, key); +- spin_unlock(&adev->vm_manager.pasid_lock); +- goto ignore_iv; +- } +- +- spin_unlock(&adev->vm_manager.pasid_lock); +- /* It's the first fault for this address, process it normally */ +- return true; +- +-ignore_iv: +- adev->irq.ih.rptr += 32; +- return false; +-} +- + /** + * vega10_ih_decode_iv - decode an interrupt vector + * +@@ -484,7 +403,6 @@ const struct amd_ip_funcs vega10_ih_ip_funcs = { + + static const struct amdgpu_ih_funcs vega10_ih_funcs = { + .get_wptr = vega10_ih_get_wptr, +- .prescreen_iv = vega10_ih_prescreen_iv, + .decode_iv = vega10_ih_decode_iv, + .set_rptr = vega10_ih_set_rptr + }; +-- +2.17.1 + |