7. Operations
This is a list of all of the operations involved in sending and receiving packets, across both hardware and software.
7.1. Packet transmission
linux: The Linux kernel calls
mqnic_start_xmit()
(viando_start_xmit()
) with ansk_buff
for transmissionmqnic_start_xmit()
(mqnic_tx.c
): The driver determines the destination transmit queue withskb_get_queue_mapping
mqnic_start_xmit()
(mqnic_tx.c
): The driver marks thesk_buff
for timestamping, if requestedmqnic_start_xmit()
(mqnic_tx.c
): The driver generates the hardware IP checksum command and writes it into the descriptormqnic_map_skb()
(mqnic_tx.c
): The driver writes a reference to thesk_buff
intoring->tx_info
mqnic_map_skb()
(mqnic_tx.c
): The driver generates DMA mappings for thesk_buff
(skb_frag_dma_map()
/dma_map_single()
) and builds the descriptormqnic_start_xmit()
(mqnic_tx.c
): The driver enqueues the packet by incrementing its local copy of the producer pointermqnic_start_xmit()
(mqnic_tx.c
): At the end of a batch of packets, the driver writes the updated producer pointer to the NIC via MMIOqueue_manager
s_axil_*
: The MMIO write arrives at the queue manager via AXI litequeue_manager
m_axis_doorbell_*
: The queue manager updates the producer pointer and generates a doorbell eventtx_scheduler_rr
s_axis_doorbell_*
: The doorbell event arrives at the port schedulerstx_scheduler_rr: The scheduler marks the queue as active and schedules it if necessary
tx_scheduler_rr: The scheduler decides to send a packet
tx_scheduler_rr
m_axis_tx_req_*
: The scheduler generates a transmit requesttx_engine
s_axis_tx_req_*
: The transmit request arrives at the transmit enginetx_engine
m_axis_desc_req_*
: The transmit engine issues a descriptor requestdesc_fetch
s_axis_desc_req_*
: The descriptor request arrives at the descriptor fetch moduledesc_fetch
m_axis_desc_dequeue_req_*
: The descriptor fetch module issues a dequeue request to the queue managerqueue_manager
s_axis_dequeue_req_*
: The dequeue request arrives at the queue manager modulequeue_manager: If the queue is not empty, the queue manager starts a dequeue operation on the queue
queue_manager
m_axis_dequeue_resp_*
: The queue manager sends a response containing the operation status and DMA addressdesc_fetch
s_axis_desc_dequeue_resp_*
: The response arrives at the descriptor fetch moduledesc_fetch
m_axis_req_status_*
: The descriptor module reports the descriptor fetch statusdesc_fetch
m_axis_dma_read_desc_*
: The descriptor module issues a DMA read requestdma_if_pcie_rd
s_axis_read_desc_*
: The request arrives at the DMA read interfacedma_if_pcie_rd
: The DMA read interface issues a PCIe read requestdma_if_pcie_rd
: The read data comes back in a completion packet and is written to the descriptor fetch local DMA RAMdma_if_pcie_rd
m_axis_read_desc_status_*
: The DMA read interface issues a status messagedesc_fetch
m_axis_desc_dequeue_commit_*
: The descriptor fetch module issues a dequeue commit messagequeue_manager: The queue manager commits the dequeue operation and updates the consumer pointer
desc_fetch
dma_read_desc_*
: The descriptor fetch module issues a read request to its internal DMA moduledesc_fetch
m_axis_desc_*
: The internal DMA module reads the descriptor and transfers it via AXI streamtx_engine: The descriptor arrives at the transmit engine
tx_engine: The transmit engine stores the descriptor data
tx_engine
m_axis_dma_read_desc_*
: The transmit engine issues a DMA read requestdma_if_pcie_rd
s_axis_read_desc_*
: The request arrives at the DMA read interfacedma_if_pcie_rd
: The DMA read interface issues a PCIe read requestdma_if_pcie_rd
: The read data comes back in a completion packet and is written to the interface local DMA RAMdma_if_pcie_rd
m_axis_read_desc_status_*
: The DMA read interface issues a status messagetx_engine
m_axis_tx_desc_*
: The transmit engine issues a read request to the interface DMA enginetx_engine
m_axis_tx_csum_cmd_*
: The transmit engine issues a transmit checksum commandmqnic_interface_tx
tx_axis_*
: The interface DMA module reads the packet data from interface local DMA RAM and transfers it via AXI streammqnic_egress: egress processing
tx_checksum: The transmit checksum module computes and inserts the checksum
mqnic_app_block
s_axis_if_tx
: data is presented to the application sectionmqnic_app_block
m_axis_if_tx
: data is returned from the application sectionmqnic_core: Data enters per-interface transmit FIFO module and is divided into per-port, per-traffic-class FIFOs
mqnic_app_block
s_axis_sync_tx
: data is presented to the application sectionmqnic_app_block
m_axis_sync_tx
: data is returned from the application sectionmqnic_core: Data enters per-port transmit async FIFO module and is transferred to MAC TX clock domain
mqnic_app_block
s_axis_direct_tx
: data is presented to the application sectionmqnic_app_block
m_axis_direct_tx
: data is returned from the application sectionmqnic_l2_egress: layer 2 egress processing
mqnic_core: data leaves through transmit streaming interfaces
Packet is transmitted and timestamped by MAC
mqnic_core: timestamp and TX tag arrive through TX completion streaming interfaces
mqnic_app_block
s_axis_direct_tx_cpl
: TX completion is presented to the application sectionmqnic_app_block
m_axis_direct_tx_cpl
: TX completion is returned from the application sectionmqnic_core: TX completion enters per-port async FIFO module and is transferred to core clock domain
mqnic_app_block
s_axis_sync_tx_cpl
: TX completion is presented to the application sectionmqnic_app_block
m_axis_sync_tx_cpl
: TX completion is returned from the application sectionmqnic_core: TX completion enters per-interface transmit FIFO module and is placed into per-port FIFOs, then aggregated into a single stream
mqnic_app_block
s_axis_if_tx_cpl
: TX completion is presented to the application sectionmqnic_app_block
m_axis_if_tx_cpl
: TX completion is returned from the application sectiontx_engine: TX completion arrives at the transmit engine
tx_engine
m_axis_cpl_req_*
: The transmit engine issues a completion write requestcpl_write: The completion write module writes the completion data into its local DMA RAM
cpl_write
m_axis_cpl_enqueue_req_*
: The completion write module issues an enqueue request to the completion queue managercpl_queue_manager
m_axis_enqueue_req_*
: The enqueue request arrives at the completion queue manager modulecpl_queue_manager: If the queue is not full, the queue manager starts an enqueue operation on the queue
cpl_queue_manager
m_axis_enqueue_resp_*
: The completion queue manager sends a response containing the operation status and DMA addresscpl_write: The response arrives at the completion write module
cpl_write
m_axis_req_status_*
: The completion write module reports the completion write statusdesc_fetch
m_axis_dma_write_desc_*
: The completion write module issues a DMA write requestdma_if_pcie_wr
s_axis_write_desc_*
: The request arrives at the DMA write interfacedma_if_pcie_wr
: The DMA write interface reads the completion data from the completion write module local DMA RAMdma_if_pcie_wr
: The DMA write interface issues a PCIe write requestdma_if_pcie_wr
m_axis_write_desc_status_*
: The DMA write interface issues a status messagecpl_write
m_axis_desc_enqueue_commit_*
: The completion write module issues an enqueue commit messagecpl_queue_manager: The completion queue manager commits the enqueue operation and updates the producer pointer
cpl_queue_manager
m_axis_event_*
: The completion queue manager issues an event, if armedcpl_write: The event arrives at the completion write module
cpl_write: The completion write module writes the event data into its local DMA RAM
cpl_write
m_axis_cpl_enqueue_req_*
: The completion write module issues an enqueue request to the completion queue managercpl_queue_manager
s_axis_enqueue_req_*
: The enqueue request arrives at the completion queue manager modulecpl_queue_manager: If the queue is not full, the queue manager starts an enqueue operation on the queue
cpl_queue_manager
m_axis_enqueue_resp_*
: The completion queue manager sends a response containing the operation status and DMA addresscpl_write
s_axis_cpl_enqueue_resp_*
: The response arrives at the completion write modulecpl_write
m_axis_req_status_*
: The completion write module reports the completion write statusdesc_fetch
m_axis_dma_write_desc_*
: The completion write module issues a DMA write requestdma_if_pcie_wr
s_axis_write_desc_*
: The request arrives at the DMA write interfacedma_if_pcie_wr
: The DMA write interface reads the event data from the completion write module local DMA RAMdma_if_pcie_wr
: The DMA write interface issues a PCIe write requestdma_if_pcie_wr
m_axis_write_desc_status_*
: The DMA write interface issues a status messagecpl_write
m_axis_desc_enqueue_commit_*
: The completion write module issues an enqueue commit messagecpl_queue_manager: The completion queue manager commits the enqueue operation and updates the producer pointer
cpl_queue_manager
m_axis_event_*
: The completion queue manager issues an interrupt, if armedlinux: The Linux kernel calls
mqnic_irq_handler()
mqnic_irq_handler()
(mqnic_irq.c
): The driver calls the EQ handler via the notifier chain (atomic_notifier_call_chain()
)mqnic_eq_int()
(mqnic_eq.c
): The driver callsmqnic_process_eq()
mqnic_process_eq()
(mqnic_eq.c
): The driver processes the event queue, which calls the appropriate handler (mqnic_tx_irq()
)mqnic_tx_irq()
(mqnic_tx.c
): The driver enables NAPI polling on the queue (napi_schedule_irqoff()
)mqnic_eq_int()
(mqnic_eq.c
): The driver rearms the EQ (mqnic_arm_eq()
)NAPI: The Linux kernel calls
mqnic_poll_tx_cq()
mqnic_poll_tx_cq()
(mqnic_tx.c
): The driver callsmqnic_process_tx_cq()
mqnic_process_tx_cq()
(mqnic_tx.c
): The driver reads the completion queue producer pointer from the NICmqnic_process_tx_cq()
(mqnic_tx.c
): The driver reads the completion recordmqnic_process_tx_cq()
(mqnic_tx.c
): The driver reads thesk_buff
fromring->tx_info
mqnic_process_tx_cq()
(mqnic_tx.c
): The driver completes the transmit timestamp operationmqnic_process_tx_cq()
(mqnic_tx.c
): The driver callsmqnic_free_tx_desc()
mqnic_free_tx_desc()
(mqnic_tx.c
): The driver unmaps thesk_buff
(dma_unmap_single()
/dma_unmap_page()
)mqnic_free_tx_desc()
(mqnic_tx.c
): The driver frees thesk_buff
(napi_consume_skb()
)mqnic_process_tx_cq()
(mqnic_tx.c
): The driver dequeues the completion record by incrementing the completion queue consumer pointermqnic_process_tx_cq()
(mqnic_tx.c
): The driver writes the updated consumer pointer via MMIOmqnic_process_tx_cq()
(mqnic_tx.c
): The driver reads the queue consumer pointer from the NICmqnic_process_tx_cq()
(mqnic_tx.c
): The driver increments the ring consumer pointer for in-order freed descriptorsmqnic_process_tx_cq()
(mqnic_tx.c
): The driver wakes the queue if it was stopped (netif_tx_wake_queue()
)mqnic_poll_tx_cq()
(mqnic_tx.c
): The driver disables NAPI polling, when idle (napi_complete()
)mqnic_poll_tx_cq()
(mqnic_tx.c
): The driver rearms the CQ (mqnic_arm_cq()
)
7.2. Packet reception
init:
mqnic_activate_rx_ring()
(mqnic_rx.c
): The driver callsmqnic_refill_rx_buffers()
mqnic_refill_rx_buffers()
(mqnic_rx.c
): The driver callsmqnic_prepare_rx_desc()
for each empty location in the ringmqnic_prepare_rx_desc()
(mqnic_rx.c
): The driver allocates memory pages (dev_alloc_pages()
)mqnic_prepare_rx_desc()
(mqnic_rx.c
): The driver maps the pages (dev_alloc_pages()
)mqnic_prepare_rx_desc()
(mqnic_rx.c
): The driver writes a pointer to the page struct inring->rx_info
mqnic_prepare_rx_desc()
(mqnic_rx.c
): The driver writes a descriptor with the DMA pointer and lengthmqnic_refill_rx_buffers()
(mqnic_rx.c
): The driver enqueues the descriptor by incrementing its local copy of the producer pointermqnic_refill_rx_buffers()
(mqnic_rx.c
): At the end of the loop, the driver writes the updated producer pointer to the NIC via MMIO
receive:
Packet is received and timestamped by MAC
mqnic_core: data enters through receive streaming interfaces
mqnic_l2_ingress: layer 2 ingress processing
mqnic_app_block
s_axis_direct_rx
: data is presented to the application sectionmqnic_app_block
m_axis_direct_rx
: data is returned from the application sectionmqnic_core: Data enters per-port receive async FIFO module and is transferred to core clock domain
mqnic_app_block
s_axis_sync_rx
: data is presented to the application sectionmqnic_app_block
m_axis_sync_rx
: data is returned from the application sectionmqnic_core: Data enters per-interface receive FIFO module and is placed into per-port FIFOs, then aggregated into a single stream
mqnic_app_block
s_axis_if_rx
: data is presented to the application sectionmqnic_app_block
m_axis_if_rx
: data is returned from the application sectionmqnic_ingress: ingress processing
rx_hash: The receive hash module computes the packet flow hash
rx_checksum: The receive checksum module computes the packet payload checksum
mqnic_interface_rx: A receive request is generated
rx_engine: The receive hash arrives at the receive engine
rx_engine: The receive checksum arrives at the receive engine
rx_engine: The receive request arrives at the receive engine
rx_engine
m_axis_rx_desc_*
: The receive engine issues a write request to the interface DMA enginemqnic_interface_rx
rx_axis_*
: The interface DMA module writes the packet data from AXI stream to the interface local DMA RAMrx_engine
m_axis_desc_req_*
: The receive engine issues a descriptor requestdesc_fetch: The descriptor request arrives at the descriptor fetch module
desc_fetch
m_axis_desc_dequeue_req_*
: The descriptor fetch module issues a dequeue request to the queue managerqueue_manager
s_axis_dequeue_req_*
: The dequeue request arrives at the queue manager modulequeue_manager: If the queue is not empty, the queue manager starts a dequeue operation on the queue
queue_manager
m_axis_dequeue_resp_*
: The queue manager sends a response containing the operation status and DMA addressdesc_fetch
m_axis_desc_dequeue_resp_*
: The response arrives at the descriptor fetch moduledesc_fetch
m_axis_req_status_*
: The descriptor module reports the descriptor fetch statusdesc_fetch
m_axis_dma_read_desc_*
: The descriptor module issues a DMA read requestdma_if_pcie_us_rd
s_axis_read_desc_*
: The request arrives at the DMA read interfacedma_if_pcie_us_rd
: The DMA read interface issues a PCIe read requestdma_if_pcie_us_rd
: The read data comes back in a completion packet and is written to the descriptor fetch local DMA RAMdma_if_pcie_us_rd
m_axis_read_desc_status_*
: The DMA read interface issues a status messagedesc_fetch
m_axis_desc_dequeue_commit_*
: The descriptor fetch module issues a dequeue commit messagequeue_manager: The queue manager commits the dequeue operation and updates the consumer pointer
desc_fetch
dma_read_desc_*
: The descriptor fetch module issues a read request to its internal DMA moduledesc_fetch
m_axis_desc_*
: The internal DMA module reads the descriptor and transfers it via AXI streamrx_engine: The descriptor arrives at the receive engine
rx_engine: The receive engine stores the descriptor data
rx_engine
m_axis_dma_write_desc_*
: The receive engine issues a DMA write requestdma_if_pcie_us_wr
s_axis_write_desc_*
: The request arrives at the DMA write interfacedma_if_pcie_us_wr
: The DMA write interface reads the packet data from the interface local DMA RAMdma_if_pcie_us_wr
: The DMA write interface issues a PCIe write requestdma_if_pcie_us_wr
m_axis_write_desc_status_*
: The DMA write interface issues a status messagerx_engine
m_axis_cpl_req_*
: The receive engine issues a completion write requestcpl_write: The completion write module writes the completion data into its local DMA RAM
cpl_write
m_axis_cpl_enqueue_req_*
: The completion write module issues an enqueue request to the completion queue managercpl_queue_manager
s_axis_enqueue_req_*
: The enqueue request arrives at the completion queue manager modulecpl_queue_manager: If the queue is not full, the queue manager starts an enqueue operation on the queue
cpl_queue_manager
m_axis_enqueue_resp_*
: The completion queue manager sends a response containing the operation status and DMA addresscpl_write
s_axis_cpl_enqueue_resp_*
: The response arrives at the completion write modulecpl_write
m_axis_req_status_*
: The completion write module reports the completion write statusdesc_fetch
m_axis_dma_write_desc_*
: The completion write module issues a DMA write requestdma_if_pcie_us_wr
s_axis_write_desc_*
: The request arrives at the DMA write interfacedma_if_pcie_us_wr
: The DMA write interface reads the completion data from the completion write module local DMA RAMdma_if_pcie_us_wr
: The DMA write interface issues a PCIe write requestdma_if_pcie_us_wr
m_axis_write_desc_status_*
: The DMA write interface issues a status messagecpl_write
m_axis_desc_enqueue_commit_*
: The completion write module issues an enqueue commit messagecpl_queue_manager: The completion queue manager commits the enqueue operation and updates the producer pointer
cpl_queue_manager
m_axis_event_*
: The completion queue manager issues an event, if armedcpl_write: The event arrives at the completion write module
cpl_write: The completion write module writes the event data into its local DMA RAM
cpl_write
m_axis_cpl_enqueue_req_*
: The completion write module issues an enqueue request to the completion queue managercpl_queue_manager
s_axis_enqueue_req_*
: The enqueue request arrives at the completion queue manager modulecpl_queue_manager: If the queue is not full, the queue manager starts an enqueue operation on the queue
cpl_queue_manager
m_axis_enqueue_resp_*
: The completion queue manager sends a response containing the operation status and DMA addresscpl_write
s_axis_cpl_enqueue_resp_*
: The response arrives at the completion write modulecpl_write
m_axis_req_status_*
: The completion write module reports the completion write statusdesc_fetch
m_axis_dma_write_desc_*
: The completion write module issues a DMA write requestdma_if_pcie_us_wr
s_axis_write_desc_*
: The request arrives at the DMA write interfacedma_if_pcie_us_wr
: The DMA write interface reads the event data from the completion write module local DMA RAMdma_if_pcie_us_wr
: The DMA write interface issues a PCIe write requestdma_if_pcie_us_wr
m_axis_write_desc_status_*
: The DMA write interface issues a status messagecpl_write
m_axis_desc_enqueue_commit_*
: The completion write module issues an enqueue commit messagecpl_queue_manager: The completion queue manager commits the enqueue operation and updates the producer pointer
cpl_queue_manager
m_axis_event_*
: The completion queue manager issues an interrupt, if armedlinux: The Linux kernel calls
mqnic_irq_handler()
mqnic_irq_handler()
(mqnic_irq.c
): The driver calls the EQ handler via the notifier chain (atomic_notifier_call_chain()
)mqnic_eq_int()
(mqnic_eq.c
): The driver callsmqnic_process_eq()
mqnic_process_eq()
(mqnic_eq.c
): The driver processes the event queue, which calls the appropriate handler (mqnic_rx_irq()
)mqnic_rx_irq()
(mqnic_rx.c
): The driver enables NAPI polling on the queue (napi_schedule_irqoff()
)mqnic_eq_int()
(mqnic_eq.c
): The driver rearms the EQ (mqnic_arm_eq()
)NAPI: The Linux kernel calls
mqnic_poll_rx_cq()
mqnic_poll_rx_cq()
(mqnic_rx.c
): The driver callsmqnic_process_rx_cq()
mqnic_process_rx_cq()
(mqnic_rx.c
): The driver reads the CQ producer pointer from the NICmqnic_process_rx_cq()
(mqnic_rx.c
): The driver reads the completion recordmqnic_process_rx_cq()
(mqnic_rx.c
): The driver fetches a freshsk_buff
(napi_get_frags()
)mqnic_process_rx_cq()
(mqnic_rx.c
): The driver sets thesk_buff
hardware timestampmqnic_process_rx_cq()
(mqnic_rx.c
): The driver unmaps the pages (dma_unmap_page()
)mqnic_process_rx_cq()
(mqnic_rx.c
): The driver associates the pages with thesk_buff
(__skb_fill_page_desc()
)mqnic_process_rx_cq()
(mqnic_rx.c
): The driver sets thesk_buff
lengthmqnic_process_rx_cq()
(mqnic_rx.c
): The driver hands off thesk_buff
tonapi_gro_frags()
mqnic_process_rx_cq()
(mqnic_rx.c
): The driver dequeues the completion record by incrementing the CQ consumer pointermqnic_process_rx_cq()
(mqnic_rx.c
): The driver writes the updated CQ consumer pointer via MMIOmqnic_process_rx_cq()
(mqnic_rx.c
): The driver reads the queue consumer pointer from the NICmqnic_process_rx_cq()
(mqnic_rx.c
): The driver increments the ring consumer pointer for in-order freed descriptorsmqnic_process_rx_cq()
(mqnic_rx.c
): The driver callsmqnic_refill_rx_buffers()
mqnic_refill_rx_buffers()
(mqnic_rx.c
): The driver callsmqnic_prepare_rx_desc()
for each empty location in the ringmqnic_prepare_rx_desc()
(mqnic_rx.c
): The driver allocates memory pages (dev_alloc_pages()
)mqnic_prepare_rx_desc()
(mqnic_rx.c
): The driver maps the pages (dev_alloc_pages()
)mqnic_prepare_rx_desc()
(mqnic_rx.c
): The driver writes a pointer to the page struct inring->rx_info
mqnic_prepare_rx_desc()
(mqnic_rx.c
): The driver writes a descriptor with the DMA pointer and lengthmqnic_refill_rx_buffers()
(mqnic_rx.c
): The driver enqueues the descriptor by incrementing its local copy of the producer pointermqnic_refill_rx_buffers()
(mqnic_rx.c
): At the end of the loop, the driver writes the updated producer pointer to the NIC via MMIOmqnic_poll_rx_cq()
(mqnic_rx.c
): The driver disables NAPI polling, when idle (napi_complete()
)mqnic_poll_rx_cq()
(mqnic_rx.c
): The driver rearms the CQ (mqnic_arm_cq()
)