In a virtualized environment, the driver attached to a PF has enough privilege to program and access QDMA registers. For all the lesser privileged functions, certain PFs and all VFs must communicate with privileged drivers using the mailbox mechanism. The communication API must be defined by the driver. The QDMA IP does not define it.
Each function (both PF and VF) has an inbox and an outbox that can fit a message size of 128B. A VF accesses its own mailbox, and a PF accesses its own mailbox and all the functions (PF or VF) associated with that PF.
The QDMA mailbox allows the following access:
- From a VF to the associated PF.
- From a PF to any VF belonging to its own virtual function group (VFG).
- From a PF (typically a driver that does not have access to QDMA registers) to another PF.
VF To PF Messaging
A VF is allowed to post one message to a target PF mailbox until the target
function (PF) accepts it. Before posting the message the source function should make
o_msg_status is cleared, then the VF can
write the message to its Outgoing Message Registers. After finishing message
writing, the VF driver sends
through write 0x1 at the control/status register (CSR) address 0x5004. The mailbox
hardware then informs the PF driver by asserting
The function driver should enable the periodic polling of the
i_msg_status to check the availability of incoming
messages. At a PF side,
i_msg_status = 0x1
indicates one or more message is pending for the PF driver to pick up. The
cur_src_fn in the Mailbox Status Register gives the
function ID of the first pending message. The PF driver should then set the Mailbox
Target Function Register to the source function ID of the first pending message.
Then access to a PF’s Incoming Message Registers is indirectly, which means the
mailbox hardware will always return the corresponding message bytes sent by the
Target function. Upon finishing the message reading, the PF driver should also send
msg_rcv command through write 0x2 at the CSR
address. The hardware will deassert the
o_msg_status at the source function side. The following figure
illustrates the messaging flow from a VF to a PF at both the source and destination
PF To VF Messaging
The messaging flow from a PF to the VFs that belong to its VFG is slightly different than the VF to PF flow because:
A PF can send messages to multiple destination functions, therefore, it may
receives multiple acknowledgments at the moment when checking the status. As
illustrated in the following figure, a PF driver must set Mailbox Target Function
Register to the destination function ID before doing any message operation; for
example, checking the incoming message status, write message, or send the command.
At the VF side (receiving side), whenever a VF driver get the
i_msg_status = 0x1, the VF driver should read its
Incoming Message Registers to pick up the message. Depending on the application, the
VF driver can send the
msg_rcv immediately after
reading the message or after the corresponding message being processed.
To avoid one-by-one polling of the status of outgoing messages, the
mailbox hardware provides a set of Acknowledge Status Registers (ASR) for each PF.
Upon the mailbox receiving the
msg_rcv command from
a VF, it deasserts the
o_msg_status field of the
source PF and it also sets the corresponding bit in the Acknowledge Status
Registers. For a given VF with function ID <N>, acknowledge status is at:
- Acknowledge Status Register address: <N> / 32 + <0x22420 Register Address>
- Acknowledge Status bit location: <N> / 32
The mailbox hardware asserts the
filed in the Status Register (0x22400) when there is any bit was asserted in the
Acknowledge Status Register (ASR). The PF driver can poll the
ack_status before actually reading out the Acknowledge
status registers. The PF driver may detect multiple completions through one register
access. After being processed, the PF driver should also write the value back to the
same register address to clear the status.
The mailbox module supports interrupt as the alternative event notification mechanism. Each mailbox has an Interrupt Control Register (at the offset 0x22410 for a PF, or at the offset 0x5010 for a VF). Set 1 to this register to enable the interrupt. Once the interrupt is enabled, the mailbox will send the interrupt to the QDMA given there is any pending event for the mailbox to process, namely, any incoming message pending or any acknowledgment for the outgoing messages. Configure the interrupt vector through the Function Interrupt Vector Register (0x22408 for a FP, or 0x5008 for a VF) according to the driver configuration.
Enabling the interrupt does not change the event logging mechanism, which means the user must check the pending events through reading the Function Status Registers. The first step to respond to an interrupt request is disabling the interrupt. It is possible that the actual number of the pending events is more than the number of the events at the moment when the mailbox is sent the interrupt.
The mailbox will check its event status at the time the interrupt control change from disabled to enabled. If there is any new events that arrived the mailbox between reading the interrupt status and the re-enabling the interrupt, the mailbox will generate a new interrupt request immediately.