Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

iommu/vt-d: dmar_fault should only clear PPF/PFO field.

When there is a dmar irq, dmar_fault is called and all of the fields
in FSTS are cleared. But ICE/IQE/ITE should not be cleared here,
they need to be processed and cleared in function qi_check_fault.

[Minor cleanup by Joerg Roedel]

Signed-off-by: Li, Zhen-Hua <zhen-hual@hp.com>
Signed-off-by: Joerg Roedel <joro@8bytes.org>

authored by

Li, Zhen-Hua and committed by
Joerg Roedel
bd5cdad0 8bb96604

+7 -5
+7 -5
drivers/iommu/dmar.c
··· 1204 1204 1205 1205 /* TBD: ignore advanced fault log currently */ 1206 1206 if (!(fault_status & DMA_FSTS_PPF)) 1207 - goto clear_rest; 1207 + goto unlock_exit; 1208 1208 1209 1209 fault_index = dma_fsts_fault_record_index(fault_status); 1210 1210 reg = cap_fault_reg_offset(iommu->cap); ··· 1245 1245 fault_index = 0; 1246 1246 raw_spin_lock_irqsave(&iommu->register_lock, flag); 1247 1247 } 1248 - clear_rest: 1249 - /* clear all the other faults */ 1250 - fault_status = readl(iommu->reg + DMAR_FSTS_REG); 1251 - writel(fault_status, iommu->reg + DMAR_FSTS_REG); 1252 1248 1249 + writel(DMA_FSTS_PFO | DMA_FSTS_PPF, iommu->reg + DMAR_FSTS_REG); 1250 + 1251 + unlock_exit: 1253 1252 raw_spin_unlock_irqrestore(&iommu->register_lock, flag); 1254 1253 return IRQ_HANDLED; 1255 1254 } ··· 1296 1297 for_each_drhd_unit(drhd) { 1297 1298 int ret; 1298 1299 struct intel_iommu *iommu = drhd->iommu; 1300 + u32 fault_status; 1299 1301 ret = dmar_set_interrupt(iommu); 1300 1302 1301 1303 if (ret) { ··· 1309 1309 * Clear any previous faults. 1310 1310 */ 1311 1311 dmar_fault(iommu->irq, iommu); 1312 + fault_status = readl(iommu->reg + DMAR_FSTS_REG); 1313 + writel(fault_status, iommu->reg + DMAR_FSTS_REG); 1312 1314 } 1313 1315 1314 1316 return 0;