[RESEND PATCH v1 08/37] iommu/amd: Introduce per PCI segment alias_table
From: Suravee Suthikulpanit This will replace global alias table (amd_iommu_alias_table). Co-developed-by: Vasant Hegde Signed-off-by: Vasant Hegde Signed-off-by: Suravee Suthikulpanit --- drivers/iommu/amd/amd_iommu_types.h | 7 + drivers/iommu/amd/init.c| 41 ++--- drivers/iommu/amd/iommu.c | 41 ++--- 3 files changed, 64 insertions(+), 25 deletions(-) diff --git a/drivers/iommu/amd/amd_iommu_types.h b/drivers/iommu/amd/amd_iommu_types.h index 330bb346207a..f9776f188e36 100644 --- a/drivers/iommu/amd/amd_iommu_types.h +++ b/drivers/iommu/amd/amd_iommu_types.h @@ -572,6 +572,13 @@ struct amd_iommu_pci_seg { * will be copied to. It's only be used in kdump kernel. */ struct dev_table_entry *old_dev_tbl_cpy; + + /* +* The alias table is a driver specific data structure which contains the +* mappings of the PCI device ids to the actual requestor ids on the IOMMU. +* More than one device can share the same requestor id. +*/ + u16 *alias_table; }; /* diff --git a/drivers/iommu/amd/init.c b/drivers/iommu/amd/init.c index af413738da01..fe31de6e764c 100644 --- a/drivers/iommu/amd/init.c +++ b/drivers/iommu/amd/init.c @@ -698,6 +698,31 @@ static inline void free_irq_lookup_table(struct amd_iommu_pci_seg *pci_seg) pci_seg->irq_lookup_table = NULL; } +static int __init alloc_alias_table(struct amd_iommu_pci_seg *pci_seg) +{ + int i; + + pci_seg->alias_table = (void *)__get_free_pages(GFP_KERNEL, + get_order(alias_table_size)); + if (!pci_seg->alias_table) + return -ENOMEM; + + /* +* let all alias entries point to itself +*/ + for (i = 0; i <= amd_iommu_last_bdf; ++i) + pci_seg->alias_table[i] = i; + + return 0; +} + +static void __init free_alias_table(struct amd_iommu_pci_seg *pci_seg) +{ + free_pages((unsigned long)pci_seg->alias_table, + get_order(alias_table_size)); + pci_seg->alias_table = NULL; +} + /* * Allocates the command buffer. This buffer is per AMD IOMMU. We can * write commands to that buffer later and the IOMMU will execute them @@ -1266,6 +1291,7 @@ static int __init init_iommu_from_acpi(struct amd_iommu *iommu, u32 dev_i, ext_flags = 0; bool alias = false; struct ivhd_entry *e; + struct amd_iommu_pci_seg *pci_seg = iommu->pci_seg; u32 ivhd_size; int ret; @@ -1347,7 +1373,7 @@ static int __init init_iommu_from_acpi(struct amd_iommu *iommu, devid_to = e->ext >> 8; set_dev_entry_from_acpi(iommu, devid , e->flags, 0); set_dev_entry_from_acpi(iommu, devid_to, e->flags, 0); - amd_iommu_alias_table[devid] = devid_to; + pci_seg->alias_table[devid] = devid_to; break; case IVHD_DEV_ALIAS_RANGE: @@ -1405,7 +1431,7 @@ static int __init init_iommu_from_acpi(struct amd_iommu *iommu, devid = e->devid; for (dev_i = devid_start; dev_i <= devid; ++dev_i) { if (alias) { - amd_iommu_alias_table[dev_i] = devid_to; + pci_seg->alias_table[dev_i] = devid_to; set_dev_entry_from_acpi(iommu, devid_to, flags, ext_flags); } @@ -1540,6 +1566,8 @@ static struct amd_iommu_pci_seg *__init alloc_pci_segment(u16 id) if (alloc_dev_table(pci_seg)) return NULL; + if (alloc_alias_table(pci_seg)) + return NULL; if (alloc_rlookup_table(pci_seg)) return NULL; @@ -1566,6 +1594,7 @@ static void __init free_pci_segment(void) list_del(_seg->list); free_irq_lookup_table(pci_seg); free_rlookup_table(pci_seg); + free_alias_table(pci_seg); free_dev_table(pci_seg); kfree(pci_seg); } @@ -2838,7 +2867,7 @@ static void __init ivinfo_init(void *ivrs) static int __init early_amd_iommu_init(void) { struct acpi_table_header *ivrs_base; - int i, remap_cache_sz, ret; + int remap_cache_sz, ret; acpi_status status; if (!amd_iommu_detected) @@ -2909,12 +2938,6 @@ static int __init early_amd_iommu_init(void) if (amd_iommu_pd_alloc_bitmap == NULL) goto out; - /* -* let all alias entries point to itself -*/ - for (i = 0; i <= amd_iommu_last_bdf; ++i) - amd_iommu_alias_table[i] = i; - /* * never allocate domain 0 because its used as the non-allocated and
[PATCH v1 08/37] iommu/amd: Introduce per PCI segment alias_table
From: Suravee Suthikulpanit This will replace global alias table (amd_iommu_alias_table). Co-developed-by: Vasant Hegde Signed-off-by: Vasant Hegde Signed-off-by: Suravee Suthikulpanit --- drivers/iommu/amd/amd_iommu_types.h | 7 + drivers/iommu/amd/init.c| 41 ++--- drivers/iommu/amd/iommu.c | 41 ++--- 3 files changed, 64 insertions(+), 25 deletions(-) diff --git a/drivers/iommu/amd/amd_iommu_types.h b/drivers/iommu/amd/amd_iommu_types.h index 330bb346207a..f9776f188e36 100644 --- a/drivers/iommu/amd/amd_iommu_types.h +++ b/drivers/iommu/amd/amd_iommu_types.h @@ -572,6 +572,13 @@ struct amd_iommu_pci_seg { * will be copied to. It's only be used in kdump kernel. */ struct dev_table_entry *old_dev_tbl_cpy; + + /* +* The alias table is a driver specific data structure which contains the +* mappings of the PCI device ids to the actual requestor ids on the IOMMU. +* More than one device can share the same requestor id. +*/ + u16 *alias_table; }; /* diff --git a/drivers/iommu/amd/init.c b/drivers/iommu/amd/init.c index af413738da01..fe31de6e764c 100644 --- a/drivers/iommu/amd/init.c +++ b/drivers/iommu/amd/init.c @@ -698,6 +698,31 @@ static inline void free_irq_lookup_table(struct amd_iommu_pci_seg *pci_seg) pci_seg->irq_lookup_table = NULL; } +static int __init alloc_alias_table(struct amd_iommu_pci_seg *pci_seg) +{ + int i; + + pci_seg->alias_table = (void *)__get_free_pages(GFP_KERNEL, + get_order(alias_table_size)); + if (!pci_seg->alias_table) + return -ENOMEM; + + /* +* let all alias entries point to itself +*/ + for (i = 0; i <= amd_iommu_last_bdf; ++i) + pci_seg->alias_table[i] = i; + + return 0; +} + +static void __init free_alias_table(struct amd_iommu_pci_seg *pci_seg) +{ + free_pages((unsigned long)pci_seg->alias_table, + get_order(alias_table_size)); + pci_seg->alias_table = NULL; +} + /* * Allocates the command buffer. This buffer is per AMD IOMMU. We can * write commands to that buffer later and the IOMMU will execute them @@ -1266,6 +1291,7 @@ static int __init init_iommu_from_acpi(struct amd_iommu *iommu, u32 dev_i, ext_flags = 0; bool alias = false; struct ivhd_entry *e; + struct amd_iommu_pci_seg *pci_seg = iommu->pci_seg; u32 ivhd_size; int ret; @@ -1347,7 +1373,7 @@ static int __init init_iommu_from_acpi(struct amd_iommu *iommu, devid_to = e->ext >> 8; set_dev_entry_from_acpi(iommu, devid , e->flags, 0); set_dev_entry_from_acpi(iommu, devid_to, e->flags, 0); - amd_iommu_alias_table[devid] = devid_to; + pci_seg->alias_table[devid] = devid_to; break; case IVHD_DEV_ALIAS_RANGE: @@ -1405,7 +1431,7 @@ static int __init init_iommu_from_acpi(struct amd_iommu *iommu, devid = e->devid; for (dev_i = devid_start; dev_i <= devid; ++dev_i) { if (alias) { - amd_iommu_alias_table[dev_i] = devid_to; + pci_seg->alias_table[dev_i] = devid_to; set_dev_entry_from_acpi(iommu, devid_to, flags, ext_flags); } @@ -1540,6 +1566,8 @@ static struct amd_iommu_pci_seg *__init alloc_pci_segment(u16 id) if (alloc_dev_table(pci_seg)) return NULL; + if (alloc_alias_table(pci_seg)) + return NULL; if (alloc_rlookup_table(pci_seg)) return NULL; @@ -1566,6 +1594,7 @@ static void __init free_pci_segment(void) list_del(_seg->list); free_irq_lookup_table(pci_seg); free_rlookup_table(pci_seg); + free_alias_table(pci_seg); free_dev_table(pci_seg); kfree(pci_seg); } @@ -2838,7 +2867,7 @@ static void __init ivinfo_init(void *ivrs) static int __init early_amd_iommu_init(void) { struct acpi_table_header *ivrs_base; - int i, remap_cache_sz, ret; + int remap_cache_sz, ret; acpi_status status; if (!amd_iommu_detected) @@ -2909,12 +2938,6 @@ static int __init early_amd_iommu_init(void) if (amd_iommu_pd_alloc_bitmap == NULL) goto out; - /* -* let all alias entries point to itself -*/ - for (i = 0; i <= amd_iommu_last_bdf; ++i) - amd_iommu_alias_table[i] = i; - /* * never allocate domain 0 because its used as the non-allocated and