spin_lock(&iommu->lock);
        pte = intel_pasid_get_entry(dev, pasid);
-       if (WARN_ON(!pte) || !pasid_pte_is_present(pte)) {
+       if (WARN_ON(!pte)) {
                spin_unlock(&iommu->lock);
                return;
        }
 
+       if (!pasid_pte_is_present(pte)) {
+               if (!pasid_pte_is_fault_disabled(pte)) {
+                       WARN_ON(READ_ONCE(pte->val[0]) != 0);
+                       spin_unlock(&iommu->lock);
+                       return;
+               }
+
+               /*
+                * When a PASID is used for SVA by a device, it's possible
+                * that the pasid entry is non-present with the Fault
+                * Processing Disabled bit set. Clear the pasid entry and
+                * drain the PRQ for the PASID before return.
+                */
+               pasid_clear_entry(pte);
+               spin_unlock(&iommu->lock);
+               intel_iommu_drain_pasid_prq(dev, pasid);
+
+               return;
+       }
+
        did = pasid_get_domain_id(pte);
        pgtt = pasid_pte_get_pgtt(pte);
        intel_pasid_clear_entry(dev, pasid, fault_ignore);
 
        return READ_ONCE(pte->val[0]) & PASID_PTE_PRESENT;
 }
 
+/* Get FPD(Fault Processing Disable) bit of a PASID table entry */
+static inline bool pasid_pte_is_fault_disabled(struct pasid_entry *pte)
+{
+       return READ_ONCE(pte->val[0]) & PASID_PTE_FPD;
+}
+
 /* Get PGTT field of a PASID table entry */
 static inline u16 pasid_pte_get_pgtt(struct pasid_entry *pte)
 {