aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/pci/dmar.c
diff options
context:
space:
mode:
authorLinus Torvalds <torvalds@linux-foundation.org>2010-05-21 20:25:01 -0400
committerLinus Torvalds <torvalds@linux-foundation.org>2010-05-21 20:25:01 -0400
commit0961d6581c870850342ad6ea25263763433d666f (patch)
tree371c61fd7f621397907983031003e784a040402e /drivers/pci/dmar.c
parent1756ac3d3c41341297ea25b818b7fce505bb2a9a (diff)
parentfd0c8894893cba722bdea12de25b49f980795d06 (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.c82
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
510int dmar_pci_device_match(struct pci_dev *devices[], int cnt, 515static 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
617static int bios_warned; 624static 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
619int __init check_zero_address(void) 636int __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 */
1460int dmar_ir_support(void) 1450int __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}