Commit eba67e5d authored by Suresh Siddha's avatar Suresh Siddha Committed by H. Peter Anvin

x86, dmar: routines for disabling queued invalidation and intr remapping

Impact: new interfaces (not yet used)

Routines for disabling queued invalidation and interrupt remapping.
Signed-off-by: default avatarSuresh Siddha <suresh.b.siddha@intel.com>
Signed-off-by: default avatarH. Peter Anvin <hpa@linux.intel.com>
parent 9d783ba0
...@@ -753,6 +753,42 @@ int qi_flush_iotlb(struct intel_iommu *iommu, u16 did, u64 addr, ...@@ -753,6 +753,42 @@ int qi_flush_iotlb(struct intel_iommu *iommu, u16 did, u64 addr,
return qi_submit_sync(&desc, iommu); return qi_submit_sync(&desc, iommu);
} }
/*
* Disable Queued Invalidation interface.
*/
void dmar_disable_qi(struct intel_iommu *iommu)
{
unsigned long flags;
u32 sts;
cycles_t start_time = get_cycles();
if (!ecap_qis(iommu->ecap))
return;
spin_lock_irqsave(&iommu->register_lock, flags);
sts = dmar_readq(iommu->reg + DMAR_GSTS_REG);
if (!(sts & DMA_GSTS_QIES))
goto end;
/*
* Give a chance to HW to complete the pending invalidation requests.
*/
while ((readl(iommu->reg + DMAR_IQT_REG) !=
readl(iommu->reg + DMAR_IQH_REG)) &&
(DMAR_OPERATION_TIMEOUT > (get_cycles() - start_time)))
cpu_relax();
iommu->gcmd &= ~DMA_GCMD_QIE;
writel(iommu->gcmd, iommu->reg + DMAR_GCMD_REG);
IOMMU_WAIT_OP(iommu, DMAR_GSTS_REG, readl,
!(sts & DMA_GSTS_QIES), sts);
end:
spin_unlock_irqrestore(&iommu->register_lock, flags);
}
/* /*
* Enable Queued Invalidation interface. This is a must to support * Enable Queued Invalidation interface. This is a must to support
* interrupt-remapping. Also used by DMA-remapping, which replaces * interrupt-remapping. Also used by DMA-remapping, which replaces
......
...@@ -467,6 +467,33 @@ static int setup_intr_remapping(struct intel_iommu *iommu, int mode) ...@@ -467,6 +467,33 @@ static int setup_intr_remapping(struct intel_iommu *iommu, int mode)
return 0; return 0;
} }
/*
* Disable Interrupt Remapping.
*/
static void disable_intr_remapping(struct intel_iommu *iommu)
{
unsigned long flags;
u32 sts;
if (!ecap_ir_support(iommu->ecap))
return;
spin_lock_irqsave(&iommu->register_lock, flags);
sts = dmar_readq(iommu->reg + DMAR_GSTS_REG);
if (!(sts & DMA_GSTS_IRES))
goto end;
iommu->gcmd &= ~DMA_GCMD_IRE;
writel(iommu->gcmd, iommu->reg + DMAR_GCMD_REG);
IOMMU_WAIT_OP(iommu, DMAR_GSTS_REG,
readl, !(sts & DMA_GSTS_IRES), sts);
end:
spin_unlock_irqrestore(&iommu->register_lock, flags);
}
int __init enable_intr_remapping(int eim) int __init enable_intr_remapping(int eim)
{ {
struct dmar_drhd_unit *drhd; struct dmar_drhd_unit *drhd;
......
...@@ -321,6 +321,7 @@ extern struct dmar_drhd_unit * dmar_find_matched_drhd_unit(struct pci_dev *dev); ...@@ -321,6 +321,7 @@ extern struct dmar_drhd_unit * dmar_find_matched_drhd_unit(struct pci_dev *dev);
extern int alloc_iommu(struct dmar_drhd_unit *drhd); extern int alloc_iommu(struct dmar_drhd_unit *drhd);
extern void free_iommu(struct intel_iommu *iommu); extern void free_iommu(struct intel_iommu *iommu);
extern int dmar_enable_qi(struct intel_iommu *iommu); extern int dmar_enable_qi(struct intel_iommu *iommu);
extern void dmar_disable_qi(struct intel_iommu *iommu);
extern void qi_global_iec(struct intel_iommu *iommu); extern void qi_global_iec(struct intel_iommu *iommu);
extern int qi_flush_context(struct intel_iommu *iommu, u16 did, u16 sid, extern int qi_flush_context(struct intel_iommu *iommu, u16 did, u16 sid,
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment