[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

[Xen-changelog] [xen-unstable] VT-d: define a macro for waiting hardare completion



# HG changeset patch
# User Keir Fraser <keir.fraser@xxxxxxxxxx>
# Date 1244190438 -3600
# Node ID a69daf23602a8b7f41a7dc304c7050def59597c7
# Parent  931dbe86e5f37d5eb89e7383098f04b934475c48
VT-d: define a macro for waiting hardare completion

When set some registers of VT-d, it must wait for hardware
completion. There are lots of duplicated code to do that. This patch
defines a macro for it, thus it is much cleaner.

Signed-off-by: Weidong Han <weidong.han@xxxxxxxxx>
---
 xen/drivers/passthrough/vtd/dmar.h     |   14 +++++
 xen/drivers/passthrough/vtd/intremap.c |   45 ++++------------
 xen/drivers/passthrough/vtd/iommu.c    |   88 +++++----------------------------
 xen/drivers/passthrough/vtd/qinval.c   |   24 ++-------
 xen/drivers/passthrough/vtd/utils.c    |   19 +------
 5 files changed, 52 insertions(+), 138 deletions(-)

diff -r 931dbe86e5f3 -r a69daf23602a xen/drivers/passthrough/vtd/dmar.h
--- a/xen/drivers/passthrough/vtd/dmar.h        Fri Jun 05 09:26:39 2009 +0100
+++ b/xen/drivers/passthrough/vtd/dmar.h        Fri Jun 05 09:27:18 2009 +0100
@@ -90,6 +90,20 @@ void dmar_scope_remove_buses(struct dmar
 
 #define DMAR_OPERATION_TIMEOUT MILLISECS(1000)
 
+#define IOMMU_WAIT_OP(iommu, offset, op, cond, sts) \
+do {                                                \
+    s_time_t start_time = NOW();                    \
+    while (1) {                                     \
+        sts = op(iommu->reg, offset);               \
+        if ( cond )                                 \
+            break;                                  \
+        if ( NOW() > start_time + DMAR_OPERATION_TIMEOUT )      \
+            panic("%s:%d:%s: DMAR hardware is malfunctional\n", \
+                  __FILE__, __LINE__, __func__);                \
+        cpu_relax();                                            \
+    }                                                           \
+} while (0)
+
 int vtd_hw_check(void);
 void disable_pmr(struct iommu *iommu);
 int is_usb_device(u8 bus, u8 devfn);
diff -r 931dbe86e5f3 -r a69daf23602a xen/drivers/passthrough/vtd/intremap.c
--- a/xen/drivers/passthrough/vtd/intremap.c    Fri Jun 05 09:26:39 2009 +0100
+++ b/xen/drivers/passthrough/vtd/intremap.c    Fri Jun 05 09:27:18 2009 +0100
@@ -534,7 +534,7 @@ int enable_intremap(struct iommu *iommu)
 int enable_intremap(struct iommu *iommu)
 {
     struct ir_ctrl *ir_ctrl;
-    s_time_t start_time;
+    u32 sts;
 
     ASSERT(ecap_intr_remap(iommu->ecap) && iommu_intremap);
 
@@ -564,38 +564,22 @@ int enable_intremap(struct iommu *iommu)
     iommu->gcmd |= DMA_GCMD_SIRTP;
     dmar_writel(iommu->reg, DMAR_GCMD_REG, iommu->gcmd);
 
-    /* Make sure hardware complete it */
-    start_time = NOW();
-    while ( !(dmar_readl(iommu->reg, DMAR_GSTS_REG) & DMA_GSTS_SIRTPS) )
-    {
-        if ( NOW() > (start_time + DMAR_OPERATION_TIMEOUT) )
-            panic("Cannot set SIRTP field for interrupt remapping\n");
-        cpu_relax();
-    }
-
+    IOMMU_WAIT_OP(iommu, DMAR_GSTS_REG, dmar_readl,
+                  (sts & DMA_GSTS_SIRTPS), sts);
+ 
     /* enable comaptiblity format interrupt pass through */
     iommu->gcmd |= DMA_GCMD_CFI;
     dmar_writel(iommu->reg, DMAR_GCMD_REG, iommu->gcmd);
 
-    start_time = NOW();
-    while ( !(dmar_readl(iommu->reg, DMAR_GSTS_REG) & DMA_GSTS_CFIS) )
-    {
-        if ( NOW() > (start_time + DMAR_OPERATION_TIMEOUT) )
-            panic("Cannot set CFI field for interrupt remapping\n");
-        cpu_relax();
-    }
+    IOMMU_WAIT_OP(iommu, DMAR_GSTS_REG, dmar_readl,
+                  (sts & DMA_GSTS_CFIS), sts);
 
     /* enable interrupt remapping hardware */
     iommu->gcmd |= DMA_GCMD_IRE;
     dmar_writel(iommu->reg, DMAR_GCMD_REG, iommu->gcmd);
 
-    start_time = NOW();
-    while ( !(dmar_readl(iommu->reg, DMAR_GSTS_REG) & DMA_GSTS_IRES) )
-    {
-        if ( NOW() > (start_time + DMAR_OPERATION_TIMEOUT) )
-            panic("Cannot set IRE field for interrupt remapping\n");
-        cpu_relax();
-    }
+    IOMMU_WAIT_OP(iommu, DMAR_GSTS_REG, dmar_readl,
+                  (sts & DMA_GSTS_IRES), sts);
 
     /* After set SIRTP, we should do globally invalidate the IEC */
     iommu_flush_iec_global(iommu);
@@ -605,18 +589,13 @@ int enable_intremap(struct iommu *iommu)
 
 void disable_intremap(struct iommu *iommu)
 {
-    s_time_t start_time;
+    u32 sts;
 
     ASSERT(ecap_intr_remap(iommu->ecap) && iommu_intremap);
 
     iommu->gcmd &= ~(DMA_GCMD_SIRTP | DMA_GCMD_CFI | DMA_GCMD_IRE);
     dmar_writel(iommu->reg, DMAR_GCMD_REG, iommu->gcmd);
 
-    start_time = NOW();
-    while ( dmar_readl(iommu->reg, DMAR_GSTS_REG) & DMA_GSTS_IRES )
-    {
-        if ( NOW() > (start_time + DMAR_OPERATION_TIMEOUT) )
-            panic("Cannot clear IRE field for interrupt remapping\n");
-        cpu_relax();
-    }
-}
+    IOMMU_WAIT_OP(iommu, DMAR_GSTS_REG, dmar_readl,
+                  !(sts & DMA_GSTS_IRES), sts);
+}
diff -r 931dbe86e5f3 -r a69daf23602a xen/drivers/passthrough/vtd/iommu.c
--- a/xen/drivers/passthrough/vtd/iommu.c       Fri Jun 05 09:26:39 2009 +0100
+++ b/xen/drivers/passthrough/vtd/iommu.c       Fri Jun 05 09:27:18 2009 +0100
@@ -230,7 +230,6 @@ static void iommu_flush_write_buffer(str
 {
     u32 val;
     unsigned long flag;
-    s_time_t start_time;
 
     if ( !rwbf_quirk && !cap_rwbf(iommu->cap) )
         return;
@@ -240,17 +239,9 @@ static void iommu_flush_write_buffer(str
     dmar_writel(iommu->reg, DMAR_GCMD_REG, val);
 
     /* Make sure hardware complete it */
-    start_time = NOW();
-    for ( ; ; )
-    {
-        val = dmar_readl(iommu->reg, DMAR_GSTS_REG);
-        if ( !(val & DMA_GSTS_WBFS) )
-            break;
-        if ( NOW() > start_time + DMAR_OPERATION_TIMEOUT )
-            panic("%s: DMAR hardware is malfunctional,"
-                  " please disable IOMMU\n", __func__);
-        cpu_relax();
-    }
+    IOMMU_WAIT_OP(iommu, DMAR_GSTS_REG, dmar_readl,
+                  !(val & DMA_GSTS_WBFS), val);
+
     spin_unlock_irqrestore(&iommu->register_lock, flag);
 }
 
@@ -263,7 +254,6 @@ static int flush_context_reg(
     struct iommu *iommu = (struct iommu *) _iommu;
     u64 val = 0;
     unsigned long flag;
-    s_time_t start_time;
 
     /*
      * In the non-present entry flush case, if hardware doesn't cache
@@ -301,17 +291,9 @@ static int flush_context_reg(
     dmar_writeq(iommu->reg, DMAR_CCMD_REG, val);
 
     /* Make sure hardware complete it */
-    start_time = NOW();
-    for ( ; ; )
-    {
-        val = dmar_readq(iommu->reg, DMAR_CCMD_REG);
-        if ( !(val & DMA_CCMD_ICC) )
-            break;
-        if ( NOW() > start_time + DMAR_OPERATION_TIMEOUT )
-            panic("%s: DMAR hardware is malfunctional,"
-                  " please disable IOMMU\n", __func__);
-        cpu_relax();
-    }
+    IOMMU_WAIT_OP(iommu, DMAR_CCMD_REG, dmar_readq,
+                  !(val & DMA_CCMD_ICC), val);
+
     spin_unlock_irqrestore(&iommu->register_lock, flag);
     /* flush context entry will implicitly flush write buffer */
     return 0;
@@ -352,7 +334,6 @@ static int flush_iotlb_reg(void *_iommu,
     int tlb_offset = ecap_iotlb_offset(iommu->ecap);
     u64 val = 0, val_iva = 0;
     unsigned long flag;
-    s_time_t start_time;
 
     /*
      * In the non-present entry flush case, if hardware doesn't cache
@@ -399,17 +380,8 @@ static int flush_iotlb_reg(void *_iommu,
     dmar_writeq(iommu->reg, tlb_offset + 8, val);
 
     /* Make sure hardware complete it */
-    start_time = NOW();
-    for ( ; ; )
-    {
-        val = dmar_readq(iommu->reg, tlb_offset + 8);
-        if ( !(val & DMA_TLB_IVT) )
-            break;
-        if ( NOW() > start_time + DMAR_OPERATION_TIMEOUT )
-            panic("%s: DMAR hardware is malfunctional,"
-                  " please disable IOMMU\n", __func__);
-        cpu_relax();
-    }
+    IOMMU_WAIT_OP(iommu, (tlb_offset + 8), dmar_readq,
+                  !(val & DMA_TLB_IVT), val);
     spin_unlock_irqrestore(&iommu->register_lock, flag);
 
     /* check IOTLB invalidation granularity */
@@ -578,7 +550,6 @@ static int iommu_set_root_entry(struct i
 {
     u32 cmd, sts;
     unsigned long flags;
-    s_time_t start_time;
 
     spin_lock(&iommu->lock);
 
@@ -597,18 +568,8 @@ static int iommu_set_root_entry(struct i
     dmar_writel(iommu->reg, DMAR_GCMD_REG, cmd);
 
     /* Make sure hardware complete it */
-    start_time = NOW();
-    for ( ; ; )
-    {
-        sts = dmar_readl(iommu->reg, DMAR_GSTS_REG);
-        if ( sts & DMA_GSTS_RTPS )
-            break;
-        if ( NOW() > start_time + DMAR_OPERATION_TIMEOUT )
-            panic("%s: DMAR hardware is malfunctional,"
-                  " please disable IOMMU\n", __func__);
-        cpu_relax();
-    }
-
+    IOMMU_WAIT_OP(iommu, DMAR_GSTS_REG, dmar_readl,
+                  (sts & DMA_GSTS_RTPS), sts);
     spin_unlock_irqrestore(&iommu->register_lock, flags);
 
     return 0;
@@ -618,25 +579,16 @@ static void iommu_enable_translation(str
 {
     u32 sts;
     unsigned long flags;
-    s_time_t start_time;
 
     dprintk(XENLOG_INFO VTDPREFIX,
             "iommu_enable_translation: iommu->reg = %p\n", iommu->reg);
     spin_lock_irqsave(&iommu->register_lock, flags);
     iommu->gcmd |= DMA_GCMD_TE;
     dmar_writel(iommu->reg, DMAR_GCMD_REG, iommu->gcmd);
+
     /* Make sure hardware complete it */
-    start_time = NOW();
-    for ( ; ; )
-    {
-        sts = dmar_readl(iommu->reg, DMAR_GSTS_REG);
-        if ( sts & DMA_GSTS_TES )
-            break;
-        if ( NOW() > start_time + DMAR_OPERATION_TIMEOUT )
-            panic("%s: DMAR hardware is malfunctional,"
-                  " please disable IOMMU\n", __func__);
-        cpu_relax();
-    }
+    IOMMU_WAIT_OP(iommu, DMAR_GSTS_REG, dmar_readl,
+                  (sts & DMA_GSTS_TES), sts);
 
     /* Disable PMRs when VT-d engine takes effect per spec definition */
     disable_pmr(iommu);
@@ -647,24 +599,14 @@ static void iommu_disable_translation(st
 {
     u32 sts;
     unsigned long flags;
-    s_time_t start_time;
 
     spin_lock_irqsave(&iommu->register_lock, flags);
     iommu->gcmd &= ~ DMA_GCMD_TE;
     dmar_writel(iommu->reg, DMAR_GCMD_REG, iommu->gcmd);
 
     /* Make sure hardware complete it */
-    start_time = NOW();
-    for ( ; ; )
-    {
-        sts = dmar_readl(iommu->reg, DMAR_GSTS_REG);
-        if ( !(sts & DMA_GSTS_TES) )
-            break;
-        if ( NOW() > start_time + DMAR_OPERATION_TIMEOUT )
-            panic("%s: DMAR hardware is malfunctional,"
-                  " please disable IOMMU\n", __func__);
-        cpu_relax();
-    }
+    IOMMU_WAIT_OP(iommu, DMAR_GSTS_REG, dmar_readl,
+                  !(sts & DMA_GSTS_TES), sts);
     spin_unlock_irqrestore(&iommu->register_lock, flags);
 }
 
diff -r 931dbe86e5f3 -r a69daf23602a xen/drivers/passthrough/vtd/qinval.c
--- a/xen/drivers/passthrough/vtd/qinval.c      Fri Jun 05 09:26:39 2009 +0100
+++ b/xen/drivers/passthrough/vtd/qinval.c      Fri Jun 05 09:27:18 2009 +0100
@@ -418,9 +418,9 @@ static int flush_iotlb_qi(
 
 int enable_qinval(struct iommu *iommu)
 {
-    s_time_t start_time;
     struct qi_ctrl *qi_ctrl;
     struct iommu_flush *flush;
+    u32 sts;
 
     qi_ctrl = iommu_qi_ctrl(iommu);
     flush = iommu_get_flush(iommu);
@@ -458,13 +458,8 @@ int enable_qinval(struct iommu *iommu)
     dmar_writel(iommu->reg, DMAR_GCMD_REG, iommu->gcmd);
 
     /* Make sure hardware complete it */
-    start_time = NOW();
-    while ( !(dmar_readl(iommu->reg, DMAR_GSTS_REG) & DMA_GSTS_QIES) )
-    {
-        if ( NOW() > (start_time + DMAR_OPERATION_TIMEOUT) )
-            panic("Cannot set QIE field for queue invalidation\n");
-        cpu_relax();
-    }
+    IOMMU_WAIT_OP(iommu, DMAR_GSTS_REG, dmar_readl,
+                  (sts & DMA_GSTS_QIES), sts);
 
     qinval_enabled = 1;
     return 0;
@@ -472,7 +467,7 @@ int enable_qinval(struct iommu *iommu)
 
 void disable_qinval(struct iommu *iommu)
 {
-    s_time_t start_time;
+    u32 sts;
 
     ASSERT(ecap_queued_inval(iommu->ecap) && iommu_qinval);
 
@@ -480,11 +475,6 @@ void disable_qinval(struct iommu *iommu)
     dmar_writel(iommu->reg, DMAR_GCMD_REG, iommu->gcmd);
 
     /* Make sure hardware complete it */
-    start_time = NOW();
-    while ( dmar_readl(iommu->reg, DMAR_GSTS_REG) & DMA_GSTS_QIES )
-    {
-        if ( NOW() > (start_time + DMAR_OPERATION_TIMEOUT) )
-            panic("Cannot clear QIE field for queue invalidation\n");
-        cpu_relax();
-    }
-}
+    IOMMU_WAIT_OP(iommu, DMAR_GSTS_REG, dmar_readl,
+                  !(sts & DMA_GSTS_QIES), sts);
+}
diff -r 931dbe86e5f3 -r a69daf23602a xen/drivers/passthrough/vtd/utils.c
--- a/xen/drivers/passthrough/vtd/utils.c       Fri Jun 05 09:26:39 2009 +0100
+++ b/xen/drivers/passthrough/vtd/utils.c       Fri Jun 05 09:27:18 2009 +0100
@@ -38,27 +38,16 @@ int is_usb_device(u8 bus, u8 devfn)
 /* Disable vt-d protected memory registers. */
 void disable_pmr(struct iommu *iommu)
 {
-    s_time_t start_time;
-    unsigned int val;
+    u32 val;
 
     val = dmar_readl(iommu->reg, DMAR_PMEN_REG);
     if ( !(val & DMA_PMEN_PRS) )
         return;
 
     dmar_writel(iommu->reg, DMAR_PMEN_REG, val & ~DMA_PMEN_EPM);
-    start_time = NOW();
-
-    for ( ; ; )
-    {
-        val = dmar_readl(iommu->reg, DMAR_PMEN_REG);
-        if ( (val & DMA_PMEN_PRS) == 0 )
-            break;
-
-        if ( NOW() > start_time + DMAR_OPERATION_TIMEOUT )
-            panic("Disable PMRs timeout\n");
-
-        cpu_relax();
-    }
+
+    IOMMU_WAIT_OP(iommu, DMAR_PMEN_REG, dmar_readl,
+                  !(val & DMA_PMEN_PRS), val);
 
     dprintk(XENLOG_INFO VTDPREFIX,
             "Disabled protected memory registers\n");

_______________________________________________
Xen-changelog mailing list
Xen-changelog@xxxxxxxxxxxxxxxxxxx
http://lists.xensource.com/xen-changelog


 


Rackspace

Lists.xenproject.org is hosted with RackSpace, monitoring our
servers 24x7x365 and backed by RackSpace's Fanatical Support®.