}
 
        INIT_KFIFO(vm->faults);
+       vm->fault_credit = 16;
 
        return 0;
 
                amdgpu_vm_free_reserved_vmid(adev, vm, i);
 }
 
+/**
+ * amdgpu_vm_pasid_fault_credit - Check fault credit for given PASID
+ *
+ * @adev: amdgpu_device pointer
+ * @pasid: PASID do identify the VM
+ *
+ * This function is expected to be called in interrupt context. Returns
+ * true if there was fault credit, false otherwise
+ */
+bool amdgpu_vm_pasid_fault_credit(struct amdgpu_device *adev,
+                                 unsigned int pasid)
+{
+       struct amdgpu_vm *vm;
+
+       spin_lock(&adev->vm_manager.pasid_lock);
+       vm = idr_find(&adev->vm_manager.pasid_idr, pasid);
+       spin_unlock(&adev->vm_manager.pasid_lock);
+       if (!vm)
+               /* VM not found, can't track fault credit */
+               return true;
+
+       /* No lock needed. only accessed by IRQ handler */
+       if (!vm->fault_credit)
+               /* Too many faults in this VM */
+               return false;
+
+       vm->fault_credit--;
+       return true;
+}
+
 /**
  * amdgpu_vm_manager_init - init the VM manager
  *
 
        /* Flag to indicate ATS support from PTE for GFX9 */
        bool                    pte_support_ats;
 
-       /* Up to 128 pending page faults */
+       /* Up to 128 pending retry page faults */
        DECLARE_KFIFO(faults, u64, 128);
+
+       /* Limit non-retry fault storms */
+       unsigned int            fault_credit;
 };
 
 struct amdgpu_vm_id {
 int amdgpu_vm_init(struct amdgpu_device *adev, struct amdgpu_vm *vm,
                   int vm_context, unsigned int pasid);
 void amdgpu_vm_fini(struct amdgpu_device *adev, struct amdgpu_vm *vm);
+bool amdgpu_vm_pasid_fault_credit(struct amdgpu_device *adev,
+                                 unsigned int pasid);
 void amdgpu_vm_get_pd_bo(struct amdgpu_vm *vm,
                         struct list_head *validated,
                         struct amdgpu_bo_list_entry *entry);
 
  */
 static bool cik_ih_prescreen_iv(struct amdgpu_device *adev)
 {
-       /* Process all interrupts */
-       return true;
+       u32 ring_index = adev->irq.ih.rptr >> 2;
+       u16 pasid;
+
+       switch (le32_to_cpu(adev->irq.ih.ring[ring_index]) & 0xff) {
+       case 146:
+       case 147:
+               pasid = le32_to_cpu(adev->irq.ih.ring[ring_index + 2]) >> 16;
+               if (!pasid || amdgpu_vm_pasid_fault_credit(adev, pasid))
+                       return true;
+               break;
+       default:
+               /* Not a VM fault */
+               return true;
+       }
+
+       adev->irq.ih.rptr += 16;
+       return false;
 }
 
  /**
 
  */
 static bool cz_ih_prescreen_iv(struct amdgpu_device *adev)
 {
-       /* Process all interrupts */
-       return true;
+       u32 ring_index = adev->irq.ih.rptr >> 2;
+       u16 pasid;
+
+       switch (le32_to_cpu(adev->irq.ih.ring[ring_index]) & 0xff) {
+       case 146:
+       case 147:
+               pasid = le32_to_cpu(adev->irq.ih.ring[ring_index + 2]) >> 16;
+               if (!pasid || amdgpu_vm_pasid_fault_credit(adev, pasid))
+                       return true;
+               break;
+       default:
+               /* Not a VM fault */
+               return true;
+       }
+
+       adev->irq.ih.rptr += 16;
+       return false;
 }
 
 /**
 
  */
 static bool iceland_ih_prescreen_iv(struct amdgpu_device *adev)
 {
-       /* Process all interrupts */
-       return true;
+       u32 ring_index = adev->irq.ih.rptr >> 2;
+       u16 pasid;
+
+       switch (le32_to_cpu(adev->irq.ih.ring[ring_index]) & 0xff) {
+       case 146:
+       case 147:
+               pasid = le32_to_cpu(adev->irq.ih.ring[ring_index + 2]) >> 16;
+               if (!pasid || amdgpu_vm_pasid_fault_credit(adev, pasid))
+                       return true;
+               break;
+       default:
+               /* Not a VM fault */
+               return true;
+       }
+
+       adev->irq.ih.rptr += 16;
+       return false;
 }
 
 /**
 
  */
 static bool tonga_ih_prescreen_iv(struct amdgpu_device *adev)
 {
-       /* Process all interrupts */
-       return true;
+       u32 ring_index = adev->irq.ih.rptr >> 2;
+       u16 pasid;
+
+       switch (le32_to_cpu(adev->irq.ih.ring[ring_index]) & 0xff) {
+       case 146:
+       case 147:
+               pasid = le32_to_cpu(adev->irq.ih.ring[ring_index + 2]) >> 16;
+               if (!pasid || amdgpu_vm_pasid_fault_credit(adev, pasid))
+                       return true;
+               break;
+       default:
+               /* Not a VM fault */
+               return true;
+       }
+
+       adev->irq.ih.rptr += 16;
+       return false;
 }
 
 /**
 
                return true;
        }
 
-       /* Not a retry fault */
-       if (!(dw5 & 0x80))
-               return true;
-
        pasid = dw3 & 0xffff;
        /* No PASID, can't identify faulting process */
        if (!pasid)
                return true;
 
+       /* Not a retry fault, check fault credit */
+       if (!(dw5 & 0x80)) {
+               if (!amdgpu_vm_pasid_fault_credit(adev, pasid))
+                       goto ignore_iv;
+               return true;
+       }
+
        addr = ((u64)(dw5 & 0xf) << 44) | ((u64)dw4 << 12);
        key = AMDGPU_VM_FAULT(pasid, addr);
        r = amdgpu_ih_add_fault(adev, key);