Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 1531a6a6 authored by Suresh Siddha's avatar Suresh Siddha Committed by H. Peter Anvin
Browse files

x86, dmar: start with sane state while enabling dma and interrupt-remapping



Impact: cleanup/sanitization

Start from a sane state while enabling dma and interrupt-remapping, by
clearing the previous recorded faults and disabling previously
enabled 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 eba67e5d
Loading
Loading
Loading
Loading
+1 −4
Original line number Diff line number Diff line
@@ -982,7 +982,7 @@ static int dmar_fault_do_one(struct intel_iommu *iommu, int type,
}

#define PRIMARY_FAULT_REG_LEN (16)
static irqreturn_t dmar_fault(int irq, void *dev_id)
irqreturn_t dmar_fault(int irq, void *dev_id)
{
	struct intel_iommu *iommu = dev_id;
	int reg, fault_index;
@@ -1074,9 +1074,6 @@ int dmar_set_interrupt(struct intel_iommu *iommu)
		return 0;
	}

	/* Force fault register is cleared */
	dmar_fault(irq, iommu);

	ret = request_irq(irq, dmar_fault, 0, iommu->name, iommu);
	if (ret)
		printk(KERN_ERR "IOMMU: can't request irq\n");
+29 −0
Original line number Diff line number Diff line
@@ -1855,11 +1855,40 @@ static int __init init_dmars(void)
		}
	}

	/*
	 * Start from the sane iommu hardware state.
	 */
	for_each_drhd_unit(drhd) {
		if (drhd->ignored)
			continue;

		iommu = drhd->iommu;

		/*
		 * If the queued invalidation is already initialized by us
		 * (for example, while enabling interrupt-remapping) then
		 * we got the things already rolling from a sane state.
		 */
		if (iommu->qi)
			continue;

		/*
		 * Clear any previous faults.
		 */
		dmar_fault(-1, iommu);
		/*
		 * Disable queued invalidation if supported and already enabled
		 * before OS handover.
		 */
		dmar_disable_qi(iommu);
	}

	for_each_drhd_unit(drhd) {
		if (drhd->ignored)
			continue;

		iommu = drhd->iommu;

		if (dmar_enable_qi(iommu)) {
			/*
			 * Queued Invalidate not enabled, use Register Based
+17 −0
Original line number Diff line number Diff line
@@ -499,6 +499,23 @@ int __init enable_intr_remapping(int eim)
	struct dmar_drhd_unit *drhd;
	int setup = 0;

	for_each_drhd_unit(drhd) {
		struct intel_iommu *iommu = drhd->iommu;

		/*
		 * Clear previous faults.
		 */
		dmar_fault(-1, iommu);

		/*
		 * Disable intr remapping and queued invalidation, if already
		 * enabled prior to OS handover.
		 */
		disable_intr_remapping(iommu);

		dmar_disable_qi(iommu);
	}

	/*
	 * check for the Interrupt-remapping support
	 */
+2 −0
Original line number Diff line number Diff line
@@ -24,6 +24,7 @@
#include <linux/acpi.h>
#include <linux/types.h>
#include <linux/msi.h>
#include <linux/irqreturn.h>

#if defined(CONFIG_DMAR) || defined(CONFIG_INTR_REMAP)
struct intel_iommu;
@@ -125,6 +126,7 @@ extern void dmar_msi_mask(unsigned int irq);
extern void dmar_msi_read(int irq, struct msi_msg *msg);
extern void dmar_msi_write(int irq, struct msi_msg *msg);
extern int dmar_set_interrupt(struct intel_iommu *iommu);
extern irqreturn_t dmar_fault(int irq, void *dev_id);
extern int arch_setup_dmar_msi(unsigned int irq);

#ifdef CONFIG_DMAR