[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
|
Lists.xenproject.org is hosted with RackSpace, monitoring our |