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 | |
| 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>
| -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; |
