diff options
author | Linus Torvalds <torvalds@linux-foundation.org> | 2010-05-21 20:25:01 -0400 |
---|---|---|
committer | Linus Torvalds <torvalds@linux-foundation.org> | 2010-05-21 20:25:01 -0400 |
commit | 0961d6581c870850342ad6ea25263763433d666f (patch) | |
tree | 371c61fd7f621397907983031003e784a040402e /drivers/pci/dmar.c | |
parent | 1756ac3d3c41341297ea25b818b7fce505bb2a9a (diff) | |
parent | fd0c8894893cba722bdea12de25b49f980795d06 (diff) |
Merge git://git.infradead.org/iommu-2.6
* git://git.infradead.org/iommu-2.6:
intel-iommu: Set a more specific taint flag for invalid BIOS DMAR tables
intel-iommu: Combine the BIOS DMAR table warning messages
panic: Add taint flag TAINT_FIRMWARE_WORKAROUND ('I')
panic: Allow warnings to set different taint flags
intel-iommu: intel_iommu_map_range failed at very end of address space
intel-iommu: errors with smaller iommu widths
intel-iommu: Fix boot inside 64bit virtualbox with io-apic disabled
intel-iommu: use physfn to search drhd for VF
intel-iommu: Print out iommu seq_id
intel-iommu: Don't complain that ACPI_DMAR_SCOPE_TYPE_IOAPIC is not supported
intel-iommu: Avoid global flushes with caching mode.
intel-iommu: Use correct domain ID when caching mode is enabled
intel-iommu mistakenly uses offset_pfn when caching mode is enabled
intel-iommu: use for_each_set_bit()
intel-iommu: Fix section mismatch dmar_ir_support() uses dmar_tbl.
Diffstat (limited to 'drivers/pci/dmar.c')
-rw-r--r-- | drivers/pci/dmar.c | 82 |
1 files changed, 37 insertions, 45 deletions
diff --git a/drivers/pci/dmar.c b/drivers/pci/dmar.c index 33ead97f0c4b..0a19708074c2 100644 --- a/drivers/pci/dmar.c +++ b/drivers/pci/dmar.c | |||
@@ -131,9 +131,10 @@ static int __init dmar_parse_dev_scope(void *start, void *end, int *cnt, | |||
131 | if (scope->entry_type == ACPI_DMAR_SCOPE_TYPE_ENDPOINT || | 131 | if (scope->entry_type == ACPI_DMAR_SCOPE_TYPE_ENDPOINT || |
132 | scope->entry_type == ACPI_DMAR_SCOPE_TYPE_BRIDGE) | 132 | scope->entry_type == ACPI_DMAR_SCOPE_TYPE_BRIDGE) |
133 | (*cnt)++; | 133 | (*cnt)++; |
134 | else | 134 | else if (scope->entry_type != ACPI_DMAR_SCOPE_TYPE_IOAPIC) { |
135 | printk(KERN_WARNING PREFIX | 135 | printk(KERN_WARNING PREFIX |
136 | "Unsupported device scope\n"); | 136 | "Unsupported device scope\n"); |
137 | } | ||
137 | start += scope->length; | 138 | start += scope->length; |
138 | } | 139 | } |
139 | if (*cnt == 0) | 140 | if (*cnt == 0) |
@@ -309,6 +310,8 @@ int dmar_find_matched_atsr_unit(struct pci_dev *dev) | |||
309 | struct acpi_dmar_atsr *atsr; | 310 | struct acpi_dmar_atsr *atsr; |
310 | struct dmar_atsr_unit *atsru; | 311 | struct dmar_atsr_unit *atsru; |
311 | 312 | ||
313 | dev = pci_physfn(dev); | ||
314 | |||
312 | list_for_each_entry(atsru, &dmar_atsr_units, list) { | 315 | list_for_each_entry(atsru, &dmar_atsr_units, list) { |
313 | atsr = container_of(atsru->hdr, struct acpi_dmar_atsr, header); | 316 | atsr = container_of(atsru->hdr, struct acpi_dmar_atsr, header); |
314 | if (atsr->segment == pci_domain_nr(dev->bus)) | 317 | if (atsr->segment == pci_domain_nr(dev->bus)) |
@@ -358,12 +361,14 @@ dmar_parse_one_rhsa(struct acpi_dmar_header *header) | |||
358 | return 0; | 361 | return 0; |
359 | } | 362 | } |
360 | } | 363 | } |
361 | WARN(1, "Your BIOS is broken; RHSA refers to non-existent DMAR unit at %llx\n" | 364 | WARN_TAINT( |
362 | "BIOS vendor: %s; Ver: %s; Product Version: %s\n", | 365 | 1, TAINT_FIRMWARE_WORKAROUND, |
363 | drhd->reg_base_addr, | 366 | "Your BIOS is broken; RHSA refers to non-existent DMAR unit at %llx\n" |
364 | dmi_get_system_info(DMI_BIOS_VENDOR), | 367 | "BIOS vendor: %s; Ver: %s; Product Version: %s\n", |
365 | dmi_get_system_info(DMI_BIOS_VERSION), | 368 | drhd->reg_base_addr, |
366 | dmi_get_system_info(DMI_PRODUCT_VERSION)); | 369 | dmi_get_system_info(DMI_BIOS_VENDOR), |
370 | dmi_get_system_info(DMI_BIOS_VERSION), | ||
371 | dmi_get_system_info(DMI_PRODUCT_VERSION)); | ||
367 | 372 | ||
368 | return 0; | 373 | return 0; |
369 | } | 374 | } |
@@ -507,7 +512,7 @@ parse_dmar_table(void) | |||
507 | return ret; | 512 | return ret; |
508 | } | 513 | } |
509 | 514 | ||
510 | int dmar_pci_device_match(struct pci_dev *devices[], int cnt, | 515 | static int dmar_pci_device_match(struct pci_dev *devices[], int cnt, |
511 | struct pci_dev *dev) | 516 | struct pci_dev *dev) |
512 | { | 517 | { |
513 | int index; | 518 | int index; |
@@ -530,6 +535,8 @@ dmar_find_matched_drhd_unit(struct pci_dev *dev) | |||
530 | struct dmar_drhd_unit *dmaru = NULL; | 535 | struct dmar_drhd_unit *dmaru = NULL; |
531 | struct acpi_dmar_hardware_unit *drhd; | 536 | struct acpi_dmar_hardware_unit *drhd; |
532 | 537 | ||
538 | dev = pci_physfn(dev); | ||
539 | |||
533 | list_for_each_entry(dmaru, &dmar_drhd_units, list) { | 540 | list_for_each_entry(dmaru, &dmar_drhd_units, list) { |
534 | drhd = container_of(dmaru->hdr, | 541 | drhd = container_of(dmaru->hdr, |
535 | struct acpi_dmar_hardware_unit, | 542 | struct acpi_dmar_hardware_unit, |
@@ -614,7 +621,17 @@ int __init dmar_table_init(void) | |||
614 | return 0; | 621 | return 0; |
615 | } | 622 | } |
616 | 623 | ||
617 | static int bios_warned; | 624 | static void warn_invalid_dmar(u64 addr, const char *message) |
625 | { | ||
626 | WARN_TAINT_ONCE( | ||
627 | 1, TAINT_FIRMWARE_WORKAROUND, | ||
628 | "Your BIOS is broken; DMAR reported at address %llx%s!\n" | ||
629 | "BIOS vendor: %s; Ver: %s; Product Version: %s\n", | ||
630 | addr, message, | ||
631 | dmi_get_system_info(DMI_BIOS_VENDOR), | ||
632 | dmi_get_system_info(DMI_BIOS_VERSION), | ||
633 | dmi_get_system_info(DMI_PRODUCT_VERSION)); | ||
634 | } | ||
618 | 635 | ||
619 | int __init check_zero_address(void) | 636 | int __init check_zero_address(void) |
620 | { | 637 | { |
@@ -640,13 +657,7 @@ int __init check_zero_address(void) | |||
640 | 657 | ||
641 | drhd = (void *)entry_header; | 658 | drhd = (void *)entry_header; |
642 | if (!drhd->address) { | 659 | if (!drhd->address) { |
643 | /* Promote an attitude of violence to a BIOS engineer today */ | 660 | warn_invalid_dmar(0, ""); |
644 | WARN(1, "Your BIOS is broken; DMAR reported at address zero!\n" | ||
645 | "BIOS vendor: %s; Ver: %s; Product Version: %s\n", | ||
646 | dmi_get_system_info(DMI_BIOS_VENDOR), | ||
647 | dmi_get_system_info(DMI_BIOS_VERSION), | ||
648 | dmi_get_system_info(DMI_PRODUCT_VERSION)); | ||
649 | bios_warned = 1; | ||
650 | goto failed; | 661 | goto failed; |
651 | } | 662 | } |
652 | 663 | ||
@@ -659,14 +670,8 @@ int __init check_zero_address(void) | |||
659 | ecap = dmar_readq(addr + DMAR_ECAP_REG); | 670 | ecap = dmar_readq(addr + DMAR_ECAP_REG); |
660 | early_iounmap(addr, VTD_PAGE_SIZE); | 671 | early_iounmap(addr, VTD_PAGE_SIZE); |
661 | if (cap == (uint64_t)-1 && ecap == (uint64_t)-1) { | 672 | if (cap == (uint64_t)-1 && ecap == (uint64_t)-1) { |
662 | /* Promote an attitude of violence to a BIOS engineer today */ | 673 | warn_invalid_dmar(drhd->address, |
663 | WARN(1, "Your BIOS is broken; DMAR reported at address %llx returns all ones!\n" | 674 | " returns all ones"); |
664 | "BIOS vendor: %s; Ver: %s; Product Version: %s\n", | ||
665 | drhd->address, | ||
666 | dmi_get_system_info(DMI_BIOS_VENDOR), | ||
667 | dmi_get_system_info(DMI_BIOS_VERSION), | ||
668 | dmi_get_system_info(DMI_PRODUCT_VERSION)); | ||
669 | bios_warned = 1; | ||
670 | goto failed; | 675 | goto failed; |
671 | } | 676 | } |
672 | } | 677 | } |
@@ -731,14 +736,7 @@ int alloc_iommu(struct dmar_drhd_unit *drhd) | |||
731 | int msagaw = 0; | 736 | int msagaw = 0; |
732 | 737 | ||
733 | if (!drhd->reg_base_addr) { | 738 | if (!drhd->reg_base_addr) { |
734 | if (!bios_warned) { | 739 | warn_invalid_dmar(0, ""); |
735 | WARN(1, "Your BIOS is broken; DMAR reported at address zero!\n" | ||
736 | "BIOS vendor: %s; Ver: %s; Product Version: %s\n", | ||
737 | dmi_get_system_info(DMI_BIOS_VENDOR), | ||
738 | dmi_get_system_info(DMI_BIOS_VERSION), | ||
739 | dmi_get_system_info(DMI_PRODUCT_VERSION)); | ||
740 | bios_warned = 1; | ||
741 | } | ||
742 | return -EINVAL; | 740 | return -EINVAL; |
743 | } | 741 | } |
744 | 742 | ||
@@ -758,16 +756,7 @@ int alloc_iommu(struct dmar_drhd_unit *drhd) | |||
758 | iommu->ecap = dmar_readq(iommu->reg + DMAR_ECAP_REG); | 756 | iommu->ecap = dmar_readq(iommu->reg + DMAR_ECAP_REG); |
759 | 757 | ||
760 | if (iommu->cap == (uint64_t)-1 && iommu->ecap == (uint64_t)-1) { | 758 | if (iommu->cap == (uint64_t)-1 && iommu->ecap == (uint64_t)-1) { |
761 | if (!bios_warned) { | 759 | warn_invalid_dmar(drhd->reg_base_addr, " returns all ones"); |
762 | /* Promote an attitude of violence to a BIOS engineer today */ | ||
763 | WARN(1, "Your BIOS is broken; DMAR reported at address %llx returns all ones!\n" | ||
764 | "BIOS vendor: %s; Ver: %s; Product Version: %s\n", | ||
765 | drhd->reg_base_addr, | ||
766 | dmi_get_system_info(DMI_BIOS_VENDOR), | ||
767 | dmi_get_system_info(DMI_BIOS_VERSION), | ||
768 | dmi_get_system_info(DMI_PRODUCT_VERSION)); | ||
769 | bios_warned = 1; | ||
770 | } | ||
771 | goto err_unmap; | 760 | goto err_unmap; |
772 | } | 761 | } |
773 | 762 | ||
@@ -806,7 +795,8 @@ int alloc_iommu(struct dmar_drhd_unit *drhd) | |||
806 | } | 795 | } |
807 | 796 | ||
808 | ver = readl(iommu->reg + DMAR_VER_REG); | 797 | ver = readl(iommu->reg + DMAR_VER_REG); |
809 | pr_info("IOMMU %llx: ver %d:%d cap %llx ecap %llx\n", | 798 | pr_info("IOMMU %d: reg_base_addr %llx ver %d:%d cap %llx ecap %llx\n", |
799 | iommu->seq_id, | ||
810 | (unsigned long long)drhd->reg_base_addr, | 800 | (unsigned long long)drhd->reg_base_addr, |
811 | DMAR_VER_MAJOR(ver), DMAR_VER_MINOR(ver), | 801 | DMAR_VER_MAJOR(ver), DMAR_VER_MINOR(ver), |
812 | (unsigned long long)iommu->cap, | 802 | (unsigned long long)iommu->cap, |
@@ -1457,9 +1447,11 @@ int dmar_reenable_qi(struct intel_iommu *iommu) | |||
1457 | /* | 1447 | /* |
1458 | * Check interrupt remapping support in DMAR table description. | 1448 | * Check interrupt remapping support in DMAR table description. |
1459 | */ | 1449 | */ |
1460 | int dmar_ir_support(void) | 1450 | int __init dmar_ir_support(void) |
1461 | { | 1451 | { |
1462 | struct acpi_table_dmar *dmar; | 1452 | struct acpi_table_dmar *dmar; |
1463 | dmar = (struct acpi_table_dmar *)dmar_tbl; | 1453 | dmar = (struct acpi_table_dmar *)dmar_tbl; |
1454 | if (!dmar) | ||
1455 | return 0; | ||
1464 | return dmar->flags & 0x1; | 1456 | return dmar->flags & 0x1; |
1465 | } | 1457 | } |