Skip to content

Commit 329ca72

Browse files
committed
iommu/amd: Enable support for up to 2K interrupts per function
JIRA: https://issues.redhat.com/browse/RHEL-22785 Upstream Status: git://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git commit 19e5cc1 Author: Kishon Vijay Abraham I <kvijayab@amd.com> Date: Fri Mar 7 15:28:22 2025 +0530 iommu/amd: Enable support for up to 2K interrupts per function AMD IOMMU optionally supports up to 2K interrupts per function on newer platforms. Support for this feature is indicated through Extended Feature 2 Register (MMIO Offset 01A0h[NumIntRemapSup]). Allocate 2K IRTEs per device when this support is available. Co-developed-by: Sairaj Kodilkar <sarunkod@amd.com> Signed-off-by: Sairaj Kodilkar <sarunkod@amd.com> Signed-off-by: Kishon Vijay Abraham I <kvijayab@amd.com> Reviewed-by: Vasant Hegde <vasant.hegde@amd.com> Link: https://lore.kernel.org/r/20250307095822.2274-5-sarunkod@amd.com Signed-off-by: Joerg Roedel <jroedel@suse.de> Signed-off-by: Eder Zulian <ezulian@redhat.com>
1 parent d464df2 commit 329ca72

File tree

3 files changed

+65
-14
lines changed

3 files changed

+65
-14
lines changed

drivers/iommu/amd/amd_iommu_types.h

Lines changed: 11 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -112,6 +112,10 @@
112112
#define FEATURE_SNPAVICSUP_GAM(x) \
113113
(FIELD_GET(FEATURE_SNPAVICSUP, x) == 0x1)
114114

115+
#define FEATURE_NUM_INT_REMAP_SUP GENMASK_ULL(9, 8)
116+
#define FEATURE_NUM_INT_REMAP_SUP_2K(x) \
117+
(FIELD_GET(FEATURE_NUM_INT_REMAP_SUP, x) == 0x1)
118+
115119
/* Note:
116120
* The current driver only support 16-bit PASID.
117121
* Currently, hardware only implement upto 16-bit PASID
@@ -175,6 +179,9 @@
175179
#define CONTROL_GAM_EN 25
176180
#define CONTROL_GALOG_EN 28
177181
#define CONTROL_GAINT_EN 29
182+
#define CONTROL_NUM_INT_REMAP_MODE 43
183+
#define CONTROL_NUM_INT_REMAP_MODE_MASK 0x03
184+
#define CONTROL_NUM_INT_REMAP_MODE_2K 0x01
178185
#define CONTROL_EPH_EN 45
179186
#define CONTROL_XT_EN 50
180187
#define CONTROL_INTCAPXT_EN 51
@@ -309,14 +316,13 @@
309316
#define DTE_IRQ_REMAP_INTCTL (2ULL << 60)
310317
#define DTE_IRQ_REMAP_ENABLE 1ULL
311318

312-
/*
313-
* AMD IOMMU hardware only support 512 IRTEs despite
314-
* the architectural limitation of 2048 entries.
315-
*/
316319
#define DTE_INTTABLEN_MASK (0xfULL << 1)
317320
#define DTE_INTTABLEN_VALUE_512 9ULL
318321
#define DTE_INTTABLEN_512 (DTE_INTTABLEN_VALUE_512 << 1)
319322
#define MAX_IRQS_PER_TABLE_512 BIT(DTE_INTTABLEN_VALUE_512)
323+
#define DTE_INTTABLEN_VALUE_2K 11ULL
324+
#define DTE_INTTABLEN_2K (DTE_INTTABLEN_VALUE_2K << 1)
325+
#define MAX_IRQS_PER_TABLE_2K BIT(DTE_INTTABLEN_VALUE_2K)
320326

