diff options
author | Li, Zhen-Hua <zhen-hual@hp.com> | 2013-03-25 04:20:52 -0400 |
---|---|---|
committer | Joerg Roedel <joro@8bytes.org> | 2013-03-26 12:17:54 -0400 |
commit | bd5cdad0c8e0f0adcd6e9c582abe4c4233c19b03 (patch) | |
tree | 978d99a04a9ee1be0cdcfb5f89da3a4169ee2379 /drivers/iommu | |
parent | 8bb9660418e05bb1845ac1a2428444d78e322cc7 (diff) |
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')
-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 e5cdaf87822c..9f8aa07360ba 100644 --- a/drivers/iommu/dmar.c +++ b/drivers/iommu/dmar.c | |||
@@ -1204,7 +1204,7 @@ irqreturn_t dmar_fault(int irq, void *dev_id) | |||
1204 | 1204 | ||
1205 | /* TBD: ignore advanced fault log currently */ | 1205 | /* TBD: ignore advanced fault log currently */ |
1206 | if (!(fault_status & DMA_FSTS_PPF)) | 1206 | if (!(fault_status & DMA_FSTS_PPF)) |
1207 | goto clear_rest; | 1207 | goto unlock_exit; |
1208 | 1208 | ||
1209 | fault_index = dma_fsts_fault_record_index(fault_status); | 1209 | fault_index = dma_fsts_fault_record_index(fault_status); |
1210 | reg = cap_fault_reg_offset(iommu->cap); | 1210 | reg = cap_fault_reg_offset(iommu->cap); |
@@ -1245,11 +1245,10 @@ irqreturn_t dmar_fault(int irq, void *dev_id) | |||
1245 | fault_index = 0; | 1245 | fault_index = 0; |
1246 | raw_spin_lock_irqsave(&iommu->register_lock, flag); | 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 | raw_spin_unlock_irqrestore(&iommu->register_lock, flag); | 1252 | raw_spin_unlock_irqrestore(&iommu->register_lock, flag); |
1254 | return IRQ_HANDLED; | 1253 | return IRQ_HANDLED; |
1255 | } | 1254 | } |
@@ -1297,6 +1296,7 @@ int __init enable_drhd_fault_handling(void) | |||
1297 | for_each_drhd_unit(drhd) { | 1296 | for_each_drhd_unit(drhd) { |
1298 | int ret; | 1297 | int ret; |
1299 | struct intel_iommu *iommu = drhd->iommu; | 1298 | struct intel_iommu *iommu = drhd->iommu; |
1299 | u32 fault_status; | ||
1300 | ret = dmar_set_interrupt(iommu); | 1300 | ret = dmar_set_interrupt(iommu); |
1301 | 1301 | ||
1302 | if (ret) { | 1302 | if (ret) { |
@@ -1309,6 +1309,8 @@ int __init enable_drhd_fault_handling(void) | |||
1309 | * Clear any previous faults. | 1309 | * Clear any previous faults. |
1310 | */ | 1310 | */ |
1311 | dmar_fault(iommu->irq, iommu); | 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 | return 0; | 1316 | return 0; |