Merge branch 'core-iommu-for-linus' of git://git.kernel.org/pub/scm/linux/kernel...
[pandora-kernel.git] / drivers / iommu / intel-iommu.c
index a88f3cb..f28d933 100644 (file)
@@ -398,11 +398,11 @@ static long list_size;
 
 static void domain_remove_dev_info(struct dmar_domain *domain);
 
-#ifdef CONFIG_DMAR_DEFAULT_ON
+#ifdef CONFIG_INTEL_IOMMU_DEFAULT_ON
 int dmar_disabled = 0;
 #else
 int dmar_disabled = 1;
-#endif /*CONFIG_DMAR_DEFAULT_ON*/
+#endif /*CONFIG_INTEL_IOMMU_DEFAULT_ON*/
 
 static int dmar_map_gfx = 1;
 static int dmar_forcedac;
@@ -2157,7 +2157,7 @@ static inline int iommu_prepare_rmrr_dev(struct dmar_rmrr_unit *rmrr,
                rmrr->end_address);
 }
 
-#ifdef CONFIG_DMAR_FLOPPY_WA
+#ifdef CONFIG_INTEL_IOMMU_FLOPPY_WA
 static inline void iommu_prepare_isa(void)
 {
        struct pci_dev *pdev;
@@ -2180,7 +2180,7 @@ static inline void iommu_prepare_isa(void)
 {
        return;
 }
-#endif /* !CONFIG_DMAR_FLPY_WA */
+#endif /* !CONFIG_INTEL_IOMMU_FLPY_WA */
 
 static int md_domain_init(struct dmar_domain *domain, int guest_width);
 
@@ -2491,7 +2491,7 @@ static int __init init_dmars(void)
        if (iommu_pass_through)
                iommu_identity_mapping |= IDENTMAP_ALL;
 
-#ifdef CONFIG_DMAR_BROKEN_GFX_WA
+#ifdef CONFIG_INTEL_IOMMU_BROKEN_GFX_WA
        iommu_identity_mapping |= IDENTMAP_GFX;
 #endif
 
@@ -3399,6 +3399,151 @@ static void __init init_iommu_pm_ops(void)
 static inline void init_iommu_pm_ops(void) {}
 #endif /* CONFIG_PM */
 
+LIST_HEAD(dmar_rmrr_units);
+
+static void __init dmar_register_rmrr_unit(struct dmar_rmrr_unit *rmrr)
+{
+       list_add(&rmrr->list, &dmar_rmrr_units);
+}
+
+
+int __init dmar_parse_one_rmrr(struct acpi_dmar_header *header)
+{
+       struct acpi_dmar_reserved_memory *rmrr;
+       struct dmar_rmrr_unit *rmrru;
+
+       rmrru = kzalloc(sizeof(*rmrru), GFP_KERNEL);
+       if (!rmrru)
+               return -ENOMEM;
+
+       rmrru->hdr = header;
+       rmrr = (struct acpi_dmar_reserved_memory *)header;
+       rmrru->base_address = rmrr->base_address;
+       rmrru->end_address = rmrr->end_address;
+
+       dmar_register_rmrr_unit(rmrru);
+       return 0;
+}
+
+static int __init
+rmrr_parse_dev(struct dmar_rmrr_unit *rmrru)
+{
+       struct acpi_dmar_reserved_memory *rmrr;
+       int ret;
+
+       rmrr = (struct acpi_dmar_reserved_memory *) rmrru->hdr;
+       ret = dmar_parse_dev_scope((void *)(rmrr + 1),
+               ((void *)rmrr) + rmrr->header.length,
+               &rmrru->devices_cnt, &rmrru->devices, rmrr->segment);
+
+       if (ret || (rmrru->devices_cnt == 0)) {
+               list_del(&rmrru->list);
+               kfree(rmrru);
+       }
+       return ret;
+}
+
+static LIST_HEAD(dmar_atsr_units);
+
+int __init dmar_parse_one_atsr(struct acpi_dmar_header *hdr)
+{
+       struct acpi_dmar_atsr *atsr;
+       struct dmar_atsr_unit *atsru;
+
+       atsr = container_of(hdr, struct acpi_dmar_atsr, header);
+       atsru = kzalloc(sizeof(*atsru), GFP_KERNEL);
+       if (!atsru)
+               return -ENOMEM;
+
+       atsru->hdr = hdr;
+       atsru->include_all = atsr->flags & 0x1;
+
+       list_add(&atsru->list, &dmar_atsr_units);
+
+       return 0;
+}
+
+static int __init atsr_parse_dev(struct dmar_atsr_unit *atsru)
+{
+       int rc;
+       struct acpi_dmar_atsr *atsr;
+
+       if (atsru->include_all)
+               return 0;
+
+       atsr = container_of(atsru->hdr, struct acpi_dmar_atsr, header);
+       rc = dmar_parse_dev_scope((void *)(atsr + 1),
+                               (void *)atsr + atsr->header.length,
+                               &atsru->devices_cnt, &atsru->devices,
+                               atsr->segment);
+       if (rc || !atsru->devices_cnt) {
+               list_del(&atsru->list);
+               kfree(atsru);
+       }
+
+       return rc;
+}
+
+int dmar_find_matched_atsr_unit(struct pci_dev *dev)
+{
+       int i;
+       struct pci_bus *bus;
+       struct acpi_dmar_atsr *atsr;
+       struct dmar_atsr_unit *atsru;
+
+       dev = pci_physfn(dev);
+
+       list_for_each_entry(atsru, &dmar_atsr_units, list) {
+               atsr = container_of(atsru->hdr, struct acpi_dmar_atsr, header);
+               if (atsr->segment == pci_domain_nr(dev->bus))
+                       goto found;
+       }
+
+       return 0;
+
+found:
+       for (bus = dev->bus; bus; bus = bus->parent) {
+               struct pci_dev *bridge = bus->self;
+
+               if (!bridge || !pci_is_pcie(bridge) ||
+                   bridge->pcie_type == PCI_EXP_TYPE_PCI_BRIDGE)
+                       return 0;
+
+               if (bridge->pcie_type == PCI_EXP_TYPE_ROOT_PORT) {
+                       for (i = 0; i < atsru->devices_cnt; i++)
+                               if (atsru->devices[i] == bridge)
+                                       return 1;
+                       break;
+               }
+       }
+
+       if (atsru->include_all)
+               return 1;
+
+       return 0;
+}
+
+int dmar_parse_rmrr_atsr_dev(void)
+{
+       struct dmar_rmrr_unit *rmrr, *rmrr_n;
+       struct dmar_atsr_unit *atsr, *atsr_n;
+       int ret = 0;
+
+       list_for_each_entry_safe(rmrr, rmrr_n, &dmar_rmrr_units, list) {
+               ret = rmrr_parse_dev(rmrr);
+               if (ret)
+                       return ret;
+       }
+
+       list_for_each_entry_safe(atsr, atsr_n, &dmar_atsr_units, list) {
+               ret = atsr_parse_dev(atsr);
+               if (ret)
+                       return ret;
+       }
+
+       return ret;
+}
+
 /*
  * Here we only respond to action of unbound device from driver.
  *
@@ -3448,16 +3593,12 @@ int __init intel_iommu_init(void)
                return  -ENODEV;
        }
 
-       if (dmar_dev_scope_init()) {
+       if (dmar_dev_scope_init() < 0) {
                if (force_on)
                        panic("tboot: Failed to initialize DMAR device scope\n");
                return  -ENODEV;
        }
 
-       /*
-        * Check the need for DMA-remapping initialization now.
-        * Above initialization will also be used by Interrupt-remapping.
-        */
        if (no_iommu || dmar_disabled)
                return -ENODEV;
 
@@ -3467,6 +3608,12 @@ int __init intel_iommu_init(void)
                return  -ENODEV;
        }
 
+       if (list_empty(&dmar_rmrr_units))
+               printk(KERN_INFO "DMAR: No RMRR found\n");
+
+       if (list_empty(&dmar_atsr_units))
+               printk(KERN_INFO "DMAR: No ATSR found\n");
+
        if (dmar_init_reserved_ranges()) {
                if (force_on)
                        panic("tboot: Failed to reserve iommu ranges\n");