mirror of https://github.com/torvalds/linux.git
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: Vasant Hegde <vasant.hegde@amd.com> Signed-off-by: Vasant Hegde <vasant.hegde@amd.com> Signed-off-by: Suravee Suthikulpanit <suravee.suthikulpanit@amd.com> Link: https://lore.kernel.org/r/20220706113825.25582-4-vasant.hegde@amd.com Signed-off-by: Joerg Roedel <jroedel@suse.de>
This commit is contained in:
parent
404ec4e4c1
commit
04230c1199
|
|
@ -128,4 +128,5 @@ static inline void amd_iommu_apply_ivrs_quirks(void) { }
|
||||||
|
|
||||||
extern void amd_iommu_domain_set_pgtable(struct protection_domain *domain,
|
extern void amd_iommu_domain_set_pgtable(struct protection_domain *domain,
|
||||||
u64 *root, int mode);
|
u64 *root, int mode);
|
||||||
|
extern struct dev_table_entry *get_dev_table(struct amd_iommu *iommu);
|
||||||
#endif
|
#endif
|
||||||
|
|
|
||||||
|
|
@ -544,6 +544,16 @@ struct amd_iommu_pci_seg {
|
||||||
|
|
||||||
/* PCI segment number */
|
/* PCI segment number */
|
||||||
u16 id;
|
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;
|
||||||
};
|
};
|
||||||
|
|
||||||
/*
|
/*
|
||||||
|
|
|
||||||
|
|
@ -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 following functions belong to the code path which parses the ACPI table
|
||||||
* the second time. In this ACPI parsing iteration we allocate IOMMU specific
|
* the second time. In this ACPI parsing iteration we allocate IOMMU specific
|
||||||
* data structures, initialize the device/alias/rlookup table and also
|
* data structures, initialize the per PCI segment device/alias/rlookup table
|
||||||
* basically initialize the hardware.
|
* 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
|
* Allocates the command buffer. This buffer is per AMD IOMMU. We can
|
||||||
* write commands to that buffer later and the IOMMU will execute them
|
* 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;
|
pci_seg->id = id;
|
||||||
list_add_tail(&pci_seg->list, &amd_iommu_pci_seg_list);
|
list_add_tail(&pci_seg->list, &amd_iommu_pci_seg_list);
|
||||||
|
|
||||||
|
if (alloc_dev_table(pci_seg))
|
||||||
|
return NULL;
|
||||||
|
|
||||||
return pci_seg;
|
return pci_seg;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -1492,6 +1513,7 @@ static void __init free_pci_segments(void)
|
||||||
|
|
||||||
for_each_pci_segment_safe(pci_seg, next) {
|
for_each_pci_segment_safe(pci_seg, next) {
|
||||||
list_del(&pci_seg->list);
|
list_del(&pci_seg->list);
|
||||||
|
free_dev_table(pci_seg);
|
||||||
kfree(pci_seg);
|
kfree(pci_seg);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -134,6 +134,18 @@ static inline int get_device_id(struct device *dev)
|
||||||
return devid;
|
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)
|
static struct protection_domain *to_pdomain(struct iommu_domain *dom)
|
||||||
{
|
{
|
||||||
return container_of(dom, struct protection_domain, domain);
|
return container_of(dom, struct protection_domain, domain);
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue