Interrupt Aggregation Ring - Interrupt Aggregation Ring - 3.4 English - PG347

Versal Adaptive SoC CPM DMA and Bridge Mode for PCI Express Product Guide (PG347)

Document_ID
PG347
Release_Date
2026-07-31
Version
3.4 English

For indirect interrupt, it does interrupt aggregation. The following are some restrictions for the interrupt aggregation.

  • Each Interrupt Aggregation Ring can only be associated with one function. But multiple rings can be associated with the same function.
  • The interrupt engine supports up to three interrupts from same source, until software services the interrupts.

In the indirect interrupt, the QDMA processes the interrupt with the following steps.

  • Look up the QID to Vector Table.
  • Look up the Interrupt Context.
  • Write to the Interrupt Aggregation Ring.
  • Send out the PCIe MSI-X message.

This block diagram is of the indirect interrupt.

Figure 1. Indirect Interrupt

The Interrupt Context includes the information of the Interrupt Aggregation Ring. It has 256 entries to support up to 256 Interrupt Aggregation Rings.

The following is the Interrupt Context Structure (0x8).

Table 1. Interrupt Context Structure (0x8)
Signal Bit Owner Description
pidx [75:64] DMA Producer Index
page_size [63:61] Driver

Interrupt Aggregation Ring size:

  • 0: 4 KB
  • 1: 8 KB
  • 2: 12 KB
  • 3: 16 KB
  • 4: 20 KB
  • 5: 24 KB
  • 6: 28 KB
  • 7: 32 KB
baddr_4k [60:9] Drive Base address of Interrupt Aggregation Ring – bit[63:12]
color [8] DMA Color bit
int_st [7] DMA Interrupt State:

0: WAIT_TRIGGER

1: ISR_RUNNING

reserved [6] NA

Reserved

vec [5:1] Driver Interrupt vector index in MSI-X table
valid [0] Driver Valid

The software needs to size the Interrupt Aggregation Ring appropriately. Each source can send up to three messages to the ring. Therefore, the size of the ring needs satisfy the following formula.

Number of entry >= 3 * (number of queues + error interrupts that are mapped to this ring)

The Interrupt Context is programmed by the context access. The QDMA_IND_CTXT_CMD.Qid has the ring index, which is from the Qid to Vector Table. The operation of MDMA_CTXT_CMD_CLR can clear all of the bits in the Interrupt Context. The MDMA_CTXT_CMD_INV can clear the valid bit.

  • Context access through QDMA_TRQ_SEL_IND:
    • QDMA_IND_CTXT_CMD.Qid = Ring index
    • QDMA_IND_CTXT_CMD.Sel = MDMA_CTXT_SEL_INT_COAL (0x8)
    • QDMA_IND_CTXT_CMD.cmd.Op =
      • MDMA_CTXT_CMD_WR,
      • MDMA_CTXT_CMD_RD,
      • MDMA_CTXT_CMD_CLR, or
      • MDMA_CTXT_CMD_INV.

After it looks up the Interrupt Context, it then writes to the Interrupt Aggregation Ring. It also updates the Interrupt Context with the new PIDX, color, and the interrupt state.

This is the Interrupt Aggregation Ring entry structure. It has 8B data.

Table 2. Interrupt Aggregation Ring Entry Structure
Signal Bit Owner Description
coal_color [63:63] DMA The color bit of the Interrupt Aggregation Ring. This bit inverts every time pidx wraps around on the Interrupt Aggregation Ring.
qid [62:52] DMA This is from Interrupt source. Queue ID.
int_type [51:51] DMA 0: H2C

1: C2H

err_int [50:50] DMA 0: non-error interrupt

1: error interrupt

reserved [49:39] DMA Reserved
stat_desc [38:0] DMA This is the status descriptor of the Interrupt source.

The following is the information in the stat_desc.

Table 3. stat_desc Information
Signal Bit Owner Description
error [38:35] DMA

This is from interrupt source: {c2h_err[1:0], h2c_err[1:0]}

int_st [34:33] DMA This is from Interrupt source. Interrupt state.

0: WRB_INT_ISR

1: WRB_INT_TRIG

2: WRB_INT_ARMED

color [32:32] DMA This is from Interrupt source. This bit inverts every time pidx wraps around and this field gets copied to color field of descriptor.
cidx [31:16] DMA This is from Interrupt source. Cumulative consumed pointer
pidx [15:0] DMA This is from Interrupt source. Cumulative pointer of total interrupt Aggregation Ring entry written

When the software allocates the memory space for the Interrupt Aggregation Ring, the coal_color starts with 1’b0. The software needs to initialize the color bit of the Interrupt Context to be 1’b1. When the hardware writes to the Interrupt Aggregation Ring, it reads color bit from the Interrupt Context, and writes it to the entry. When the ring (PIDX) wraps around, the hardware will flip the color bit in the Interrupt Context. In this way, when the software reads from the Interrupt Aggregation Ring, it will know which entries got written by the hardware by looking at the color bit.

The software reads the Interrupt Aggregation Ring to get the qid, the int_type (H2C or C2H), and the err_int. From the qid, the software can identify it the queue is stream or MM.

When the err_int is set, it is an error interrupt. The software can then check the error status register of the Central Error Aggregator QDMA_GLBL_ERR_STAT (0x248). The register shows the error source. The software can then read the error status register of the Leaf Error Aggregator of the corresponding error.

The stat_desc in the Interrupt Aggregation Ring is the status descriptor from the Interrupt source. When the status descriptor is disabled, the software can get the status descriptor information from the Interrupt Aggregation Ring.

The two cases are as follows:

  • The interrupt source is C2H stream, then it is the status descriptor of the C2H Completion Ring. The software can read the pidx of the C2H Completion Ring.
  • The interrupt source is others (H2C stream, H2C MM, C2H MM), then it is the status descriptor of that source. The software can read the cidx.

Finally, the QDMA sends out the PCIe MSI-X message using the interrupt vector from the Interrupt Context.

When the PCIe MSI-X interrupt is received by the Host, the software reads the Interrupt Aggregation Ring to determine which queue needs service. After the software reads the Interrupt Aggregation Ring, it will do a dynamic pointer update for the software CIDX to indicate the cumulative pointer that the software reads to. The software does the dynamic pointer update using the register QDMA_DMAP_SEL_INT_CIDX[2048] (0x6400). If the software cidx is equal to the pidx, this will trigger a write to the Interrupt Context on the interrupt state of that queue. This is to indicate the QDMA that the software already reads all of the entries in the Interrupt Aggregation Ring. If the software cidx is not equal to the pidx, it will send out another PCIe MSI-X message. Therefore, the software can read the Interrupt Aggregation Ring again. After that, the software can perform a pointer update of the interrupt source ring. For example, for a C2H stream interrupt, the software will update the pointer of the interrupt source ring, which is the C2H Completion Ring.

These are the steps for the software:

  1. After the software gets the PCIe MSI-X message, it reads the Interrupt Aggregation Ring entries.
  2. The software uses the coal_color bit to identify the written entries. Each entry has Qid and Int_type (H2C or C2H). From the Qid and Int_type, the software can check if it is stream or MM. This points to a corresponding source ring. For example, if it is C2H stream, the source ring is the C2H Completion Ring. The software can then read the source ring to get information, and do a dynamic pointer update of the source ring after that.
  3. After the software finishes reading of all written entries, it does one dynamic point update of the software cidx using the register QDMA_DMAP_SEL_INT_CIDX[2048] (0x6400). The Qid in the register is the Qid in the last written entry. This tells hardware the pointer of the Interrupt Aggregation Ring that the software reads to.

    If the software cidx is not equal to the PIDX, the hardware will send out another PCIE MSI-X message, so that the software can read the Interrupt Aggregation Ring again.

When the software performs the dynamic point update for the Interrupt Aggregation Ring using the register QDMA_DMAP_SEL_INT_CIDX[2048] (0x6400), it needs to use the virtual qid. The FMAP block in the hardware translates the virtual qid to absolute qid. The interrupt Engine uses the absolute qid when it looks up the qid to Vector Table.

Figure 2. Interrupt Engine

The following diagram shows the indirect interrupt flow. The Interrupt module gets the interrupt requests. It first writes to the Interrupt Aggregation Ring. Then it waits for the write completions. After that, it sends out the PCIe MSI-X message. The interrupt requests can keep on coming, and the Interrupt module keeps on processing them. In the meantime, the software reads the Interrupt Aggregation Ring and it does the dynamic pointer update. If the software CIDX is not equal to the PIDX, it will send out another PCIe MSI-X message.

Figure 3. Interrupt Flow