]>
Commit | Line | Data |
---|---|---|
2cb7cef9 BS |
1 | From: Suresh Siddha <suresh.b.siddha@intel.com> |
2 | Subject: x64, x2apic/intr-remap: parse ioapic scope under vt-d structures | |
3 | References: fate #303948 and fate #303984 | |
4 | Patch-Mainline: queued for .28 | |
5 | Commit-ID: ad3ad3f6a2caebf56869b83b69e23eb9fa5e0ab6 | |
6 | ||
7 | Signed-off-by: Thomas Renninger <trenn@suse.de> | |
8 | ||
9 | Parse the vt-d device scope structures to find the mapping between IO-APICs | |
10 | and the interrupt remapping hardware units. | |
11 | ||
12 | This will be used later for enabling Interrupt-remapping for IOAPIC devices. | |
13 | ||
14 | Signed-off-by: Suresh Siddha <suresh.b.siddha@intel.com> | |
15 | Cc: akpm@linux-foundation.org | |
16 | Cc: arjan@linux.intel.com | |
17 | Cc: andi@firstfloor.org | |
18 | Cc: ebiederm@xmission.com | |
19 | Cc: jbarnes@virtuousgeek.org | |
20 | Cc: steiner@sgi.com | |
21 | Signed-off-by: Ingo Molnar <mingo@elte.hu> | |
22 | ||
23 | --- | |
24 | drivers/pci/Makefile | 2 + | |
25 | drivers/pci/dmar.c | 3 + | |
26 | drivers/pci/intel-iommu.h | 2 + | |
27 | drivers/pci/intr_remapping.c | 70 +++++++++++++++++++++++++++++++++++++++++++ | |
28 | drivers/pci/intr_remapping.h | 6 +++ | |
29 | include/linux/dmar.h | 1 | |
30 | 6 files changed, 84 insertions(+) | |
31 | ||
32 | Index: linux-2.6.26/drivers/pci/Makefile | |
33 | =================================================================== | |
34 | --- linux-2.6.26.orig/drivers/pci/Makefile | |
35 | +++ linux-2.6.26/drivers/pci/Makefile | |
36 | @@ -26,6 +26,8 @@ obj-$(CONFIG_HT_IRQ) += htirq.o | |
37 | # Build Intel IOMMU support | |
38 | obj-$(CONFIG_DMAR) += dmar.o iova.o intel-iommu.o | |
39 | ||
40 | +obj-$(CONFIG_INTR_REMAP) += dmar.o intr_remapping.o | |
41 | + | |
42 | # | |
43 | # Some architectures use the generic PCI setup functions | |
44 | # | |
45 | Index: linux-2.6.26/drivers/pci/dmar.c | |
46 | =================================================================== | |
47 | --- linux-2.6.26.orig/drivers/pci/dmar.c | |
48 | +++ linux-2.6.26/drivers/pci/dmar.c | |
49 | @@ -425,6 +425,9 @@ int __init dmar_table_init(void) | |
50 | } | |
51 | #endif | |
52 | ||
53 | +#ifdef CONFIG_INTR_REMAP | |
54 | + parse_ioapics_under_ir(); | |
55 | +#endif | |
56 | return 0; | |
57 | } | |
58 | ||
59 | Index: linux-2.6.26/drivers/pci/intel-iommu.h | |
60 | =================================================================== | |
61 | --- linux-2.6.26.orig/drivers/pci/intel-iommu.h | |
62 | +++ linux-2.6.26/drivers/pci/intel-iommu.h | |
63 | @@ -114,6 +114,8 @@ static inline void dmar_writeq(void __io | |
64 | #define ecap_max_iotlb_offset(e) \ | |
65 | (ecap_iotlb_offset(e) + ecap_niotlb_iunits(e) * 16) | |
66 | #define ecap_coherent(e) ((e) & 0x1) | |
67 | +#define ecap_eim_support(e) ((e >> 4) & 0x1) | |
68 | +#define ecap_ir_support(e) ((e >> 3) & 0x1) | |
69 | ||
70 | ||
71 | /* IOTLB_REG */ | |
72 | Index: linux-2.6.26/drivers/pci/intr_remapping.c | |
73 | =================================================================== | |
74 | --- /dev/null | |
75 | +++ linux-2.6.26/drivers/pci/intr_remapping.c | |
76 | @@ -0,0 +1,70 @@ | |
77 | +#include <linux/dmar.h> | |
78 | +#include <asm/io_apic.h> | |
79 | +#include "intel-iommu.h" | |
80 | +#include "intr_remapping.h" | |
81 | + | |
82 | +static struct ioapic_scope ir_ioapic[MAX_IO_APICS]; | |
83 | +static int ir_ioapic_num; | |
84 | + | |
85 | +static int ir_parse_ioapic_scope(struct acpi_dmar_header *header, | |
86 | + struct intel_iommu *iommu) | |
87 | +{ | |
88 | + struct acpi_dmar_hardware_unit *drhd; | |
89 | + struct acpi_dmar_device_scope *scope; | |
90 | + void *start, *end; | |
91 | + | |
92 | + drhd = (struct acpi_dmar_hardware_unit *)header; | |
93 | + | |
94 | + start = (void *)(drhd + 1); | |
95 | + end = ((void *)drhd) + header->length; | |
96 | + | |
97 | + while (start < end) { | |
98 | + scope = start; | |
99 | + if (scope->entry_type == ACPI_DMAR_SCOPE_TYPE_IOAPIC) { | |
100 | + if (ir_ioapic_num == MAX_IO_APICS) { | |
101 | + printk(KERN_WARNING "Exceeded Max IO APICS\n"); | |
102 | + return -1; | |
103 | + } | |
104 | + | |
105 | + printk(KERN_INFO "IOAPIC id %d under DRHD base" | |
106 | + " 0x%Lx\n", scope->enumeration_id, | |
107 | + drhd->address); | |
108 | + | |
109 | + ir_ioapic[ir_ioapic_num].iommu = iommu; | |
110 | + ir_ioapic[ir_ioapic_num].id = scope->enumeration_id; | |
111 | + ir_ioapic_num++; | |
112 | + } | |
113 | + start += scope->length; | |
114 | + } | |
115 | + | |
116 | + return 0; | |
117 | +} | |
118 | + | |
119 | +/* | |
120 | + * Finds the assocaition between IOAPIC's and its Interrupt-remapping | |
121 | + * hardware unit. | |
122 | + */ | |
123 | +int __init parse_ioapics_under_ir(void) | |
124 | +{ | |
125 | + struct dmar_drhd_unit *drhd; | |
126 | + int ir_supported = 0; | |
127 | + | |
128 | + for_each_drhd_unit(drhd) { | |
129 | + struct intel_iommu *iommu = drhd->iommu; | |
130 | + | |
131 | + if (ecap_ir_support(iommu->ecap)) { | |
132 | + if (ir_parse_ioapic_scope(drhd->hdr, iommu)) | |
133 | + return -1; | |
134 | + | |
135 | + ir_supported = 1; | |
136 | + } | |
137 | + } | |
138 | + | |
139 | + if (ir_supported && ir_ioapic_num != nr_ioapics) { | |
140 | + printk(KERN_WARNING | |
141 | + "Not all IO-APIC's listed under remapping hardware\n"); | |
142 | + return -1; | |
143 | + } | |
144 | + | |
145 | + return ir_supported; | |
146 | +} | |
147 | Index: linux-2.6.26/drivers/pci/intr_remapping.h | |
148 | =================================================================== | |
149 | --- /dev/null | |
150 | +++ linux-2.6.26/drivers/pci/intr_remapping.h | |
151 | @@ -0,0 +1,6 @@ | |
152 | +#include "intel-iommu.h" | |
153 | + | |
154 | +struct ioapic_scope { | |
155 | + struct intel_iommu *iommu; | |
156 | + unsigned int id; | |
157 | +}; | |
158 | Index: linux-2.6.26/include/linux/dmar.h | |
159 | =================================================================== | |
160 | --- linux-2.6.26.orig/include/linux/dmar.h | |
161 | +++ linux-2.6.26/include/linux/dmar.h | |
162 | @@ -47,6 +47,7 @@ extern int intel_iommu_init(void); | |
163 | extern int dmar_table_init(void); | |
164 | extern int early_dmar_detect(void); | |
165 | extern int dmar_dev_scope_init(void); | |
166 | +extern int parse_ioapics_under_ir(void); | |
167 | ||
168 | extern struct list_head dmar_drhd_units; | |
169 | extern struct list_head dmar_rmrr_units; |