aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/pci/dmar.c
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/pci/dmar.c')
-rw-r--r--drivers/pci/dmar.c62
1 files changed, 51 insertions, 11 deletions
diff --git a/drivers/pci/dmar.c b/drivers/pci/dmar.c
index 14bbaa17e2ca..e5f8fc164fd3 100644
--- a/drivers/pci/dmar.c
+++ b/drivers/pci/dmar.c
@@ -175,15 +175,6 @@ dmar_parse_one_drhd(struct acpi_dmar_header *header)
175 int ret = 0; 175 int ret = 0;
176 176
177 drhd = (struct acpi_dmar_hardware_unit *)header; 177 drhd = (struct acpi_dmar_hardware_unit *)header;
178 if (!drhd->address) {
179 /* Promote an attitude of violence to a BIOS engineer today */
180 WARN(1, "Your BIOS is broken; DMAR reported at address zero!\n"
181 "BIOS vendor: %s; Ver: %s; Product Version: %s\n",
182 dmi_get_system_info(DMI_BIOS_VENDOR),
183 dmi_get_system_info(DMI_BIOS_VERSION),
184 dmi_get_system_info(DMI_PRODUCT_VERSION));
185 return -ENODEV;
186 }
187 dmaru = kzalloc(sizeof(*dmaru), GFP_KERNEL); 178 dmaru = kzalloc(sizeof(*dmaru), GFP_KERNEL);
188 if (!dmaru) 179 if (!dmaru)
189 return -ENOMEM; 180 return -ENOMEM;
@@ -354,6 +345,7 @@ dmar_table_print_dmar_entry(struct acpi_dmar_header *header)
354 struct acpi_dmar_hardware_unit *drhd; 345 struct acpi_dmar_hardware_unit *drhd;
355 struct acpi_dmar_reserved_memory *rmrr; 346 struct acpi_dmar_reserved_memory *rmrr;
356 struct acpi_dmar_atsr *atsr; 347 struct acpi_dmar_atsr *atsr;
348 struct acpi_dmar_rhsa *rhsa;
357 349
358 switch (header->type) { 350 switch (header->type) {
359 case ACPI_DMAR_TYPE_HARDWARE_UNIT: 351 case ACPI_DMAR_TYPE_HARDWARE_UNIT:
@@ -375,6 +367,12 @@ dmar_table_print_dmar_entry(struct acpi_dmar_header *header)
375 atsr = container_of(header, struct acpi_dmar_atsr, header); 367 atsr = container_of(header, struct acpi_dmar_atsr, header);
376 printk(KERN_INFO PREFIX "ATSR flags: %#x\n", atsr->flags); 368 printk(KERN_INFO PREFIX "ATSR flags: %#x\n", atsr->flags);
377 break; 369 break;
370 case ACPI_DMAR_HARDWARE_AFFINITY:
371 rhsa = container_of(header, struct acpi_dmar_rhsa, header);
372 printk(KERN_INFO PREFIX "RHSA base: %#016Lx proximity domain: %#x\n",
373 (unsigned long long)rhsa->base_address,
374 rhsa->proximity_domain);
375 break;
378 } 376 }
379} 377}
380 378
@@ -459,9 +457,13 @@ parse_dmar_table(void)
459 ret = dmar_parse_one_atsr(entry_header); 457 ret = dmar_parse_one_atsr(entry_header);
460#endif 458#endif
461 break; 459 break;
460 case ACPI_DMAR_HARDWARE_AFFINITY:
461 /* We don't do anything with RHSA (yet?) */
462 break;
462 default: 463 default:
463 printk(KERN_WARNING PREFIX 464 printk(KERN_WARNING PREFIX
464 "Unknown DMAR structure type\n"); 465 "Unknown DMAR structure type %d\n",
466 entry_header->type);
465 ret = 0; /* for forward compatibility */ 467 ret = 0; /* for forward compatibility */
466 break; 468 break;
467 } 469 }
@@ -580,12 +582,50 @@ int __init dmar_table_init(void)
580 return 0; 582 return 0;
581} 583}
582 584
585int __init check_zero_address(void)
586{
587 struct acpi_table_dmar *dmar;
588 struct acpi_dmar_header *entry_header;
589 struct acpi_dmar_hardware_unit *drhd;
590
591 dmar = (struct acpi_table_dmar *)dmar_tbl;
592 entry_header = (struct acpi_dmar_header *)(dmar + 1);
593
594 while (((unsigned long)entry_header) <
595 (((unsigned long)dmar) + dmar_tbl->length)) {
596 /* Avoid looping forever on bad ACPI tables */
597 if (entry_header->length == 0) {
598 printk(KERN_WARNING PREFIX
599 "Invalid 0-length structure\n");
600 return 0;
601 }
602
603 if (entry_header->type == ACPI_DMAR_TYPE_HARDWARE_UNIT) {
604 drhd = (void *)entry_header;
605 if (!drhd->address) {
606 /* Promote an attitude of violence to a BIOS engineer today */
607 WARN(1, "Your BIOS is broken; DMAR reported at address zero!\n"
608 "BIOS vendor: %s; Ver: %s; Product Version: %s\n",
609 dmi_get_system_info(DMI_BIOS_VENDOR),
610 dmi_get_system_info(DMI_BIOS_VERSION),
611 dmi_get_system_info(DMI_PRODUCT_VERSION));
612 return 0;
613 }
614 break;
615 }
616
617 entry_header = ((void *)entry_header + entry_header->length);
618 }
619 return 1;
620}
621
583void __init detect_intel_iommu(void) 622void __init detect_intel_iommu(void)
584{ 623{
585 int ret; 624 int ret;
586 625
587 ret = dmar_table_detect(); 626 ret = dmar_table_detect();
588 627 if (ret)
628 ret = check_zero_address();
589 { 629 {
590#ifdef CONFIG_INTR_REMAP 630#ifdef CONFIG_INTR_REMAP
591 struct acpi_table_dmar *dmar; 631 struct acpi_table_dmar *dmar;