ia64/xen-unstable

diff xen/drivers/passthrough/vtd/intremap.c @ 19734:4fb8a6c993e2

VT-d: correct way to submit command to GCMD register

Per VT-d spec, software should submit only one "incremental" command
at a time to Global Command reigster. Current implementation uses a
variable (gcmd) to record the state of Global Status register. It's
error prone.

Signed-off-by: Weidong Han <weidong.han@intel.com>
author Keir Fraser <keir.fraser@citrix.com>
date Fri Jun 05 09:29:42 2009 +0100 (2009-06-05)
parents a69daf23602a
children fa51db0871e1
line diff
     1.1 --- a/xen/drivers/passthrough/vtd/intremap.c	Fri Jun 05 09:27:18 2009 +0100
     1.2 +++ b/xen/drivers/passthrough/vtd/intremap.c	Fri Jun 05 09:29:42 2009 +0100
     1.3 @@ -534,7 +534,7 @@ void msi_msg_write_remap_rte(
     1.4  int enable_intremap(struct iommu *iommu)
     1.5  {
     1.6      struct ir_ctrl *ir_ctrl;
     1.7 -    u32 sts;
     1.8 +    u32 sts, gcmd;
     1.9  
    1.10      ASSERT(ecap_intr_remap(iommu->ecap) && iommu_intremap);
    1.11  
    1.12 @@ -561,22 +561,23 @@ int enable_intremap(struct iommu *iommu)
    1.13      dmar_writeq(iommu->reg, DMAR_IRTA_REG, ir_ctrl->iremap_maddr);
    1.14  
    1.15      /* set SIRTP */
    1.16 -    iommu->gcmd |= DMA_GCMD_SIRTP;
    1.17 -    dmar_writel(iommu->reg, DMAR_GCMD_REG, iommu->gcmd);
    1.18 +    gcmd = dmar_readl(iommu->reg, DMAR_GSTS_REG);
    1.19 +    gcmd |= DMA_GCMD_SIRTP;
    1.20 +    dmar_writel(iommu->reg, DMAR_GCMD_REG, gcmd);
    1.21  
    1.22      IOMMU_WAIT_OP(iommu, DMAR_GSTS_REG, dmar_readl,
    1.23                    (sts & DMA_GSTS_SIRTPS), sts);
    1.24   
    1.25      /* enable comaptiblity format interrupt pass through */
    1.26 -    iommu->gcmd |= DMA_GCMD_CFI;
    1.27 -    dmar_writel(iommu->reg, DMAR_GCMD_REG, iommu->gcmd);
    1.28 +    gcmd |= DMA_GCMD_CFI;
    1.29 +    dmar_writel(iommu->reg, DMAR_GCMD_REG, gcmd);
    1.30  
    1.31      IOMMU_WAIT_OP(iommu, DMAR_GSTS_REG, dmar_readl,
    1.32                    (sts & DMA_GSTS_CFIS), sts);
    1.33  
    1.34      /* enable interrupt remapping hardware */
    1.35 -    iommu->gcmd |= DMA_GCMD_IRE;
    1.36 -    dmar_writel(iommu->reg, DMAR_GCMD_REG, iommu->gcmd);
    1.37 +    gcmd |= DMA_GCMD_IRE;
    1.38 +    dmar_writel(iommu->reg, DMAR_GCMD_REG, gcmd);
    1.39  
    1.40      IOMMU_WAIT_OP(iommu, DMAR_GSTS_REG, dmar_readl,
    1.41                    (sts & DMA_GSTS_IRES), sts);
    1.42 @@ -593,8 +594,8 @@ void disable_intremap(struct iommu *iomm
    1.43  
    1.44      ASSERT(ecap_intr_remap(iommu->ecap) && iommu_intremap);
    1.45  
    1.46 -    iommu->gcmd &= ~(DMA_GCMD_SIRTP | DMA_GCMD_CFI | DMA_GCMD_IRE);
    1.47 -    dmar_writel(iommu->reg, DMAR_GCMD_REG, iommu->gcmd);
    1.48 +    sts = dmar_readl(iommu->reg, DMAR_GSTS_REG);
    1.49 +    dmar_writel(iommu->reg, DMAR_GCMD_REG, sts & (~DMA_GCMD_IRE));
    1.50  
    1.51      IOMMU_WAIT_OP(iommu, DMAR_GSTS_REG, dmar_readl,
    1.52                    !(sts & DMA_GSTS_IRES), sts);