aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorSuresh Siddha <suresh.b.siddha@intel.com>2008-07-10 14:16:40 -0400
committerIngo Molnar <mingo@elte.hu>2008-07-12 02:44:50 -0400
commitad3ad3f6a2caebf56869b83b69e23eb9fa5e0ab6 (patch)
tree7bc99dde6a6313eb43783086a33f6eebc1da1907
parent2d6b5f85bb4ca919d8ab0f30311309b53fb93bc3 (diff)
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: Suresh 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: Ingo Molnar <mingo@elte.hu>
-rw-r--r--drivers/pci/Makefile2
-rw-r--r--drivers/pci/dmar.c3
-rw-r--r--drivers/pci/intel-iommu.h2
-rw-r--r--drivers/pci/intr_remapping.c70
-rw-r--r--drivers/pci/intr_remapping.h6
-rw-r--r--include/linux/dmar.h1
6 files changed, 84 insertions, 0 deletions
diff --git a/drivers/pci/Makefile b/drivers/pci/Makefile
index 4d1ce2e7361..1c409c7b0d5 100644
--- a/drivers/pci/Makefile
+++ b/drivers/pci/Makefile
@@ -26,6 +26,8 @@ obj-$(CONFIG_HT_IRQ) += htirq.o
26# Build Intel IOMMU support 26# Build Intel IOMMU support
27obj-$(CONFIG_DMAR) += dmar.o iova.o intel-iommu.o 27obj-$(CONFIG_DMAR) += dmar.o iova.o intel-iommu.o
28 28
29obj-$(CONFIG_INTR_REMAP) += dmar.o intr_remapping.o
30
29# 31#
30# Some architectures use the generic PCI setup functions 32# Some architectures use the generic PCI setup functions
31# 33#
diff --git a/drivers/pci/dmar.c b/drivers/pci/dmar.c
index 903f1701edf..127764cfbe2 100644
--- a/drivers/pci/dmar.c
+++ b/drivers/pci/dmar.c
@@ -423,6 +423,9 @@ int __init dmar_table_init(void)
423 printk(KERN_INFO PREFIX "No RMRR found\n"); 423 printk(KERN_INFO PREFIX "No RMRR found\n");
424#endif 424#endif
425 425
426#ifdef CONFIG_INTR_REMAP
427 parse_ioapics_under_ir();
428#endif
426 return 0; 429 return 0;
427} 430}
428 431
diff --git a/drivers/pci/intel-iommu.h b/drivers/pci/intel-iommu.h
index 371e3b9caf3..eb167e39b46 100644
--- a/drivers/pci/intel-iommu.h
+++ b/drivers/pci/intel-iommu.h
@@ -114,6 +114,8 @@ static inline void dmar_writeq(void __iomem *addr, u64 val)
114#define ecap_max_iotlb_offset(e) \ 114#define ecap_max_iotlb_offset(e) \
115 (ecap_iotlb_offset(e) + ecap_niotlb_iunits(e) * 16) 115 (ecap_iotlb_offset(e) + ecap_niotlb_iunits(e) * 16)
116#define ecap_coherent(e) ((e) & 0x1) 116#define ecap_coherent(e) ((e) & 0x1)
117#define ecap_eim_support(e) ((e >> 4) & 0x1)
118#define ecap_ir_support(e) ((e >> 3) & 0x1)
117 119
118 120
119/* IOTLB_REG */ 121/* IOTLB_REG */
diff --git a/drivers/pci/intr_remapping.c b/drivers/pci/intr_remapping.c
new file mode 100644
index 00000000000..a80b87921c6
--- /dev/null
+++ b/drivers/pci/intr_remapping.c
@@ -0,0 +1,70 @@
1#include <linux/dmar.h>
2#include <asm/io_apic.h>
3#include "intel-iommu.h"
4#include "intr_remapping.h"
5
6static struct ioapic_scope ir_ioapic[MAX_IO_APICS];
7static int ir_ioapic_num;
8
9static int ir_parse_ioapic_scope(struct acpi_dmar_header *header,
10 struct intel_iommu *iommu)
11{
12 struct acpi_dmar_hardware_unit *drhd;
13 struct acpi_dmar_device_scope *scope;
14 void *start, *end;
15
16 drhd = (struct acpi_dmar_hardware_unit *)header;
17
18 start = (void *)(drhd + 1);
19 end = ((void *)drhd) + header->length;
20
21 while (start < end) {
22 scope = start;
23 if (scope->entry_type == ACPI_DMAR_SCOPE_TYPE_IOAPIC) {
24 if (ir_ioapic_num == MAX_IO_APICS) {
25 printk(KERN_WARNING "Exceeded Max IO APICS\n");
26 return -1;
27 }
28
29 printk(KERN_INFO "IOAPIC id %d under DRHD base"
30 " 0x%Lx\n", scope->enumeration_id,
31 drhd->address);
32
33 ir_ioapic[ir_ioapic_num].iommu = iommu;
34 ir_ioapic[ir_ioapic_num].id = scope->enumeration_id;
35 ir_ioapic_num++;
36 }
37 start += scope->length;
38 }
39
40 return 0;
41}
42
43/*
44 * Finds the assocaition between IOAPIC's and its Interrupt-remapping
45 * hardware unit.
46 */
47int __init parse_ioapics_under_ir(void)
48{
49 struct dmar_drhd_unit *drhd;
50 int ir_supported = 0;
51
52 for_each_drhd_unit(drhd) {
53 struct intel_iommu *iommu = drhd->iommu;
54
55 if (ecap_ir_support(iommu->ecap)) {
56 if (ir_parse_ioapic_scope(drhd->hdr, iommu))
57 return -1;
58
59 ir_supported = 1;
60 }
61 }
62
63 if (ir_supported && ir_ioapic_num != nr_ioapics) {
64 printk(KERN_WARNING
65 "Not all IO-APIC's listed under remapping hardware\n");
66 return -1;
67 }
68
69 return ir_supported;
70}
diff --git a/drivers/pci/intr_remapping.h b/drivers/pci/intr_remapping.h
new file mode 100644
index 00000000000..c4a40b2f33f
--- /dev/null
+++ b/drivers/pci/intr_remapping.h
@@ -0,0 +1,6 @@
1#include "intel-iommu.h"
2
3struct ioapic_scope {
4 struct intel_iommu *iommu;
5 unsigned int id;
6};
diff --git a/include/linux/dmar.h b/include/linux/dmar.h
index 3ab07e42558..c4e96eb2961 100644
--- a/include/linux/dmar.h
+++ b/include/linux/dmar.h
@@ -47,6 +47,7 @@ extern int intel_iommu_init(void);
47extern int dmar_table_init(void); 47extern int dmar_table_init(void);
48extern int early_dmar_detect(void); 48extern int early_dmar_detect(void);
49extern int dmar_dev_scope_init(void); 49extern int dmar_dev_scope_init(void);
50extern int parse_ioapics_under_ir(void);
50 51
51extern struct list_head dmar_drhd_units; 52extern struct list_head dmar_drhd_units;
52extern struct list_head dmar_rmrr_units; 53extern struct list_head dmar_rmrr_units;