+++ /dev/null
-From: Suresh Siddha <suresh.b.siddha@intel.com>
-Subject: x64, x2apic/intr-remap: code re-structuring, to be used by both DMA and Interrupt remapping
-References: fate #303948 and fate #303984
-Patch-Mainline: queued for .28
-Commit-ID: 1886e8a90a580f3ad343f2065c84c1b9e1dac9ef
-
-Signed-off-by: Thomas Renninger <trenn@suse.de>
-
-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 | 89 +++++++++++++++++++++++++++++++++++++---------
- drivers/pci/intel-iommu.c | 10 ++---
- drivers/pci/intel-iommu.h | 2 -
- include/linux/dmar.h | 10 ++++-
- 4 files changed, 88 insertions(+), 23 deletions(-)
-
---- a/drivers/pci/dmar.c
-+++ b/drivers/pci/dmar.c
-@@ -174,19 +174,37 @@ dmar_parse_one_drhd(struct acpi_dmar_hea
- 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_hea
- 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_hea
- {
- 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_d
- 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;
- }
-
-@@ -375,7 +432,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;
-@@ -384,7 +441,7 @@ struct intel_iommu *alloc_iommu(struct d
-
- iommu = kzalloc(sizeof(*iommu), GFP_KERNEL);
- if (!iommu)
-- return NULL;
-+ return -ENOMEM;
-
- iommu->seq_id = iommu_allocated++;
-
-@@ -417,10 +474,10 @@ struct intel_iommu *alloc_iommu(struct d
- 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)
---- a/drivers/pci/intel-iommu.c
-+++ b/drivers/pci/intel-iommu.c
-@@ -1667,11 +1667,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)
-@@ -2349,6 +2346,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();
-
---- a/drivers/pci/intel-iommu.h
-+++ b/drivers/pci/intel-iommu.h
-@@ -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
---- a/include/linux/dmar.h
-+++ b/include/linux/dmar.h
-@@ -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__ */