Skip to content

Commit

Permalink
---
Browse files Browse the repository at this point in the history
yaml
---
r: 142250
b: refs/heads/master
c: eb4a52b
h: refs/heads/master
v: v3
  • Loading branch information
Fenghua Yu authored and David Woodhouse committed Apr 3, 2009
1 parent 0832c27 commit cd74e73
Show file tree
Hide file tree
Showing 2 changed files with 56 additions and 16 deletions.
2 changes: 1 addition & 1 deletion [refs]
Original file line number Diff line number Diff line change
@@ -1,2 +1,2 @@
---
refs/heads/master: f59c7b69bcba31cd355ababe067202b9895d6102
refs/heads/master: eb4a52bc660ea835482c582eaaf4893742cbd160
70 changes: 55 additions & 15 deletions trunk/drivers/pci/dmar.c
Original file line number Diff line number Diff line change
Expand Up @@ -789,15 +789,42 @@ void dmar_disable_qi(struct intel_iommu *iommu)
spin_unlock_irqrestore(&iommu->register_lock, flags);
}

/*
* Enable queued invalidation.
*/
static void __dmar_enable_qi(struct intel_iommu *iommu)
{
u32 cmd, sts;
unsigned long flags;
struct q_inval *qi = iommu->qi;

qi->free_head = qi->free_tail = 0;
qi->free_cnt = QI_LENGTH;

spin_lock_irqsave(&iommu->register_lock, flags);

/* write zero to the tail reg */
writel(0, iommu->reg + DMAR_IQT_REG);

dmar_writeq(iommu->reg + DMAR_IQA_REG, virt_to_phys(qi->desc));

cmd = iommu->gcmd | DMA_GCMD_QIE;
iommu->gcmd |= DMA_GCMD_QIE;
writel(cmd, iommu->reg + DMAR_GCMD_REG);

/* Make sure hardware complete it */
IOMMU_WAIT_OP(iommu, DMAR_GSTS_REG, readl, (sts & DMA_GSTS_QIES), sts);

spin_unlock_irqrestore(&iommu->register_lock, flags);
}

/*
* Enable Queued Invalidation interface. This is a must to support
* interrupt-remapping. Also used by DMA-remapping, which replaces
* register based IOTLB invalidation.
*/
int dmar_enable_qi(struct intel_iommu *iommu)
{
u32 cmd, sts;
unsigned long flags;
struct q_inval *qi;

if (!ecap_qis(iommu->ecap))
Expand Down Expand Up @@ -835,19 +862,7 @@ int dmar_enable_qi(struct intel_iommu *iommu)

spin_lock_init(&qi->q_lock);

spin_lock_irqsave(&iommu->register_lock, flags);
/* write zero to the tail reg */
writel(0, iommu->reg + DMAR_IQT_REG);

dmar_writeq(iommu->reg + DMAR_IQA_REG, virt_to_phys(qi->desc));

cmd = iommu->gcmd | DMA_GCMD_QIE;
iommu->gcmd |= DMA_GCMD_QIE;
writel(cmd, iommu->reg + DMAR_GCMD_REG);

/* Make sure hardware complete it */
IOMMU_WAIT_OP(iommu, DMAR_GSTS_REG, readl, (sts & DMA_GSTS_QIES), sts);
spin_unlock_irqrestore(&iommu->register_lock, flags);
__dmar_enable_qi(iommu);

return 0;
}
Expand Down Expand Up @@ -1102,3 +1117,28 @@ int __init enable_drhd_fault_handling(void)

return 0;
}

/*
* Re-enable Queued Invalidation interface.
*/
int dmar_reenable_qi(struct intel_iommu *iommu)
{
if (!ecap_qis(iommu->ecap))
return -ENOENT;

if (!iommu->qi)
return -ENOENT;

/*
* First disable queued invalidation.
*/
dmar_disable_qi(iommu);
/*
* Then enable queued invalidation again. Since there is no pending
* invalidation requests now, it's safe to re-enable queued
* invalidation.
*/
__dmar_enable_qi(iommu);

return 0;
}

0 comments on commit cd74e73

Please sign in to comment.