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