diff options
author | David Woodhouse <David.Woodhouse@intel.com> | 2009-12-08 04:58:33 -0500 |
---|---|---|
committer | David Woodhouse <David.Woodhouse@intel.com> | 2009-12-08 04:59:24 -0500 |
commit | ec208491936d6adb8a70c3dd4a517cdfe54e823d (patch) | |
tree | c7291450e8e559c5fbf3360df30999432204af3c /drivers/pci/dmar.c | |
parent | aa697079ee66315c4b9747a5eb3e48487fb1b8be (diff) | |
parent | 7b626acb8f983eb83b396ab96cc24b18d635d487 (diff) |
Merge branch 'master' of git://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux-2.6
Merge the BIOS workarounds from 2.6.32, and the swiotlb fallback on failure.
Diffstat (limited to 'drivers/pci/dmar.c')
-rw-r--r-- | drivers/pci/dmar.c | 59 |
1 files changed, 47 insertions, 12 deletions
diff --git a/drivers/pci/dmar.c b/drivers/pci/dmar.c index 0d064d1e840a..525a32487abd 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; |
@@ -622,12 +613,53 @@ int __init dmar_table_init(void) | |||
622 | return 0; | 613 | return 0; |
623 | } | 614 | } |
624 | 615 | ||
616 | int __init check_zero_address(void) | ||
617 | { | ||
618 | struct acpi_table_dmar *dmar; | ||
619 | struct acpi_dmar_header *entry_header; | ||
620 | struct acpi_dmar_hardware_unit *drhd; | ||
621 | |||
622 | dmar = (struct acpi_table_dmar *)dmar_tbl; | ||
623 | entry_header = (struct acpi_dmar_header *)(dmar + 1); | ||
624 | |||
625 | while (((unsigned long)entry_header) < | ||
626 | (((unsigned long)dmar) + dmar_tbl->length)) { | ||
627 | /* Avoid looping forever on bad ACPI tables */ | ||
628 | if (entry_header->length == 0) { | ||
629 | printk(KERN_WARNING PREFIX | ||
630 | "Invalid 0-length structure\n"); | ||
631 | return 0; | ||
632 | } | ||
633 | |||
634 | if (entry_header->type == ACPI_DMAR_TYPE_HARDWARE_UNIT) { | ||
635 | drhd = (void *)entry_header; | ||
636 | if (!drhd->address) { | ||
637 | /* Promote an attitude of violence to a BIOS engineer today */ | ||
638 | WARN(1, "Your BIOS is broken; DMAR reported at address zero!\n" | ||
639 | "BIOS vendor: %s; Ver: %s; Product Version: %s\n", | ||
640 | dmi_get_system_info(DMI_BIOS_VENDOR), | ||
641 | dmi_get_system_info(DMI_BIOS_VERSION), | ||
642 | dmi_get_system_info(DMI_PRODUCT_VERSION)); | ||
643 | #ifdef CONFIG_DMAR | ||
644 | dmar_disabled = 1; | ||
645 | #endif | ||
646 | return 0; | ||
647 | } | ||
648 | break; | ||
649 | } | ||
650 | |||
651 | entry_header = ((void *)entry_header + entry_header->length); | ||
652 | } | ||
653 | return 1; | ||
654 | } | ||
655 | |||
625 | void __init detect_intel_iommu(void) | 656 | void __init detect_intel_iommu(void) |
626 | { | 657 | { |
627 | int ret; | 658 | int ret; |
628 | 659 | ||
629 | ret = dmar_table_detect(); | 660 | ret = dmar_table_detect(); |
630 | 661 | if (ret) | |
662 | ret = check_zero_address(); | ||
631 | { | 663 | { |
632 | #ifdef CONFIG_INTR_REMAP | 664 | #ifdef CONFIG_INTR_REMAP |
633 | struct acpi_table_dmar *dmar; | 665 | struct acpi_table_dmar *dmar; |
@@ -644,10 +676,13 @@ void __init detect_intel_iommu(void) | |||
644 | "x2apic and Intr-remapping.\n"); | 676 | "x2apic and Intr-remapping.\n"); |
645 | #endif | 677 | #endif |
646 | #ifdef CONFIG_DMAR | 678 | #ifdef CONFIG_DMAR |
647 | if (ret && !no_iommu && !iommu_detected && !swiotlb && | 679 | if (ret && !no_iommu && !iommu_detected && !dmar_disabled) |
648 | !dmar_disabled) | ||
649 | iommu_detected = 1; | 680 | iommu_detected = 1; |
650 | #endif | 681 | #endif |
682 | #ifdef CONFIG_X86 | ||
683 | if (ret) | ||
684 | x86_init.iommu.iommu_init = intel_iommu_init; | ||
685 | #endif | ||
651 | } | 686 | } |
652 | early_acpi_os_unmap_memory(dmar_tbl, dmar_tbl_size); | 687 | early_acpi_os_unmap_memory(dmar_tbl, dmar_tbl_size); |
653 | dmar_tbl = NULL; | 688 | dmar_tbl = NULL; |