aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorSuresh Siddha <suresh.b.siddha@intel.com>2008-07-10 14:16:37 -0400
committerIngo Molnar <mingo@elte.hu>2008-07-12 02:44:48 -0400
commit1886e8a90a580f3ad343f2065c84c1b9e1dac9ef (patch)
tree1f0a6b536a1bb7b24585973e70ad8e1a9a076f09
parentc42d9f32443397aed2d37d37df161392e6a5862f (diff)
x64, x2apic/intr-remap: code re-structuring, to be used by both DMA and Interrupt remapping
Allocate the iommu during the parse of DMA remapping hardware definition structures. And also, introduce routines for device scope initialization which will be explicitly called during dma-remapping initialization. These will be used for enabling interrupt remapping separately from the existing DMA-remapping enabling sequence. 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/dmar.c89
-rw-r--r--drivers/pci/intel-iommu.c10
-rw-r--r--drivers/pci/intel-iommu.h2
-rw-r--r--include/linux/dmar.h10
4 files changed, 88 insertions, 23 deletions
diff --git a/drivers/pci/dmar.c b/drivers/pci/dmar.c
index 1a59423a8eda..158bc5bfcf75 100644
--- a/drivers/pci/dmar.c
+++ b/drivers/pci/dmar.c
@@ -174,19 +174,37 @@ dmar_parse_one_drhd(struct acpi_dmar_header *header)
174 struct acpi_dmar_hardware_unit *drhd; 174 struct acpi_dmar_hardware_unit *drhd;
175 struct dmar_drhd_unit *dmaru; 175 struct dmar_drhd_unit *dmaru;
176 int ret = 0; 176 int ret = 0;
177 static int include_all;
178 177
179 dmaru = kzalloc(sizeof(*dmaru), GFP_KERNEL); 178 dmaru = kzalloc(sizeof(*dmaru), GFP_KERNEL);
180 if (!dmaru) 179 if (!dmaru)
181 return -ENOMEM; 180 return -ENOMEM;
182 181
182 dmaru->hdr = header;
183 drhd = (struct acpi_dmar_hardware_unit *)header; 183 drhd = (struct acpi_dmar_hardware_unit *)header;
184 dmaru->reg_base_addr = drhd->address; 184 dmaru->reg_base_addr = drhd->address;
185 dmaru->include_all = drhd->flags & 0x1; /* BIT0: INCLUDE_ALL */ 185 dmaru->include_all = drhd->flags & 0x1; /* BIT0: INCLUDE_ALL */
186 186
187 ret = alloc_iommu(dmaru);
188 if (ret) {
189 kfree(dmaru);
190 return ret;
191 }
192 dmar_register_drhd_unit(dmaru);
193 return 0;
194}
195
196static int __init
197dmar_parse_dev(struct dmar_drhd_unit *dmaru)
198{
199 struct acpi_dmar_hardware_unit *drhd;
200 static int include_all;
201 int ret;
202
203 drhd = (struct acpi_dmar_hardware_unit *) dmaru->hdr;
204
187 if (!dmaru->include_all) 205 if (!dmaru->include_all)
188 ret = dmar_parse_dev_scope((void *)(drhd + 1), 206 ret = dmar_parse_dev_scope((void *)(drhd + 1),
189 ((void *)drhd) + header->length, 207 ((void *)drhd) + drhd->header.length,
190 &dmaru->devices_cnt, &dmaru->devices, 208 &dmaru->devices_cnt, &dmaru->devices,
191 drhd->segment); 209 drhd->segment);
192 else { 210 else {
@@ -199,10 +217,10 @@ dmar_parse_one_drhd(struct acpi_dmar_header *header)
199 include_all = 1; 217 include_all = 1;
200 } 218 }
201 219
202 if (ret || (dmaru->devices_cnt == 0 && !dmaru->include_all)) 220 if (ret || (dmaru->devices_cnt == 0 && !dmaru->include_all)) {
221 list_del(&dmaru->list);
203 kfree(dmaru); 222 kfree(dmaru);
204 else 223 }
205 dmar_register_drhd_unit(dmaru);
206 return ret; 224 return ret;
207} 225}
208 226
@@ -211,23 +229,35 @@ dmar_parse_one_rmrr(struct acpi_dmar_header *header)
211{ 229{
212 struct acpi_dmar_reserved_memory *rmrr; 230 struct acpi_dmar_reserved_memory *rmrr;
213 struct dmar_rmrr_unit *rmrru; 231 struct dmar_rmrr_unit *rmrru;
214 int ret = 0;
215 232
216 rmrru = kzalloc(sizeof(*rmrru), GFP_KERNEL); 233 rmrru = kzalloc(sizeof(*rmrru), GFP_KERNEL);
217 if (!rmrru) 234 if (!rmrru)
218 return -ENOMEM; 235 return -ENOMEM;
219 236
237 rmrru->hdr = header;
220 rmrr = (struct acpi_dmar_reserved_memory *)header; 238 rmrr = (struct acpi_dmar_reserved_memory *)header;
221 rmrru->base_address = rmrr->base_address; 239 rmrru->base_address = rmrr->base_address;
222 rmrru->end_address = rmrr->end_address; 240 rmrru->end_address = rmrr->end_address;
241
242 dmar_register_rmrr_unit(rmrru);
243 return 0;
244}
245
246static int __init
247rmrr_parse_dev(struct dmar_rmrr_unit *rmrru)
248{
249 struct acpi_dmar_reserved_memory *rmrr;
250 int ret;
251
252 rmrr = (struct acpi_dmar_reserved_memory *) rmrru->hdr;
223 ret = dmar_parse_dev_scope((void *)(rmrr + 1), 253 ret = dmar_parse_dev_scope((void *)(rmrr + 1),
224 ((void *)rmrr) + header->length, 254 ((void *)rmrr) + rmrr->header.length,
225 &rmrru->devices_cnt, &rmrru->devices, rmrr->segment); 255 &rmrru->devices_cnt, &rmrru->devices, rmrr->segment);
226 256
227 if (ret || (rmrru->devices_cnt == 0)) 257 if (ret || (rmrru->devices_cnt == 0)) {
258 list_del(&rmrru->list);
228 kfree(rmrru); 259 kfree(rmrru);
229 else 260 }
230 dmar_register_rmrr_unit(rmrru);
231 return ret; 261 return ret;
232} 262}
233 263
@@ -333,15 +363,42 @@ dmar_find_matched_drhd_unit(struct pci_dev *dev)
333 return NULL; 363 return NULL;
334} 364}
335 365
366int __init dmar_dev_scope_init(void)
367{
368 struct dmar_drhd_unit *drhd;
369 struct dmar_rmrr_unit *rmrr;
370 int ret = -ENODEV;
371
372 for_each_drhd_unit(drhd) {
373 ret = dmar_parse_dev(drhd);
374 if (ret)
375 return ret;
376 }
377
378 for_each_rmrr_units(rmrr) {
379 ret = rmrr_parse_dev(rmrr);
380 if (ret)
381 return ret;
382 }
383
384 return ret;
385}
386
336 387
337int __init dmar_table_init(void) 388int __init dmar_table_init(void)
338{ 389{
339 390 static int dmar_table_initialized;
340 int ret; 391 int ret;
341 392
393 if (dmar_table_initialized)
394 return 0;
395
396 dmar_table_initialized = 1;
397
342 ret = parse_dmar_table(); 398 ret = parse_dmar_table();
343 if (ret) { 399 if (ret) {
344 printk(KERN_INFO PREFIX "parse DMAR table failure.\n"); 400 if (ret != -ENODEV)
401 printk(KERN_INFO PREFIX "parse DMAR table failure.\n");
345 return ret; 402 return ret;
346 } 403 }
347 404
@@ -377,7 +434,7 @@ int __init early_dmar_detect(void)
377 return (ACPI_SUCCESS(status) ? 1 : 0); 434 return (ACPI_SUCCESS(status) ? 1 : 0);
378} 435}
379 436
380struct intel_iommu *alloc_iommu(struct dmar_drhd_unit *drhd) 437int alloc_iommu(struct dmar_drhd_unit *drhd)
381{ 438{
382 struct intel_iommu *iommu; 439 struct intel_iommu *iommu;
383 int map_size; 440 int map_size;
@@ -386,7 +443,7 @@ struct intel_iommu *alloc_iommu(struct dmar_drhd_unit *drhd)
386 443
387 iommu = kzalloc(sizeof(*iommu), GFP_KERNEL); 444 iommu = kzalloc(sizeof(*iommu), GFP_KERNEL);
388 if (!iommu) 445 if (!iommu)
389 return NULL; 446 return -ENOMEM;
390 447
391 iommu->seq_id = iommu_allocated++; 448 iommu->seq_id = iommu_allocated++;
392 449
@@ -419,10 +476,10 @@ struct intel_iommu *alloc_iommu(struct dmar_drhd_unit *drhd)
419 spin_lock_init(&iommu->register_lock); 476 spin_lock_init(&iommu->register_lock);
420 477
421 drhd->iommu = iommu; 478 drhd->iommu = iommu;
422 return iommu; 479 return 0;
423error: 480error:
424 kfree(iommu); 481 kfree(iommu);
425 return NULL; 482 return -1;
426} 483}
427 484
428void free_iommu(struct intel_iommu *iommu) 485void free_iommu(struct intel_iommu *iommu)
diff --git a/drivers/pci/intel-iommu.c b/drivers/pci/intel-iommu.c
index 4d59a6a1f4dd..218a1f357b4d 100644
--- a/drivers/pci/intel-iommu.c
+++ b/drivers/pci/intel-iommu.c
@@ -1665,11 +1665,8 @@ int __init init_dmars(void)
1665 for_each_drhd_unit(drhd) { 1665 for_each_drhd_unit(drhd) {
1666 if (drhd->ignored) 1666 if (drhd->ignored)
1667 continue; 1667 continue;
1668 iommu = alloc_iommu(drhd); 1668
1669 if (!iommu) { 1669 iommu = drhd->iommu;
1670 ret = -ENOMEM;
1671 goto error;
1672 }
1673 1670
1674 ret = iommu_init_domains(iommu); 1671 ret = iommu_init_domains(iommu);
1675 if (ret) 1672 if (ret)
@@ -2324,6 +2321,9 @@ int __init intel_iommu_init(void)
2324 if (dmar_table_init()) 2321 if (dmar_table_init())
2325 return -ENODEV; 2322 return -ENODEV;
2326 2323
2324 if (dmar_dev_scope_init())
2325 return -ENODEV;
2326
2327 iommu_init_mempool(); 2327 iommu_init_mempool();
2328 dmar_init_reserved_ranges(); 2328 dmar_init_reserved_ranges();
2329 2329
diff --git a/drivers/pci/intel-iommu.h b/drivers/pci/intel-iommu.h
index 75c63f65b3f5..371e3b9caf32 100644
--- a/drivers/pci/intel-iommu.h
+++ b/drivers/pci/intel-iommu.h
@@ -199,7 +199,7 @@ struct intel_iommu {
199 199
200extern struct dmar_drhd_unit * dmar_find_matched_drhd_unit(struct pci_dev *dev); 200extern struct dmar_drhd_unit * dmar_find_matched_drhd_unit(struct pci_dev *dev);
201 201
202extern struct intel_iommu *alloc_iommu(struct dmar_drhd_unit *drhd); 202extern int alloc_iommu(struct dmar_drhd_unit *drhd);
203extern void free_iommu(struct intel_iommu *iommu); 203extern void free_iommu(struct intel_iommu *iommu);
204 204
205#endif 205#endif
diff --git a/include/linux/dmar.h b/include/linux/dmar.h
index 56c73b847551..3ab07e425583 100644
--- a/include/linux/dmar.h
+++ b/include/linux/dmar.h
@@ -46,12 +46,14 @@ extern int intel_iommu_init(void);
46 46
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);
49 50
50extern struct list_head dmar_drhd_units; 51extern struct list_head dmar_drhd_units;
51extern struct list_head dmar_rmrr_units; 52extern struct list_head dmar_rmrr_units;
52 53
53struct dmar_drhd_unit { 54struct dmar_drhd_unit {
54 struct list_head list; /* list of drhd units */ 55 struct list_head list; /* list of drhd units */
56 struct acpi_dmar_header *hdr; /* ACPI header */
55 u64 reg_base_addr; /* register base address*/ 57 u64 reg_base_addr; /* register base address*/
56 struct pci_dev **devices; /* target device array */ 58 struct pci_dev **devices; /* target device array */
57 int devices_cnt; /* target device count */ 59 int devices_cnt; /* target device count */
@@ -62,6 +64,7 @@ struct dmar_drhd_unit {
62 64
63struct dmar_rmrr_unit { 65struct dmar_rmrr_unit {
64 struct list_head list; /* list of rmrr units */ 66 struct list_head list; /* list of rmrr units */
67 struct acpi_dmar_header *hdr; /* ACPI header */
65 u64 base_address; /* reserved base address*/ 68 u64 base_address; /* reserved base address*/
66 u64 end_address; /* reserved end address */ 69 u64 end_address; /* reserved end address */
67 struct pci_dev **devices; /* target devices */ 70 struct pci_dev **devices; /* target devices */
@@ -72,6 +75,8 @@ struct dmar_rmrr_unit {
72 list_for_each_entry(drhd, &dmar_drhd_units, list) 75 list_for_each_entry(drhd, &dmar_drhd_units, list)
73#define for_each_rmrr_units(rmrr) \ 76#define for_each_rmrr_units(rmrr) \
74 list_for_each_entry(rmrr, &dmar_rmrr_units, list) 77 list_for_each_entry(rmrr, &dmar_rmrr_units, list)
78
79extern int alloc_iommu(struct dmar_drhd_unit *);
75#else 80#else
76static inline void detect_intel_iommu(void) 81static inline void detect_intel_iommu(void)
77{ 82{
@@ -81,6 +86,9 @@ static inline int intel_iommu_init(void)
81{ 86{
82 return -ENODEV; 87 return -ENODEV;
83} 88}
84 89static inline int dmar_table_init(void)
90{
91 return -ENODEV;
92}
85#endif /* !CONFIG_DMAR */ 93#endif /* !CONFIG_DMAR */
86#endif /* __DMAR_H__ */ 94#endif /* __DMAR_H__ */