Skip to content

Commit e5ebd90

Browse files
hegdevasantjoergroedel
authored andcommitted
iommu/amd: Enable separate interrupt for PPR and GA log
AMD IOMMU has three log buffers (i.e. Event, PPR, and GA). These logs can be configured to generate different interrupts when an entry is inserted into a log buffer. However, current implementation share single interrupt to handle all three logs. With increasing usages of the GA (for IOMMU AVIC) and PPR logs (for IOMMUv2 APIs and SVA), interrupt sharing could potentially become performance bottleneck. Hence, separate IOMMU interrupt into use three separate vectors and irq threads with corresponding name, which will be displayed in the /proc/interrupts as "AMD-Vi<x>-[Evt/PPR/GA]", where "x" is an IOMMU id. Note that this patch changes interrupt handling only in IOMMU x2apic mode (MMIO 0x18[IntCapXTEn]=1). In legacy mode it will continue to use single MSI interrupt. Signed-off-by: Vasant Hegde<[email protected]> Reviewed-by: Alexey Kardashevskiy<[email protected]> Reviewed-by: Jerry Snitselaar <[email protected]> Link: https://lore.kernel.org/r/[email protected] Signed-off-by: Joerg Roedel <[email protected]>
1 parent 2379f34 commit e5ebd90

File tree

2 files changed

+47
-12
lines changed

2 files changed

+47
-12
lines changed

drivers/iommu/amd/amd_iommu_types.h

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -705,12 +705,21 @@ struct amd_iommu {
705705
/* event buffer virtual address */
706706
u8 *evt_buf;
707707

708+
/* Name for event log interrupt */
709+
unsigned char evt_irq_name[16];
710+
708711
/* Base of the PPR log, if present */
709712
u8 *ppr_log;
710713

714+
/* Name for PPR log interrupt */
715+
unsigned char ppr_irq_name[16];
716+
711717
/* Base of the GA log, if present */
712718
u8 *ga_log;
713719

720+
/* Name for GA log interrupt */
721+
unsigned char ga_irq_name[16];
722+
714723
/* Tail of the GA log, if present */
715724
u8 *ga_log_tail;
716725

drivers/iommu/amd/init.c

Lines changed: 38 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -2335,6 +2335,7 @@ static int intcapxt_irqdomain_alloc(struct irq_domain *domain, unsigned int virq
23352335
struct irq_data *irqd = irq_domain_get_irq_data(domain, i);
23362336

23372337
irqd->chip = &intcapxt_controller;
2338+
irqd->hwirq = info->hwirq;
23382339
irqd->chip_data = info->data;
23392340
__irq_set_handler(i, handle_edge_irq, 0, "edge");
23402341
}
@@ -2361,22 +2362,14 @@ static void intcapxt_unmask_irq(struct irq_data *irqd)
23612362
xt.destid_0_23 = cfg->dest_apicid & GENMASK(23, 0);
23622363
xt.destid_24_31 = cfg->dest_apicid >> 24;
23632364

2364-
/**
2365-
* Current IOMMU implementation uses the same IRQ for all
2366-
* 3 IOMMU interrupts.
2367-
*/
2368-
writeq(xt.capxt, iommu->mmio_base + MMIO_INTCAPXT_EVT_OFFSET);
2369-
writeq(xt.capxt, iommu->mmio_base + MMIO_INTCAPXT_PPR_OFFSET);
2370-
writeq(xt.capxt, iommu->mmio_base + MMIO_INTCAPXT_GALOG_OFFSET);
2365+
writeq(xt.capxt, iommu->mmio_base + irqd->hwirq);
23712366
}
23722367

23732368
static void intcapxt_mask_irq(struct irq_data *irqd)
23742369
{
23752370
struct amd_iommu *iommu = irqd->chip_data;
23762371

2377-
writeq(0, iommu->mmio_base + MMIO_INTCAPXT_EVT_OFFSET);
2378-
writeq(0, iommu->mmio_base + MMIO_INTCAPXT_PPR_OFFSET);
2379-
writeq(0, iommu->mmio_base + MMIO_INTCAPXT_GALOG_OFFSET);
2372+
writeq(0, iommu->mmio_base + irqd->hwirq);
23802373
}
23812374

23822375

@@ -2439,7 +2432,8 @@ static struct irq_domain *iommu_get_irqdomain(void)
24392432
return iommu_irqdomain;
24402433
}
24412434

2442-
static int iommu_setup_intcapxt(struct amd_iommu *iommu)
2435+
static int __iommu_setup_intcapxt(struct amd_iommu *iommu, const char *devname,
2436+
int hwirq, irq_handler_t thread_fn)
24432437
{
24442438
struct irq_domain *domain;
24452439
struct irq_alloc_info info;
@@ -2453,6 +2447,7 @@ static int iommu_setup_intcapxt(struct amd_iommu *iommu)
24532447
init_irq_alloc_info(&info, NULL);
24542448
info.type = X86_IRQ_ALLOC_TYPE_AMDVI;
24552449
info.data = iommu;
2450+
info.hwirq = hwirq;
24562451

24572452
irq = irq_domain_alloc_irqs(domain, 1, node, &info);
24582453
if (irq < 0) {
@@ -2461,7 +2456,7 @@ static int iommu_setup_intcapxt(struct amd_iommu *iommu)
24612456
}
24622457

24632458
ret = request_threaded_irq(irq, amd_iommu_int_handler,
2464-
amd_iommu_int_thread, 0, "AMD-Vi", iommu);
2459+
thread_fn, 0, devname, iommu);
24652460
if (ret) {
24662461
irq_domain_free_irqs(irq, 1);
24672462
irq_domain_remove(domain);
@@ -2471,6 +2466,37 @@ static int iommu_setup_intcapxt(struct amd_iommu *iommu)
24712466
return 0;
24722467
}
24732468

2469+
static int iommu_setup_intcapxt(struct amd_iommu *iommu)
2470+
{
2471+
int ret;
2472+
2473+
snprintf(iommu->evt_irq_name, sizeof(iommu->evt_irq_name),
2474+
"AMD-Vi%d-Evt", iommu->index);
2475+
ret = __iommu_setup_intcapxt(iommu, iommu->evt_irq_name,
2476+
MMIO_INTCAPXT_EVT_OFFSET,
2477+
amd_iommu_int_thread_evtlog);
2478+
if (ret)
2479+
return ret;
2480+
2481+
snprintf(iommu->ppr_irq_name, sizeof(iommu->ppr_irq_name),
2482+
"AMD-Vi%d-PPR", iommu->index);
2483+
ret = __iommu_setup_intcapxt(iommu, iommu->ppr_irq_name,
2484+
MMIO_INTCAPXT_PPR_OFFSET,
2485+
amd_iommu_int_thread_pprlog);
2486+
if (ret)
2487+
return ret;
2488+
2489+
#ifdef CONFIG_IRQ_REMAP
2490+
snprintf(iommu->ga_irq_name, sizeof(iommu->ga_irq_name),
2491+
"AMD-Vi%d-GA", iommu->index);
2492+
ret = __iommu_setup_intcapxt(iommu, iommu->ga_irq_name,
2493+
MMIO_INTCAPXT_GALOG_OFFSET,
2494+
amd_iommu_int_thread_galog);
2495+
#endif
2496+
2497+
return ret;
2498+
}
2499+
24742500
static int iommu_init_irq(struct amd_iommu *iommu)
24752501
{
24762502
int ret;

0 commit comments

Comments
 (0)