Intel IOMMU Suspend/Resume Support - Interrupt Remapping

This patch enables suspend/resume for interrupt remapping. During suspend,
interrupt remapping is disabled. When resume, interrupt remapping is enabled
again.

Signed-off-by: Fenghua Yu <fenghua.yu@intel.com>
Acked-by: Ingo Molnar <mingo@elte.hu>
Signed-off-by: David Woodhouse <David.Woodhouse@intel.com>
This commit is contained in:
Fenghua Yu
2009-03-27 14:22:44 -07:00
committed by David Woodhouse
parent eb4a52bc66
commit b24696bc55
6 changed files with 204 additions and 55 deletions

View File

@@ -470,7 +470,7 @@ static int setup_intr_remapping(struct intel_iommu *iommu, int mode)
/*
* Disable Interrupt Remapping.
*/
static void disable_intr_remapping(struct intel_iommu *iommu)
static void iommu_disable_intr_remapping(struct intel_iommu *iommu)
{
unsigned long flags;
u32 sts;
@@ -478,6 +478,12 @@ static void disable_intr_remapping(struct intel_iommu *iommu)
if (!ecap_ir_support(iommu->ecap))
return;
/*
* global invalidation of interrupt entry cache before disabling
* interrupt-remapping.
*/
qi_global_iec(iommu);
spin_lock_irqsave(&iommu->register_lock, flags);
sts = dmar_readq(iommu->reg + DMAR_GSTS_REG);
@@ -511,7 +517,7 @@ int __init enable_intr_remapping(int eim)
* Disable intr remapping and queued invalidation, if already
* enabled prior to OS handover.
*/
disable_intr_remapping(iommu);
iommu_disable_intr_remapping(iommu);
dmar_disable_qi(iommu);
}
@@ -639,3 +645,54 @@ int __init parse_ioapics_under_ir(void)
return ir_supported;
}
void disable_intr_remapping(void)
{
struct dmar_drhd_unit *drhd;
struct intel_iommu *iommu = NULL;
/*
* Disable Interrupt-remapping for all the DRHD's now.
*/
for_each_iommu(iommu, drhd) {
if (!ecap_ir_support(iommu->ecap))
continue;
iommu_disable_intr_remapping(iommu);
}
}
int reenable_intr_remapping(int eim)
{
struct dmar_drhd_unit *drhd;
int setup = 0;
struct intel_iommu *iommu = NULL;
for_each_iommu(iommu, drhd)
if (iommu->qi)
dmar_reenable_qi(iommu);
/*
* Setup Interrupt-remapping for all the DRHD's now.
*/
for_each_iommu(iommu, drhd) {
if (!ecap_ir_support(iommu->ecap))
continue;
/* Set up interrupt remapping for iommu.*/
iommu_set_intr_remapping(iommu, eim);
setup = 1;
}
if (!setup)
goto error;
return 0;
error:
/*
* handle error condition gracefully here!
*/
return -1;
}