Commit 04230c11 authored by Suravee Suthikulpanit's avatar Suravee Suthikulpanit Committed by Joerg Roedel
Browse files

iommu/amd: Introduce per PCI segment device table



Introduce per PCI segment device table. All IOMMUs within the segment
will share this device table. This will replace global device
table i.e. amd_iommu_dev_table.

Also introduce helper function to get the device table for the given IOMMU.

Co-developed-by: default avatarVasant Hegde <vasant.hegde@amd.com>
Signed-off-by: default avatarVasant Hegde <vasant.hegde@amd.com>
Signed-off-by: default avatarSuravee Suthikulpanit <suravee.suthikulpanit@amd.com>
Link: https://lore.kernel.org/r/20220706113825.25582-4-vasant.hegde@amd.com


Signed-off-by: default avatarJoerg Roedel <jroedel@suse.de>
parent 404ec4e4
Loading
Loading
Loading
Loading
+1 −0
Original line number Diff line number Diff line
@@ -128,4 +128,5 @@ static inline void amd_iommu_apply_ivrs_quirks(void) { }

extern void amd_iommu_domain_set_pgtable(struct protection_domain *domain,
					 u64 *root, int mode);
extern struct dev_table_entry *get_dev_table(struct amd_iommu *iommu);
#endif
+10 −0
Original line number Diff line number Diff line
@@ -544,6 +544,16 @@ struct amd_iommu_pci_seg {

	/* PCI segment number */
	u16 id;

	/*
	 * device table virtual address
	 *
	 * Pointer to the per PCI segment device table.
	 * It is indexed by the PCI device id or the HT unit id and contains
	 * information about the domain the device belongs to as well as the
	 * page table root pointer.
	 */
	struct dev_table_entry *dev_table;
};

/*
+24 −2
Original line number Diff line number Diff line
@@ -642,11 +642,29 @@ static int __init find_last_devid_acpi(struct acpi_table_header *table)
 *
 * The following functions belong to the code path which parses the ACPI table
 * the second time. In this ACPI parsing iteration we allocate IOMMU specific
 * data structures, initialize the device/alias/rlookup table and also
 * basically initialize the hardware.
 * data structures, initialize the per PCI segment device/alias/rlookup table
 * and also basically initialize the hardware.
 *
 ****************************************************************************/

/* Allocate per PCI segment device table */
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));
	if (!pci_seg->dev_table)
		return -ENOMEM;

	return 0;
}

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));
	pci_seg->dev_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
@@ -1471,6 +1489,9 @@ static struct amd_iommu_pci_seg *__init alloc_pci_segment(u16 id)
	pci_seg->id = id;
	list_add_tail(&pci_seg->list, &amd_iommu_pci_seg_list);

	if (alloc_dev_table(pci_seg))
		return NULL;

	return pci_seg;
}

@@ -1492,6 +1513,7 @@ static void __init free_pci_segments(void)

	for_each_pci_segment_safe(pci_seg, next) {
		list_del(&pci_seg->list);
		free_dev_table(pci_seg);
		kfree(pci_seg);
	}
}
+12 −0
Original line number Diff line number Diff line
@@ -134,6 +134,18 @@ static inline int get_device_id(struct device *dev)
	return devid;
}

struct dev_table_entry *get_dev_table(struct amd_iommu *iommu)
{
	struct dev_table_entry *dev_table;
	struct amd_iommu_pci_seg *pci_seg = iommu->pci_seg;

	BUG_ON(pci_seg == NULL);
	dev_table = pci_seg->dev_table;
	BUG_ON(dev_table == NULL);

	return dev_table;
}

static struct protection_domain *to_pdomain(struct iommu_domain *dom)
{
	return container_of(dom, struct protection_domain, domain);