321327
#define PAGE_MODE_NONE 0x00
322328
#define PAGE_MODE_1_LEVEL 0x01
@@ -847,6 +853,7 @@ struct iommu_dev_data {
847853
struct device *dev;
848854
u16 devid; /* PCI Device ID */
849855

856+
unsigned int max_irqs; /* Maximum IRQs supported by device */
850857
u32 max_pasids; /* Max supported PASIDs */
851858
u32 flags; /* Holds AMD_IOMMU_DEVICE_FLAG_<*> */
852859
int ats_qdep;

drivers/iommu/amd/init.c

Lines changed: 15 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1061,7 +1061,8 @@ static bool __copy_device_table(struct amd_iommu *iommu)
10611061
int_tab_len = old_devtb[devid].data[2] & DTE_INTTABLEN_MASK;
10621062
if (irq_v && (int_ctl || int_tab_len)) {
10631063
if ((int_ctl != DTE_IRQ_REMAP_INTCTL) ||
1064-
(int_tab_len != DTE_INTTABLEN_512)) {
1064+
(int_tab_len != DTE_INTTABLEN_512 &&
1065+
int_tab_len != DTE_INTTABLEN_2K)) {
10651066
pr_err("Wrong old irq remapping flag: %#x\n", devid);
10661067
memunmap(old_devtb);
10671068
return false;
@@ -2737,6 +2738,17 @@ static void iommu_enable_irtcachedis(struct amd_iommu *iommu)
27372738
iommu->irtcachedis_enabled ? "disabled" : "enabled");
27382739
}
27392740

2741+
static void iommu_enable_2k_int(struct amd_iommu *iommu)
2742+
{
2743+
if (!FEATURE_NUM_INT_REMAP_SUP_2K(amd_iommu_efr2))
2744+
return;
2745+
2746+
iommu_feature_set(iommu,
2747+
CONTROL_NUM_INT_REMAP_MODE_2K,
2748+
CONTROL_NUM_INT_REMAP_MODE_MASK,
2749+
CONTROL_NUM_INT_REMAP_MODE);
2750+
}
2751+
27402752
static void early_enable_iommu(struct amd_iommu *iommu)
27412753
{
27422754
iommu_disable(iommu);
@@ -2749,6 +2761,7 @@ static void early_enable_iommu(struct amd_iommu *iommu)
27492761
iommu_enable_ga(iommu);
27502762
iommu_enable_xt(iommu);
27512763
iommu_enable_irtcachedis(iommu);
2764+
iommu_enable_2k_int(iommu);
27522765
iommu_enable(iommu);
27532766
amd_iommu_flush_all_caches(iommu);
27542767
}
@@ -2805,6 +2818,7 @@ static void early_enable_iommus(void)
28052818
iommu_enable_ga(iommu);
28062819
iommu_enable_xt(iommu);
28072820
iommu_enable_irtcachedis(iommu);
2821+
iommu_enable_2k_int(iommu);
28082822
iommu_set_device_table(iommu);
28092823
amd_iommu_flush_all_caches(iommu);
28102824
}

drivers/iommu/amd/iommu.c

Lines changed: 39 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -2392,8 +2392,14 @@ static struct iommu_device *amd_iommu_probe_device(struct device *dev)
23922392
}
23932393

23942394
out_err:
2395+
23952396
iommu_completion_wait(iommu);
23962397

2398+
if (FEATURE_NUM_INT_REMAP_SUP_2K(amd_iommu_efr2))
2399+
dev_data->max_irqs = MAX_IRQS_PER_TABLE_2K;
2400+
else
2401+
dev_data->max_irqs = MAX_IRQS_PER_TABLE_512;
2402+
23972403
if (dev_is_pci(dev))
23982404
pci_prepare_ats(to_pci_dev(dev), PAGE_SHIFT);
23992405

@@ -3079,6 +3085,13 @@ static void iommu_flush_irt_and_complete(struct amd_iommu *iommu, u16 devid)
30793085
raw_spin_unlock_irqrestore(&iommu->lock, flags);
30803086
}
30813087

