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_bufffor transmissionmqnic_start_xmit()(mqnic_tx.c): The driver determines the destination transmit queue withskb_get_queue_mappingmqnic_start_xmit()(mqnic_tx.c): The driver marks thesk_bufffor 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_buffintoring->tx_infomqnic_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_rds_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_rdm_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_rds_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_rdm_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_wrs_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_wrm_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_wrs_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_wrm_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_bufffromring->tx_infomqnic_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_infomqnic_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_rds_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_rdm_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_wrs_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_wrm_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_wrs_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_wrm_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_wrs_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_wrm_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_buffhardware 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_bufflengthmqnic_process_rx_cq()(mqnic_rx.c): The driver hands off thesk_bufftonapi_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_infomqnic_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())