aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/pci
diff options
context:
space:
mode:
authorDavid Woodhouse <David.Woodhouse@intel.com>2009-08-04 04:17:20 -0400
committerDavid Woodhouse <David.Woodhouse@intel.com>2009-08-04 04:17:24 -0400
commit0815565adfe3f4c369110c57d8ffe83caefeed68 (patch)
treec1a2436a7f8c7b61a09ab1b809f65bd5b1325ccc /drivers/pci
parentcfc65dd57967f2e0c7b3a8b73e6d12470b1cf1c1 (diff)
intel-iommu: Cope with broken HP DC7900 BIOS
Yet another reason why trusting this stuff to the BIOS was a bad idea. The HP DC7900 BIOS reports an iommu at an address which just returns all ones, when VT-d is disabled in the BIOS. Fix up the missing iounmap in the error paths while we're at it. Signed-off-by: David Woodhouse <David.Woodhouse@intel.com>
Diffstat (limited to 'drivers/pci')
-rw-r--r--drivers/pci/dmar.c22
1 files changed, 18 insertions, 4 deletions
diff --git a/drivers/pci/dmar.c b/drivers/pci/dmar.c
index 7b287cb38b7a..380b60e677e0 100644
--- a/drivers/pci/dmar.c
+++ b/drivers/pci/dmar.c
@@ -632,20 +632,31 @@ int alloc_iommu(struct dmar_drhd_unit *drhd)
632 iommu->cap = dmar_readq(iommu->reg + DMAR_CAP_REG); 632 iommu->cap = dmar_readq(iommu->reg + DMAR_CAP_REG);
633 iommu->ecap = dmar_readq(iommu->reg + DMAR_ECAP_REG); 633 iommu->ecap = dmar_readq(iommu->reg + DMAR_ECAP_REG);
634 634
635 if (iommu->cap == (uint64_t)-1 && iommu->ecap == (uint64_t)-1) {
636 /* Promote an attitude of violence to a BIOS engineer today */
637 WARN(1, "Your BIOS is broken; DMAR reported at address %llx returns all ones!\n"
638 "BIOS vendor: %s; Ver: %s; Product Version: %s\n",
639 drhd->reg_base_addr,
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 goto err_unmap;
644 }
645
635#ifdef CONFIG_DMAR 646#ifdef CONFIG_DMAR
636 agaw = iommu_calculate_agaw(iommu); 647 agaw = iommu_calculate_agaw(iommu);
637 if (agaw < 0) { 648 if (agaw < 0) {
638 printk(KERN_ERR 649 printk(KERN_ERR
639 "Cannot get a valid agaw for iommu (seq_id = %d)\n", 650 "Cannot get a valid agaw for iommu (seq_id = %d)\n",
640 iommu->seq_id); 651 iommu->seq_id);
641 goto error; 652 goto err_unmap;
642 } 653 }
643 msagaw = iommu_calculate_max_sagaw(iommu); 654 msagaw = iommu_calculate_max_sagaw(iommu);
644 if (msagaw < 0) { 655 if (msagaw < 0) {
645 printk(KERN_ERR 656 printk(KERN_ERR
646 "Cannot get a valid max agaw for iommu (seq_id = %d)\n", 657 "Cannot get a valid max agaw for iommu (seq_id = %d)\n",
647 iommu->seq_id); 658 iommu->seq_id);
648 goto error; 659 goto err_unmap;
649 } 660 }
650#endif 661#endif
651 iommu->agaw = agaw; 662 iommu->agaw = agaw;
@@ -665,7 +676,7 @@ int alloc_iommu(struct dmar_drhd_unit *drhd)
665 } 676 }
666 677
667 ver = readl(iommu->reg + DMAR_VER_REG); 678 ver = readl(iommu->reg + DMAR_VER_REG);
668 pr_debug("IOMMU %llx: ver %d:%d cap %llx ecap %llx\n", 679 pr_info("IOMMU %llx: ver %d:%d cap %llx ecap %llx\n",
669 (unsigned long long)drhd->reg_base_addr, 680 (unsigned long long)drhd->reg_base_addr,
670 DMAR_VER_MAJOR(ver), DMAR_VER_MINOR(ver), 681 DMAR_VER_MAJOR(ver), DMAR_VER_MINOR(ver),
671 (unsigned long long)iommu->cap, 682 (unsigned long long)iommu->cap,
@@ -675,7 +686,10 @@ int alloc_iommu(struct dmar_drhd_unit *drhd)
675 686
676 drhd->iommu = iommu; 687 drhd->iommu = iommu;
677 return 0; 688 return 0;
678error: 689
690 err_unmap:
691 iounmap(iommu->reg);
692 error:
679 kfree(iommu); 693 kfree(iommu);
680 return -1; 694 return -1;
681} 695}