3088+
static inline u8 iommu_get_int_tablen(struct iommu_dev_data *dev_data)
3089+
{
3090+
if (dev_data && dev_data->max_irqs == MAX_IRQS_PER_TABLE_2K)
3091+
return DTE_INTTABLEN_2K;
3092+
return DTE_INTTABLEN_512;
3093+
}
3094+
30823095
static void set_dte_irq_entry(struct amd_iommu *iommu, u16 devid,
30833096
struct irq_remap_table *table)
30843097
{
@@ -3093,7 +3106,7 @@ static void set_dte_irq_entry(struct amd_iommu *iommu, u16 devid,
30933106
new &= ~DTE_IRQ_PHYS_ADDR_MASK;
30943107
new |= iommu_virt_to_phys(table->table);
30953108
new |= DTE_IRQ_REMAP_INTCTL;
3096-
new |= DTE_INTTABLEN_512;
3109+
new |= iommu_get_int_tablen(dev_data);
30973110
new |= DTE_IRQ_REMAP_ENABLE;
30983111
WRITE_ONCE(dte->data[2], new);
30993112

@@ -3174,13 +3187,14 @@ static inline size_t get_irq_table_size(unsigned int max_irqs)
31743187
}
31753188

31763189
static struct irq_remap_table *alloc_irq_table(struct amd_iommu *iommu,
3177-
u16 devid, struct pci_dev *pdev)
3190+
u16 devid, struct pci_dev *pdev,
3191+
unsigned int max_irqs)
31783192
{
31793193
struct irq_remap_table *table = NULL;
31803194
struct irq_remap_table *new_table = NULL;
31813195
struct amd_iommu_pci_seg *pci_seg;
31823196
unsigned long flags;
3183-
int order = get_order(get_irq_table_size(MAX_IRQS_PER_TABLE));
3197+
int order = get_order(get_irq_table_size(max_irqs));
31843198
int nid = iommu && iommu->dev ? dev_to_node(&iommu->dev->dev) : NUMA_NO_NODE;
31853199
u16 alias;
31863200

@@ -3242,13 +3256,14 @@ static struct irq_remap_table *alloc_irq_table(struct amd_iommu *iommu,
32423256
}
32433257

32443258
static int alloc_irq_index(struct amd_iommu *iommu, u16 devid, int count,
3245-
bool align, struct pci_dev *pdev)
3259+
bool align, struct pci_dev *pdev,
3260+
unsigned long max_irqs)
32463261
{
32473262
struct irq_remap_table *table;
32483263
int index, c, alignment = 1;
32493264
unsigned long flags;
32503265

3251-
table = alloc_irq_table(iommu, devid, pdev);
3266+
table = alloc_irq_table(iommu, devid, pdev, max_irqs);
32523267
if (!table)
32533268
return -ENODEV;
32543269

@@ -3259,7 +3274,7 @@ static int alloc_irq_index(struct amd_iommu *iommu, u16 devid, int count,
32593274

32603275
/* Scan table for free entries */
32613276
for (index = ALIGN(table->min_index, alignment), c = 0;
3262-
index < MAX_IRQS_PER_TABLE;) {
3277+
index < max_irqs;) {
32633278
if (!iommu->irte_ops->is_allocated(table, index)) {
32643279
c += 1;
32653280
} else {
@@ -3529,6 +3544,14 @@ static void fill_msi_msg(struct msi_msg *msg, u32 index)
35293544
msg->data = index;
35303545
msg->address_lo = 0;
35313546
msg->arch_addr_lo.base_address = X86_MSI_BASE_ADDRESS_LOW;
3547+
/*
3548+
* The struct msi_msg.dest_mode_logical is used to set the DM bit
3549+
* in MSI Message Address Register. For device w/ 2K int-remap support,
3550+
* this is bit must be set to 1 regardless of the actual destination
3551+
* mode, which is signified by the IRTE[DM].
3552+
*/
3553+
if (FEATURE_NUM_INT_REMAP_SUP_2K(amd_iommu_efr2))
3554+
msg->arch_addr_lo.dest_mode_logical = true;
35323555
msg->address_hi = X86_MSI_BASE_ADDRESS_HIGH;
35333556
}
35343557

@@ -3591,6 +3614,8 @@ static int irq_remapping_alloc(struct irq_domain *domain, unsigned int virq,
35913614
struct amd_ir_data *data = NULL;
35923615
struct amd_iommu *iommu;
35933616
struct irq_cfg *cfg;
3617+
struct iommu_dev_data *dev_data;
3618+
unsigned long max_irqs;
35943619
int i, ret, devid, seg, sbdf;
35953620
int index;
35963621

@@ -3609,14 +3634,17 @@ static int irq_remapping_alloc(struct irq_domain *domain, unsigned int virq,
36093634
if (!iommu)
36103635
return -EINVAL;
36113636

3637+
dev_data = search_dev_data(iommu, devid);
3638+
max_irqs = dev_data ? dev_data->max_irqs : MAX_IRQS_PER_TABLE_512;
3639+
36123640
ret = irq_domain_alloc_irqs_parent(domain, virq, nr_irqs, arg);
36133641
if (ret < 0)
36143642
return ret;
36153643

36163644
if (info->type == X86_IRQ_ALLOC_TYPE_IOAPIC) {
36173645
struct irq_remap_table *table;
36183646

3619-
table = alloc_irq_table(iommu, devid, NULL);
3647+
table = alloc_irq_table(iommu, devid, NULL, max_irqs);
36203648
if (table) {
36213649
if (!table->min_index) {
36223650
/*
@@ -3637,9 +3665,11 @@ static int irq_remapping_alloc(struct irq_domain *domain, unsigned int virq,
36373665
bool align = (info->type == X86_IRQ_ALLOC_TYPE_PCI_MSI);
36383666

36393667
index = alloc_irq_index(iommu, devid, nr_irqs, align,
3640-
msi_desc_to_pci_dev(info->desc));
3668+
msi_desc_to_pci_dev(info->desc),
3669+
max_irqs);
36413670
} else {
3642-
index = alloc_irq_index(iommu, devid, nr_irqs, false, NULL);
3671+
index = alloc_irq_index(iommu, devid, nr_irqs, false, NULL,
3672+
max_irqs);
36433673
}
36443674

36453675
if (index < 0) {

0 commit comments

Comments
 (0)