]> www.pilppa.org Git - linux-2.6-omap-h63xx.git/commitdiff
x64, x2apic/intr-remap: code re-structuring, to be used by both DMA and Interrupt...
authorSuresh Siddha <suresh.b.siddha@intel.com>
Thu, 10 Jul 2008 18:16:37 +0000 (11:16 -0700)
committerIngo Molnar <mingo@elte.hu>
Sat, 12 Jul 2008 06:44:48 +0000 (08:44 +0200)
Allocate the iommu during the parse of DMA remapping hardware
definition structures. And also, introduce routines for device
scope initialization which will be explicitly called during
dma-remapping initialization.

These will be used for enabling interrupt remapping separately from the
existing DMA-remapping enabling sequence.

Signed-off-by: Suresh Siddha <suresh.b.siddha@intel.com>
Cc: akpm@linux-foundation.org
Cc: arjan@linux.intel.com
Cc: andi@firstfloor.org
Cc: ebiederm@xmission.com
Cc: jbarnes@virtuousgeek.org
Cc: steiner@sgi.com
Signed-off-by: Ingo Molnar <mingo@elte.hu>
drivers/pci/dmar.c
drivers/pci/intel-iommu.c
drivers/pci/intel-iommu.h
include/linux/dmar.h

index 1a59423a8edaf75adda02026232cba745648547c..158bc5bfcf75d593da7df744a131f1bea9e8bf0e 100644 (file)
@@ -174,19 +174,37 @@ dmar_parse_one_drhd(struct acpi_dmar_header *header)
        struct acpi_dmar_hardware_unit *drhd;
        struct dmar_drhd_unit *dmaru;
        int ret = 0;
-       static int include_all;
 
        dmaru = kzalloc(sizeof(*dmaru), GFP_KERNEL);
        if (!dmaru)
                return -ENOMEM;
 
+       dmaru->hdr = header;
        drhd = (struct acpi_dmar_hardware_unit *)header;
        dmaru->reg_base_addr = drhd->address;
        dmaru->include_all = drhd->flags & 0x1; /* BIT0: INCLUDE_ALL */
 
+       ret = alloc_iommu(dmaru);
+       if (ret) {
+               kfree(dmaru);
+               return ret;
+       }
+       dmar_register_drhd_unit(dmaru);
+       return 0;
+}
+
+static int __init
+dmar_parse_dev(struct dmar_drhd_unit *dmaru)
+{
+       struct acpi_dmar_hardware_unit *drhd;
+       static int include_all;
+       int ret;
+
+       drhd = (struct acpi_dmar_hardware_unit *) dmaru->hdr;
+
        if (!dmaru->include_all)
                ret = dmar_parse_dev_scope((void *)(drhd + 1),
-                               ((void *)drhd) + header->length,
+                               ((void *)drhd) + drhd->header.length,
                                &dmaru->devices_cnt, &dmaru->devices,
                                drhd->segment);
        else {
@@ -199,10 +217,10 @@ dmar_parse_one_drhd(struct acpi_dmar_header *header)
                include_all = 1;
        }
 
-       if (ret || (dmaru->devices_cnt == 0 && !dmaru->include_all))
+       if (ret || (dmaru->devices_cnt == 0 && !dmaru->include_all)) {
+               list_del(&dmaru->list);
                kfree(dmaru);
-       else
-               dmar_register_drhd_unit(dmaru);
+       }
        return ret;
 }
 
@@ -211,23 +229,35 @@ dmar_parse_one_rmrr(struct acpi_dmar_header *header)
 {
        struct acpi_dmar_reserved_memory *rmrr;
        struct dmar_rmrr_unit *rmrru;
-       int ret = 0;
 
        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) + header->length,
+               ((void *)rmrr) + rmrr->header.length,
                &rmrru->devices_cnt, &rmrru->devices, rmrr->segment);
 
-       if (ret || (rmrru->devices_cnt == 0))
+       if (ret || (rmrru->devices_cnt == 0)) {
+               list_del(&rmrru->list);
                kfree(rmrru);
-       else
-               dmar_register_rmrr_unit(rmrru);
+       }
        return ret;
 }
 
@@ -333,15 +363,42 @@ dmar_find_matched_drhd_unit(struct pci_dev *dev)
        return NULL;
 }
 
+int __init dmar_dev_scope_init(void)
+{
+       struct dmar_drhd_unit *drhd;
+       struct dmar_rmrr_unit *rmrr;
+       int ret = -ENODEV;
+
+       for_each_drhd_unit(drhd) {
+               ret = dmar_parse_dev(drhd);
+               if (ret)
+                       return ret;
+       }
+
+       for_each_rmrr_units(rmrr) {
+               ret = rmrr_parse_dev(rmrr);
+               if (ret)
+                       return ret;
+       }
+
+       return ret;
+}
+
 
 int __init dmar_table_init(void)
 {
-
+       static int dmar_table_initialized;
        int ret;
 
+       if (dmar_table_initialized)
+               return 0;
+
+       dmar_table_initialized = 1;
+
        ret = parse_dmar_table();
        if (ret) {
-               printk(KERN_INFO PREFIX "parse DMAR table failure.\n");
+               if (ret != -ENODEV)
+                       printk(KERN_INFO PREFIX "parse DMAR table failure.\n");
                return ret;
        }
 
@@ -377,7 +434,7 @@ int __init early_dmar_detect(void)
        return (ACPI_SUCCESS(status) ? 1 : 0);
 }
 
