From b5c852907e0e8a52f8660235390b831ce0a2b50c Mon Sep 17 00:00:00 2001 From: Vasant Hegde Date: Wed, 6 Jul 2022 17:08:01 +0530 Subject: [PATCH] iommu/amd: Introduce per PCI segment device table size With multiple pci segment support, number of BDF supported by each segment may differ. Hence introduce per segment device table size which depends on last_bdf. This will replace global "device_table_size" variable. Co-developed-by: Suravee Suthikulpanit Signed-off-by: Suravee Suthikulpanit Signed-off-by: Vasant Hegde Link: https://lore.kernel.org/r/20220706113825.25582-12-vasant.hegde@amd.com Signed-off-by: Joerg Roedel --- drivers/iommu/amd/amd_iommu_types.h | 3 +++ drivers/iommu/amd/init.c | 18 ++++++++++-------- 2 files changed, 13 insertions(+), 8 deletions(-) diff --git a/drivers/iommu/amd/amd_iommu_types.h b/drivers/iommu/amd/amd_iommu_types.h index 8be8f3d..1dbe9c7 100644 --- a/drivers/iommu/amd/amd_iommu_types.h +++ b/drivers/iommu/amd/amd_iommu_types.h @@ -555,6 +555,9 @@ struct amd_iommu_pci_seg { /* Largest PCI device id we expect translation requests for */ u16 last_bdf; + /* Size of the device table */ + u32 dev_table_size; + /* * device table virtual address * diff --git a/drivers/iommu/amd/init.c b/drivers/iommu/amd/init.c index 50be138..2950184 100644 --- a/drivers/iommu/amd/init.c +++ b/drivers/iommu/amd/init.c @@ -416,6 +416,7 @@ static void iommu_set_cwwb_range(struct amd_iommu *iommu) static void iommu_set_device_table(struct amd_iommu *iommu) { u64 entry; + u32 dev_table_size = iommu->pci_seg->dev_table_size; BUG_ON(iommu->mmio_base == NULL); @@ -652,7 +653,7 @@ static int __init find_last_devid_acpi(struct acpi_table_header *table, u16 pci_ static inline int __init alloc_dev_table(struct amd_iommu_pci_seg *pci_seg) { pci_seg->dev_table = (void *)__get_free_pages(GFP_KERNEL | __GFP_ZERO | GFP_DMA32, - get_order(dev_table_size)); + get_order(pci_seg->dev_table_size)); if (!pci_seg->dev_table) return -ENOMEM; @@ -662,7 +663,7 @@ static inline int __init alloc_dev_table(struct amd_iommu_pci_seg *pci_seg) static inline void free_dev_table(struct amd_iommu_pci_seg *pci_seg) { free_pages((unsigned long)pci_seg->dev_table, - get_order(dev_table_size)); + get_order(pci_seg->dev_table_size)); pci_seg->dev_table = NULL; } @@ -1035,7 +1036,7 @@ static bool __copy_device_table(struct amd_iommu *iommu) entry = (((u64) hi) << 32) + lo; old_devtb_size = ((entry & ~PAGE_MASK) + 1) << 12; - if (old_devtb_size != dev_table_size) { + if (old_devtb_size != pci_seg->dev_table_size) { pr_err("The device table size of IOMMU:%d is not expected!\n", iommu->index); return false; @@ -1054,15 +1055,15 @@ static bool __copy_device_table(struct amd_iommu *iommu) } old_devtb = (cc_platform_has(CC_ATTR_HOST_MEM_ENCRYPT) && is_kdump_kernel()) ? (__force void *)ioremap_encrypted(old_devtb_phys, - dev_table_size) - : memremap(old_devtb_phys, dev_table_size, MEMREMAP_WB); + pci_seg->dev_table_size) + : memremap(old_devtb_phys, pci_seg->dev_table_size, MEMREMAP_WB); if (!old_devtb) return false; gfp_flag = GFP_KERNEL | __GFP_ZERO | GFP_DMA32; pci_seg->old_dev_tbl_cpy = (void *)__get_free_pages(gfp_flag, - get_order(dev_table_size)); + get_order(pci_seg->dev_table_size)); if (pci_seg->old_dev_tbl_cpy == NULL) { pr_err("Failed to allocate memory for copying old device table!\n"); memunmap(old_devtb); @@ -1581,6 +1582,7 @@ static struct amd_iommu_pci_seg *__init alloc_pci_segment(u16 id, pci_seg->last_bdf = last_bdf; DUMP_printk("PCI segment : 0x%0x, last bdf : 0x%04x\n", id, last_bdf); + pci_seg->dev_table_size = tbl_size(DEV_TABLE_ENTRY_SIZE); pci_seg->id = id; init_llist_head(&pci_seg->dev_data_list); @@ -2678,7 +2680,7 @@ static void early_enable_iommus(void) for_each_pci_segment(pci_seg) { if (pci_seg->old_dev_tbl_cpy != NULL) { free_pages((unsigned long)pci_seg->old_dev_tbl_cpy, - get_order(dev_table_size)); + get_order(pci_seg->dev_table_size)); pci_seg->old_dev_tbl_cpy = NULL; } } @@ -2692,7 +2694,7 @@ static void early_enable_iommus(void) for_each_pci_segment(pci_seg) { free_pages((unsigned long)pci_seg->dev_table, - get_order(dev_table_size)); + get_order(pci_seg->dev_table_size)); pci_seg->dev_table = pci_seg->old_dev_tbl_cpy; } -- 2.7.4