Skip to content

Commit

Permalink
iommu/amd: Replace slab cache allocator with page allocator
Browse files Browse the repository at this point in the history
Commit 05152a0 ("iommu/amd: Add slab-cache for irq remapping tables")
introduces slab cache allocator. But slab cache allocator provides benefit
only when the allocation and deallocation of many identical objects is
frequent. The AMD IOMMU driver allocates Interrupt remapping table (IRT)
when device driver requests IRQ for the first time and never frees it.
Hence the slab allocator does not provide any benefit here.

Signed-off-by: Sairaj Kodilkar <sarunkod@amd.com>
Reviewed-by: Vasant Hegde <vasant.hegde@amd.com>
Link: https://lore.kernel.org/r/20250307095822.2274-3-sarunkod@amd.com
Signed-off-by: Joerg Roedel <jroedel@suse.de>
  • Loading branch information
Sairaj Kodilkar authored and Joerg Roedel committed Mar 13, 2025
1 parent 1c608b0 commit eaf717f
Show file tree
Hide file tree
Showing 3 changed files with 15 additions and 36 deletions.
4 changes: 0 additions & 4 deletions drivers/iommu/amd/amd_iommu_types.h
Original file line number Diff line number Diff line change
Expand Up @@ -313,7 +313,6 @@
* AMD IOMMU hardware only support 512 IRTEs despite
* the architectural limitation of 2048 entries.
*/
#define DTE_INTTAB_ALIGNMENT 128
#define DTE_INTTABLEN_VALUE 9ULL
#define DTE_INTTABLEN (DTE_INTTABLEN_VALUE << 1)
#define DTE_INTTABLEN_MASK (0xfULL << 1)
Expand Down Expand Up @@ -492,9 +491,6 @@ extern const struct iommu_ops amd_iommu_ops;
/* IVRS indicates that pre-boot remapping was enabled */
extern bool amdr_ivrs_remap_support;

/* kmem_cache to get tables with 128 byte alignement */
extern struct kmem_cache *amd_iommu_irq_cache;

#define PCI_SBDF_TO_SEGID(sbdf) (((sbdf) >> 16) & 0xffff)
#define PCI_SBDF_TO_DEVID(sbdf) ((sbdf) & 0xffff)
#define PCI_SEG_DEVID_TO_SBDF(seg, devid) ((((u32)(seg) & 0xffff) << 16) | \
Expand Down
21 changes: 1 addition & 20 deletions drivers/iommu/amd/init.c
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,6 @@
#include <linux/acpi.h>
#include <linux/list.h>
#include <linux/bitmap.h>
#include <linux/slab.h>
#include <linux/syscore_ops.h>
#include <linux/interrupt.h>
#include <linux/msi.h>
Expand Down Expand Up @@ -2931,9 +2930,6 @@ static struct syscore_ops amd_iommu_syscore_ops = {

static void __init free_iommu_resources(void)
{
kmem_cache_destroy(amd_iommu_irq_cache);
amd_iommu_irq_cache = NULL;

free_iommu_all();
free_pci_segments();
}
Expand Down Expand Up @@ -3032,7 +3028,7 @@ static void __init ivinfo_init(void *ivrs)
static int __init early_amd_iommu_init(void)
{
struct acpi_table_header *ivrs_base;
int remap_cache_sz, ret;
int ret;
acpi_status status;

if (!amd_iommu_detected)
Expand Down Expand Up @@ -3094,22 +3090,7 @@ static int __init early_amd_iommu_init(void)

if (amd_iommu_irq_remap) {
struct amd_iommu_pci_seg *pci_seg;
/*
* Interrupt remapping enabled, create kmem_cache for the
* remapping tables.
*/
ret = -ENOMEM;
if (!AMD_IOMMU_GUEST_IR_GA(amd_iommu_guest_ir))
remap_cache_sz = MAX_IRQS_PER_TABLE * sizeof(u32);
else
remap_cache_sz = MAX_IRQS_PER_TABLE * (sizeof(u64) * 2);
amd_iommu_irq_cache = kmem_cache_create("irq_remap_cache",
remap_cache_sz,
DTE_INTTAB_ALIGNMENT,
0, NULL);
if (!amd_iommu_irq_cache)
goto out;

for_each_pci_segment(pci_seg) {
if (alloc_irq_lookup_table(pci_seg))
goto out;
Expand Down
26 changes: 14 additions & 12 deletions drivers/iommu/amd/iommu.c
Original file line number Diff line number Diff line change
Expand Up @@ -75,8 +75,6 @@ struct iommu_cmd {
*/
DEFINE_IDA(pdom_ids);

struct kmem_cache *amd_iommu_irq_cache;

static int amd_iommu_attach_device(struct iommu_domain *dom,
struct device *dev);

Expand Down Expand Up @@ -3118,27 +3116,21 @@ static struct irq_remap_table *get_irq_table(struct amd_iommu *iommu, u16 devid)
return table;
}

static struct irq_remap_table *__alloc_irq_table(void)
static struct irq_remap_table *__alloc_irq_table(int nid, int order)
{
struct irq_remap_table *table;

table = kzalloc(sizeof(*table), GFP_KERNEL);
if (!table)
return NULL;

table->table = kmem_cache_alloc(amd_iommu_irq_cache, GFP_KERNEL);
table->table = iommu_alloc_pages_node(nid, GFP_KERNEL, order);
if (!table->table) {
kfree(table);
return NULL;
}
raw_spin_lock_init(&table->lock);

if (!AMD_IOMMU_GUEST_IR_GA(amd_iommu_guest_ir))
memset(table->table, 0,
MAX_IRQS_PER_TABLE * sizeof(u32));
else
memset(table->table, 0,
(MAX_IRQS_PER_TABLE * (sizeof(u64) * 2)));
return table;
}

Expand Down Expand Up @@ -3170,13 +3162,23 @@ static int set_remap_table_entry_alias(struct pci_dev *pdev, u16 alias,
return 0;
}

static inline size_t get_irq_table_size(unsigned int max_irqs)
{
if (!AMD_IOMMU_GUEST_IR_GA(amd_iommu_guest_ir))
return max_irqs * sizeof(u32);

return max_irqs * (sizeof(u64) * 2);
}

static struct irq_remap_table *alloc_irq_table(struct amd_iommu *iommu,
u16 devid, struct pci_dev *pdev)
{
struct irq_remap_table *table = NULL;
struct irq_remap_table *new_table = NULL;
struct amd_iommu_pci_seg *pci_seg;
unsigned long flags;
int order = get_order(get_irq_table_size(MAX_IRQS_PER_TABLE));
int nid = iommu && iommu->dev ? dev_to_node(&iommu->dev->dev) : NUMA_NO_NODE;
u16 alias;

spin_lock_irqsave(&iommu_table_lock, flags);
Expand All @@ -3195,7 +3197,7 @@ static struct irq_remap_table *alloc_irq_table(struct amd_iommu *iommu,
spin_unlock_irqrestore(&iommu_table_lock, flags);

/* Nothing there yet, allocate new irq remapping table */
new_table = __alloc_irq_table();
new_table = __alloc_irq_table(nid, order);
if (!new_table)
return NULL;

Expand Down Expand Up @@ -3230,7 +3232,7 @@ static struct irq_remap_table *alloc_irq_table(struct amd_iommu *iommu,
spin_unlock_irqrestore(&iommu_table_lock, flags);

if (new_table) {
kmem_cache_free(amd_iommu_irq_cache, new_table->table);
iommu_free_pages(new_table->table, order);
kfree(new_table);
}
return table;
Expand Down

0 comments on commit eaf717f

Please sign in to comment.