summaryrefslogtreecommitdiff
path: root/drivers/iommu/dmar.c
diff options
context:
space:
mode:
authorTakao Indoh <indou.takao@jp.fujitsu.com>2013-04-23 17:35:03 +0900
committerBen Hutchings <ben@decadent.org.uk>2014-08-06 18:07:42 +0100
commit73f98b0930b1871bbf515aa4abc2484f2d5095b4 (patch)
tree8785d3e5edd65e33ec551dfd99dfb6cf65921d11 /drivers/iommu/dmar.c
parentdc79279294628d41b32e86b2e0e2a850ee67dd95 (diff)
iommu/vt-d: Disable translation if already enabled
commit 3a93c841c2b3b14824f7728dd74bd00a1cedb806 upstream. This patch disables translation(dma-remapping) before its initialization if it is already enabled. This is needed for kexec/kdump boot. If dma-remapping is enabled in the first kernel, it need to be disabled before initializing its page table during second kernel boot. Wei Hu also reported that this is needed when second kernel boots with intel_iommu=off. Basically iommu->gcmd is used to know whether translation is enabled or disabled, but it is always zero at boot time even when translation is enabled since iommu->gcmd is initialized without considering such a case. Therefor this patch synchronizes iommu->gcmd value with global command register when iommu structure is allocated. Signed-off-by: Takao Indoh <indou.takao@jp.fujitsu.com> Signed-off-by: Joerg Roedel <joro@8bytes.org> [wyj: Backported to 3.4: adjust context] Signed-off-by: Yijing Wang <wangyijing@huawei.com> Signed-off-by: Ben Hutchings <ben@decadent.org.uk>
Diffstat (limited to 'drivers/iommu/dmar.c')
-rw-r--r--drivers/iommu/dmar.c11
1 files changed, 10 insertions, 1 deletions
diff --git a/drivers/iommu/dmar.c b/drivers/iommu/dmar.c
index 97b2e21ac46a..cf065df9bb18 100644
--- a/drivers/iommu/dmar.c
+++ b/drivers/iommu/dmar.c
@@ -582,7 +582,7 @@ int alloc_iommu(struct dmar_drhd_unit *drhd)
{
struct intel_iommu *iommu;
int map_size;
- u32 ver;
+ u32 ver, sts;
static int iommu_allocated = 0;
int agaw = 0;
int msagaw = 0;
@@ -652,6 +652,15 @@ int alloc_iommu(struct dmar_drhd_unit *drhd)
(unsigned long long)iommu->cap,
(unsigned long long)iommu->ecap);
+ /* Reflect status in gcmd */
+ sts = readl(iommu->reg + DMAR_GSTS_REG);
+ if (sts & DMA_GSTS_IRES)
+ iommu->gcmd |= DMA_GCMD_IRE;
+ if (sts & DMA_GSTS_TES)
+ iommu->gcmd |= DMA_GCMD_TE;
+ if (sts & DMA_GSTS_QIES)
+ iommu->gcmd |= DMA_GCMD_QIE;
+
raw_spin_lock_init(&iommu->register_lock);
drhd->iommu = iommu;