For the 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 the same source, until the software services the interrupts.
- Interrupt aggregation ring size needs to be > 3 * number of Qs.
The Interrupt Engine processes the indirect interrupt with the following steps.
- Interrupt source provides the index to which interrupt ring it belongs too.
- Reads interrupt context for that queue.
- Writes to the Interrupt Aggregation Ring.
- Sends out the PCIe MSI-X message.
This following figure shows the indirect interrupt block diagram.
The Interrupt Context includes the information of the Interrupt Aggregation Ring. It has 256 entries to support up to 256 Interrupt Aggregation Rings.
Color bit is added so software does not read more entries that what it should
read. 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 completes the
entire ring and flips to first entry in the next pass, it also flips the color value to
0 and starts writing 0 in color bit space. The software does the same after it completes
the last entry with a color value 1, and goes to the first entry in the second pass and
expects a color value 0. If the software does not see a color value 0,which indicates an
old entry, it waits for new entry with a color value 0.
The software reads the Interrupt Aggregation Ring to get the Qid
, and the int_type
(H2C or C2H). From the Qid
, the software can identify
whether the queue is stream or MM.
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.
There can be two cases:
- 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 Interrupt Engine sends out the PCIe MSI-X message using the interrupt vector from the Interrupt Context.
When there is an interrupt from any source, the interrupt engine updates PIDX and check
for int_st
of that interrupt context. If int_st
is 0 (WAITING_TRIGGER) then the interrupt engine
will send a interrupt. If int_st
is 1 (ISR_RUNNING),
the interrupt engine will not send interrupt. If the interrupt engine sends interrupt it
will update int_sts
to 1 and once software updated
CIDX and CIDX matches PIDX int_sts
will be cleared.
The process is explained below.
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 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] (0x18000). If the software CIDX is equal to the PIDX, this
will trigger a write to the Interrupt Context to clear int_st
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, the interrupt engine will send out another
PCIe MSI-X message. Therefore, the software can
read the Interrupt Aggregation Ring again. After that, the software can do a pointer
update of the interrupt source ring. For example, if it is C2H stream interrupt, the
software will update pointer of the interrupt source ring, which is the C2H Completion
Ring.
These are the steps for the software:
- After the software gets the PCIe MSI-X message, it reads the Interrupt Aggregation Ring entries.
- The software uses the
coal_color
bit to identify the written entries. Each entry hasQid
andInt_type
(H2C or C2H). From theQid
andInt_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. - After the software finishes reading of all written entries in the
Interrupt Aggregation Ring, it does one dynamic pointer update of the software
cidx
using the register QDMA_DMAP_SEL_INT_CIDX[2048] (0x18000). This communicates to the hardware of the Interrupt Aggregation Ring pointer used by the software.If the software
cidx
is not equal to thepidx
, the hardware will send out another PCIe MSI-X message, so that the software can read the Interrupt Aggregation Ring again.
When the software does the dynamic pointer update for the Interrupt Aggregation Ring using the register QDMA_DMAP_SEL_INT_CIDX[2048] (0x18000), it sends the ring index of the Interrupt Aggregation Ring.
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.