Commit b5c85290 authored by Vasant Hegde's avatar Vasant Hegde Committed by Joerg Roedel
Browse files

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: default avatarSuravee Suthikulpanit <suravee.suthikulpanit@amd.com>
Signed-off-by: default avatarSuravee Suthikulpanit <suravee.suthikulpanit@amd.com>
Signed-off-by: default avatarVasant Hegde <vasant.hegde@amd.com>
Link: https://lore.kernel.org/r/20220706113825.25582-12-vasant.hegde@amd.com


Signed-off-by: default avatarJoerg Roedel <jroedel@suse.de>
parent 30795900
Loading
Loading
Loading
Loading
+3 −0
Original line number Diff line number Diff line
@@ -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
	 *
+10 −8
Original line number Diff line number Diff line
@@ -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;
		}