#ifdef CONFIG_X86
/* set extended interrupt mode bit */
- ir_ctrl->iremap_maddr |=
- eim ? (1 << IRTA_REG_EIME_SHIFT) : 0;
+ ir_ctrl->iremap_maddr |= eim ? IRTA_EIME : 0;
#endif
spin_lock_irqsave(&iommu->register_lock, flags);
if ( !ecap_intr_remap(iommu->ecap) )
return;
+ /* If we are disabling Interrupt Remapping, make sure we dont stay in
+ * Extended Interrupt Mode, as this is unaffected by the Interrupt
+ * Remapping flag in each DMAR Global Control Register.
+ * Specifically, local apics in xapic mode do not like interrupts delivered
+ * in x2apic mode. Any code turning interrupt remapping back on will set
+ * EIME back correctly.
+ */
+ if ( iommu_supports_eim() )
+ {
+ u64 irta;
+ irta = dmar_readl(iommu->reg, DMAR_IRTA_REG);
+ dmar_writel(iommu->reg, DMAR_IRTA_REG, irta & ~IRTA_EIME);
+ IOMMU_WAIT_OP(iommu, DMAR_IRTA_REG, dmar_readl,
+ !(irta & IRTA_EIME), irta);
+ }
+
spin_lock_irqsave(&iommu->register_lock, flags);
sts = dmar_readl(iommu->reg, DMAR_GSTS_REG);
if ( !(sts & DMA_GSTS_IRES) )
#define IEC_GLOBAL_INVL 0
#define IEC_INDEX_INVL 1
-#define IRTA_REG_EIME_SHIFT 11
+#define IRTA_EIME (1 << 11)
/* 2^(IRTA_REG_TABLE_SIZE + 1) = IREMAP_ENTRY_NR */
#define IRTA_REG_TABLE_SIZE ( IREMAP_PAGE_ORDER + 7 )