diff options
author | Li, Zhen-Hua <zhen-hual@hp.com> | 2013-03-25 16:20:52 +0800 |
---|---|---|
committer | Joerg Roedel <joro@8bytes.org> | 2013-03-26 17:17:54 +0100 |
commit | bd5cdad0c8e0f0adcd6e9c582abe4c4233c19b03 (patch) | |
tree | 978d99a04a9ee1be0cdcfb5f89da3a4169ee2379 /drivers/iommu/dmar.c | |
parent | 8bb9660418e05bb1845ac1a2428444d78e322cc7 (diff) | |
download | op-kernel-dev-bd5cdad0c8e0f0adcd6e9c582abe4c4233c19b03.zip op-kernel-dev-bd5cdad0c8e0f0adcd6e9c582abe4c4233c19b03.tar.gz |
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>
Diffstat (limited to 'drivers/iommu/dmar.c')
-rw-r--r-- | drivers/iommu/dmar.c | 12 |
1 files changed, 7 insertions, 5 deletions
diff --git a/drivers/iommu/dmar.c b/drivers/iommu/dmar.c index e5cdaf8..9f8aa07 100644 --- a/drivers/iommu/dmar.c +++ b/drivers/iommu/dmar.c @@ -1204,7 +1204,7 @@ irqreturn_t dmar_fault(int irq, void *dev_id) /* TBD: ignore advanced fault log currently */ if (!(fault_status & DMA_FSTS_PPF)) - goto clear_rest; + goto unlock_exit; fault_index = dma_fsts_fault_record_index(fault_status); reg = cap_fault_reg_offset(iommu->cap); @@ -1245,11 +1245,10 @@ irqreturn_t dmar_fault(int irq, void *dev_id) fault_index = 0; raw_spin_lock_irqsave(&iommu->register_lock, flag); } -clear_rest: - /* clear all the other faults */ - fault_status = readl(iommu->reg + DMAR_FSTS_REG); - writel(fault_status, iommu->reg + DMAR_FSTS_REG); + writel(DMA_FSTS_PFO | DMA_FSTS_PPF, iommu->reg + DMAR_FSTS_REG); + +unlock_exit: raw_spin_unlock_irqrestore(&iommu->register_lock, flag); return IRQ_HANDLED; } @@ -1297,6 +1296,7 @@ int __init enable_drhd_fault_handling(void) for_each_drhd_unit(drhd) { int ret; struct intel_iommu *iommu = drhd->iommu; + u32 fault_status; ret = dmar_set_interrupt(iommu); if (ret) { @@ -1309,6 +1309,8 @@ int __init enable_drhd_fault_handling(void) * Clear any previous faults. */ dmar_fault(iommu->irq, iommu); + fault_status = readl(iommu->reg + DMAR_FSTS_REG); + writel(fault_status, iommu->reg + DMAR_FSTS_REG); } return 0; |