drm/amdgpu: move IV prescreening into the GMC code
authorChristian König <christian.koenig@amd.com>
Wed, 26 Sep 2018 09:50:09 +0000 (11:50 +0200)
committerAlex Deucher <alexander.deucher@amd.com>
Fri, 7 Dec 2018 23:14:26 +0000 (18:14 -0500)
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
drivers/gpu/drm/amd/amdgpu/amdgpu_irq.c
drivers/gpu/drm/amd/amdgpu/cik_ih.c
drivers/gpu/drm/amd/amdgpu/cz_ih.c
drivers/gpu/drm/amd/amdgpu/gmc_v9_0.c
drivers/gpu/drm/amd/amdgpu/iceland_ih.c
drivers/gpu/drm/amd/amdgpu/si_ih.c
drivers/gpu/drm/amd/amdgpu/tonga_ih.c
drivers/gpu/drm/amd/amdgpu/vega10_ih.c

index 9ce8c93ec19bf9422e8e1a8c9f60f1a58291bc87..f877bb78d10a31b11ebb9d8563d7b86055390966 100644 (file)
@@ -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))
 
index 79b6f456f2c576c13c089fda2aa5a1350ec8f0c9..b7968f4268625e99f7dc62fdddf3b44a896edae5 100644 (file)
@@ -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;
-
        entry.iv_entry = (const uint32_t *)&ih->ring[ring_index];
        amdgpu_ih_decode_iv(adev, &entry);
 
index 3e6c8c4067cb3adb15c934d7966fb8b04e3d0212..8a8b4967a101fca3b8daca0908ce39fc2247ae4b 100644 (file)
@@ -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
 };
index 447b3cbc47e5140f825899601607b77d9ceebc49..9d3ea298e116de7a0fa14e5858b50444ddd7dd46 100644 (file)
@@ -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
 };
index 016c7aab4a292e27ca4ef536b05f835bdd8b9123..ce150de723c98132511304944720629a8a9eb460 100644 (file)
@@ -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);
index 2b94a6d1550e5da00feb5888fb74945cea98cf8d..a3984d10b604e1a4127009bf63f57cf3a964da7e 100644 (file)
@@ -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
 };
index b3d7d9f83202d8a31379ef42288e2a2dc7f5f6af..2938fb9f17cc75c071ee0468434366fa68b39a4c 100644 (file)
@@ -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
 };
index 9d7b43da6acc228511263a8e43e0895fdb8e2409..15da06ddeb751d9f20e1a461d5a0e4276186a3dc 100644 (file)
@@ -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
 };
index b49290bcf10912f94a00d4bd2068a3f05d264c89..2c250b01a903eb62e6724384c4816a701f0eabe4 100644 (file)
@@ -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
 };