-struct intel_iommu *alloc_iommu(struct dmar_drhd_unit *drhd)
+int alloc_iommu(struct dmar_drhd_unit *drhd)
 {
        struct intel_iommu *iommu;
        int map_size;
@@ -386,7 +443,7 @@ struct intel_iommu *alloc_iommu(struct dmar_drhd_unit *drhd)
 
        iommu = kzalloc(sizeof(*iommu), GFP_KERNEL);
        if (!iommu)
-               return NULL;
+               return -ENOMEM;
 
        iommu->seq_id = iommu_allocated++;
 
@@ -419,10 +476,10 @@ struct intel_iommu *alloc_iommu(struct dmar_drhd_unit *drhd)
        spin_lock_init(&iommu->register_lock);
 
        drhd->iommu = iommu;
-       return iommu;
+       return 0;
 error:
        kfree(iommu);
-       return NULL;
+       return -1;
 }
 
 void free_iommu(struct intel_iommu *iommu)
index 4d59a6a1f4dd4a977724449f4b13276cf59b8f22..218a1f357b4df6855787356648e3b173779b8055 100644 (file)
@@ -1665,11 +1665,8 @@ int __init init_dmars(void)
        for_each_drhd_unit(drhd) {
                if (drhd->ignored)
                        continue;
-               iommu = alloc_iommu(drhd);
-               if (!iommu) {
-                       ret = -ENOMEM;
-                       goto error;
-               }
+
+               iommu = drhd->iommu;
 
                ret = iommu_init_domains(iommu);
                if (ret)
@@ -2324,6 +2321,9 @@ int __init intel_iommu_init(void)
        if (dmar_table_init())
                return  -ENODEV;
 
+       if (dmar_dev_scope_init())
+               return  -ENODEV;
+
        iommu_init_mempool();
        dmar_init_reserved_ranges();
 
index 75c63f65b3f5b315e491e0e7e568434d4891536d..371e3b9caf32bf35dcce310789741e9c89e28549 100644 (file)
@@ -199,7 +199,7 @@ struct intel_iommu {
 
 extern struct dmar_drhd_unit * dmar_find_matched_drhd_unit(struct pci_dev *dev);
 
-extern struct intel_iommu *alloc_iommu(struct dmar_drhd_unit *drhd);
+extern int alloc_iommu(struct dmar_drhd_unit *drhd);
 extern void free_iommu(struct intel_iommu *iommu);
 
 #endif
index 56c73b8475519cc7ee5db5886c92aa6d8f5f2d15..3ab07e425583f129d178e6392f9e4174c00ec209 100644 (file)
@@ -46,12 +46,14 @@ extern int intel_iommu_init(void);
 
 extern int dmar_table_init(void);
 extern int early_dmar_detect(void);
+extern int dmar_dev_scope_init(void);
 
 extern struct list_head dmar_drhd_units;
 extern struct list_head dmar_rmrr_units;
 
 struct dmar_drhd_unit {
        struct list_head list;          /* list of drhd units   */
+       struct  acpi_dmar_header *hdr;  /* ACPI header          */
        u64     reg_base_addr;          /* register base address*/
        struct  pci_dev **devices;      /* target device array  */
        int     devices_cnt;            /* target device count  */
@@ -62,6 +64,7 @@ struct dmar_drhd_unit {
 
 struct dmar_rmrr_unit {
        struct list_head list;          /* list of rmrr units   */
+       struct acpi_dmar_header *hdr;   /* ACPI header          */
        u64     base_address;           /* reserved base address*/
        u64     end_address;            /* reserved end address */
        struct pci_dev **devices;       /* target devices */
@@ -72,6 +75,8 @@ struct dmar_rmrr_unit {
        list_for_each_entry(drhd, &dmar_drhd_units, list)
 #define for_each_rmrr_units(rmrr) \
        list_for_each_entry(rmrr, &dmar_rmrr_units, list)
+
+extern int alloc_iommu(struct dmar_drhd_unit *);
 #else
 static inline void detect_intel_iommu(void)
 {
@@ -81,6 +86,9 @@ static inline int intel_iommu_init(void)
 {
        return -ENODEV;
 }
-
+static inline int dmar_table_init(void)
+{
+       return -ENODEV;
+}
 #endif /* !CONFIG_DMAR */
 #endif /* __DMAR_H__ */