Commit ad3ad3f6 authored by Suresh Siddha's avatar Suresh Siddha Committed by Ingo Molnar
Browse files

x64, x2apic/intr-remap: parse ioapic scope under vt-d structures



Parse the vt-d device scope structures to find the mapping between IO-APICs
and the interrupt remapping hardware units.

This will be used later for enabling Interrupt-remapping for IOAPIC devices.

Signed-off-by: default avatarSuresh Siddha <suresh.b.siddha@intel.com>
Cc: akpm@linux-foundation.org
Cc: arjan@linux.intel.com
Cc: andi@firstfloor.org
Cc: ebiederm@xmission.com
Cc: jbarnes@virtuousgeek.org
Cc: steiner@sgi.com
Signed-off-by: default avatarIngo Molnar <mingo@elte.hu>
parent 2d6b5f85
Loading
Loading
Loading
Loading
+2 −0
Original line number Diff line number Diff line
@@ -26,6 +26,8 @@ obj-$(CONFIG_HT_IRQ) += htirq.o
# Build Intel IOMMU support
obj-$(CONFIG_DMAR) += dmar.o iova.o intel-iommu.o

obj-$(CONFIG_INTR_REMAP) += dmar.o intr_remapping.o

#
# Some architectures use the generic PCI setup functions
#
+3 −0
Original line number Diff line number Diff line
@@ -423,6 +423,9 @@ int __init dmar_table_init(void)
		printk(KERN_INFO PREFIX "No RMRR found\n");
#endif

#ifdef CONFIG_INTR_REMAP
	parse_ioapics_under_ir();
#endif
	return 0;
}

+2 −0
Original line number Diff line number Diff line
@@ -114,6 +114,8 @@ static inline void dmar_writeq(void __iomem *addr, u64 val)
#define ecap_max_iotlb_offset(e) \
	(ecap_iotlb_offset(e) + ecap_niotlb_iunits(e) * 16)
#define ecap_coherent(e)	((e) & 0x1)
#define ecap_eim_support(e)	((e >> 4) & 0x1)
#define ecap_ir_support(e)	((e >> 3) & 0x1)


/* IOTLB_REG */
+70 −0
Original line number Diff line number Diff line
#include <linux/dmar.h>
#include <asm/io_apic.h>
#include "intel-iommu.h"
#include "intr_remapping.h"

static struct ioapic_scope ir_ioapic[MAX_IO_APICS];
static int ir_ioapic_num;

static int ir_parse_ioapic_scope(struct acpi_dmar_header *header,
				 struct intel_iommu *iommu)
{
	struct acpi_dmar_hardware_unit *drhd;
	struct acpi_dmar_device_scope *scope;
	void *start, *end;

	drhd = (struct acpi_dmar_hardware_unit *)header;

	start = (void *)(drhd + 1);
	end = ((void *)drhd) + header->length;

	while (start < end) {
		scope = start;
		if (scope->entry_type == ACPI_DMAR_SCOPE_TYPE_IOAPIC) {
			if (ir_ioapic_num == MAX_IO_APICS) {
				printk(KERN_WARNING "Exceeded Max IO APICS\n");
				return -1;
			}

			printk(KERN_INFO "IOAPIC id %d under DRHD base"
			       " 0x%Lx\n", scope->enumeration_id,
			       drhd->address);

			ir_ioapic[ir_ioapic_num].iommu = iommu;
			ir_ioapic[ir_ioapic_num].id = scope->enumeration_id;
			ir_ioapic_num++;
		}
		start += scope->length;
	}

	return 0;
}

/*
 * Finds the assocaition between IOAPIC's and its Interrupt-remapping
 * hardware unit.
 */
int __init parse_ioapics_under_ir(void)
{
	struct dmar_drhd_unit *drhd;
	int ir_supported = 0;

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

		if (ecap_ir_support(iommu->ecap)) {
			if (ir_parse_ioapic_scope(drhd->hdr, iommu))
				return -1;

			ir_supported = 1;
		}
	}

	if (ir_supported && ir_ioapic_num != nr_ioapics) {
		printk(KERN_WARNING
		       "Not all IO-APIC's listed under remapping hardware\n");
		return -1;
	}

	return ir_supported;
}
+6 −0
Original line number Diff line number Diff line
#include "intel-iommu.h"

struct ioapic_scope {
	struct intel_iommu *iommu;
	unsigned int id;
};
Loading