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

  1. linux: The Linux kernel calls mqnic_start_xmit() (via ndo_start_xmit()) with an sk_buff for transmission

  2. mqnic_start_xmit() (mqnic_tx.c): The driver determines the destination transmit queue with skb_get_queue_mapping

  3. mqnic_start_xmit() (mqnic_tx.c): The driver marks the sk_buff for timestamping, if requested

  4. mqnic_start_xmit() (mqnic_tx.c): The driver generates the hardware IP checksum command and writes it into the descriptor

  5. mqnic_map_skb() (mqnic_tx.c): The driver writes a reference to the sk_buff into ring->tx_info

  6. mqnic_map_skb() (mqnic_tx.c): The driver generates DMA mappings for the sk_buff (skb_frag_dma_map()/dma_map_single()) and builds the descriptor

  7. mqnic_start_xmit() (mqnic_tx.c): The driver enqueues the packet by incrementing its local copy of the producer pointer

  8. mqnic_start_xmit() (mqnic_tx.c): At the end of a batch of packets, the driver writes the updated producer pointer to the NIC via MMIO

  9. queue_manager s_axil_*: The MMIO write arrives at the queue manager via AXI lite

  10. queue_manager m_axis_doorbell_*: The queue manager updates the producer pointer and generates a doorbell event

  11. tx_scheduler_rr s_axis_doorbell_*: The doorbell event arrives at the port schedulers

  12. tx_scheduler_rr: The scheduler marks the queue as active and schedules it if necessary

  13. tx_scheduler_rr: The scheduler decides to send a packet

  14. tx_scheduler_rr m_axis_tx_req_*: The scheduler generates a transmit request

  15. tx_engine s_axis_tx_req_*: The transmit request arrives at the transmit engine

  16. tx_engine m_axis_desc_req_*: The transmit engine issues a descriptor request

  17. desc_fetch s_axis_desc_req_*: The descriptor request arrives at the descriptor fetch module

  18. desc_fetch m_axis_desc_dequeue_req_*: The descriptor fetch module issues a dequeue request to the queue manager

  19. queue_manager s_axis_dequeue_req_*: The dequeue request arrives at the queue manager module

  20. queue_manager: If the queue is not empty, the queue manager starts a dequeue operation on the queue

  21. queue_manager m_axis_dequeue_resp_*: The queue manager sends a response containing the operation status and DMA address

  22. desc_fetch s_axis_desc_dequeue_resp_*: The response arrives at the descriptor fetch module

  23. desc_fetch m_axis_req_status_*: The descriptor module reports the descriptor fetch status

  24. desc_fetch m_axis_dma_read_desc_*: The descriptor module issues a DMA read request

  25. dma_if_pcie_rd s_axis_read_desc_*: The request arrives at the DMA read interface

  26. dma_if_pcie_rd: The DMA read interface issues a PCIe read request

  27. dma_if_pcie_rd: The read data comes back in a completion packet and is written to the descriptor fetch local DMA RAM

  28. dma_if_pcie_rd m_axis_read_desc_status_*: The DMA read interface issues a status message

  29. desc_fetch m_axis_desc_dequeue_commit_*: The descriptor fetch module issues a dequeue commit message

  30. queue_manager: The queue manager commits the dequeue operation and updates the consumer pointer

  31. desc_fetch dma_read_desc_*: The descriptor fetch module issues a read request to its internal DMA module

  32. desc_fetch m_axis_desc_*: The internal DMA module reads the descriptor and transfers it via AXI stream

  33. tx_engine: The descriptor arrives at the transmit engine

  34. tx_engine: The transmit engine stores the descriptor data

  35. tx_engine m_axis_dma_read_desc_*: The transmit engine issues a DMA read request

  36. dma_if_pcie_rd s_axis_read_desc_*: The request arrives at the DMA read interface

  37. dma_if_pcie_rd: The DMA read interface issues a PCIe read request

  38. dma_if_pcie_rd: The read data comes back in a completion packet and is written to the interface local DMA RAM

  39. dma_if_pcie_rd m_axis_read_desc_status_*: The DMA read interface issues a status message

  40. tx_engine m_axis_tx_desc_*: The transmit engine issues a read request to the interface DMA engine

  41. tx_engine m_axis_tx_csum_cmd_*: The transmit engine issues a transmit checksum command

  42. mqnic_interface_tx tx_axis_*: The interface DMA module reads the packet data from interface local DMA RAM and transfers it via AXI stream

  43. mqnic_egress: egress processing

  44. tx_checksum: The transmit checksum module computes and inserts the checksum

  45. mqnic_app_block s_axis_if_tx: data is presented to the application section

  46. mqnic_app_block m_axis_if_tx: data is returned from the application section

  47. mqnic_core: Data enters per-interface transmit FIFO module and is divided into per-port, per-traffic-class FIFOs

  48. mqnic_app_block s_axis_sync_tx: data is presented to the application section

  49. mqnic_app_block m_axis_sync_tx: data is returned from the application section

  50. mqnic_core: Data enters per-port transmit async FIFO module and is transferred to MAC TX clock domain

  51. mqnic_app_block s_axis_direct_tx: data is presented to the application section

  52. mqnic_app_block m_axis_direct_tx: data is returned from the application section

  53. mqnic_l2_egress: layer 2 egress processing

  54. mqnic_core: data leaves through transmit streaming interfaces

  55. Packet is transmitted and timestamped by MAC

  56. mqnic_core: timestamp and TX tag arrive through TX completion streaming interfaces

  57. mqnic_app_block s_axis_direct_tx_cpl: TX completion is presented to the application section

  58. mqnic_app_block m_axis_direct_tx_cpl: TX completion is returned from the application section

  59. mqnic_core: TX completion enters per-port async FIFO module and is transferred to core clock domain

  60. mqnic_app_block s_axis_sync_tx_cpl: TX completion is presented to the application section

  61. mqnic_app_block m_axis_sync_tx_cpl: TX completion is returned from the application section

  62. mqnic_core: TX completion enters per-interface transmit FIFO module and is placed into per-port FIFOs, then aggregated into a single stream

  63. mqnic_app_block s_axis_if_tx_cpl: TX completion is presented to the application section

  64. mqnic_app_block m_axis_if_tx_cpl: TX completion is returned from the application section

  65. tx_engine: TX completion arrives at the transmit engine

  66. tx_engine m_axis_cpl_req_*: The transmit engine issues a completion write request

  67. cpl_write: The completion write module writes the completion data into its local DMA RAM

  68. cpl_write m_axis_cpl_enqueue_req_*: The completion write module issues an enqueue request to the completion queue manager

  69. cpl_queue_manager m_axis_enqueue_req_*: The enqueue request arrives at the completion queue manager module

  70. cpl_queue_manager: If the queue is not full, the queue manager starts an enqueue operation on the queue

  71. cpl_queue_manager m_axis_enqueue_resp_*: The completion queue manager sends a response containing the operation status and DMA address

  72. cpl_write: The response arrives at the completion write module

  73. cpl_write m_axis_req_status_*: The completion write module reports the completion write status

  74. desc_fetch m_axis_dma_write_desc_*: The completion write module issues a DMA write request

  75. dma_if_pcie_wr s_axis_write_desc_*: The request arrives at the DMA write interface

  76. dma_if_pcie_wr: The DMA write interface reads the completion data from the completion write module local DMA RAM

  77. dma_if_pcie_wr: The DMA write interface issues a PCIe write request

  78. dma_if_pcie_wr m_axis_write_desc_status_*: The DMA write interface issues a status message

  79. cpl_write m_axis_desc_enqueue_commit_*: The completion write module issues an enqueue commit message

  80. cpl_queue_manager: The completion queue manager commits the enqueue operation and updates the producer pointer

  81. cpl_queue_manager m_axis_event_*: The completion queue manager issues an event, if armed

  82. cpl_write: The event arrives at the completion write module

  83. cpl_write: The completion write module writes the event data into its local DMA RAM

  84. cpl_write m_axis_cpl_enqueue_req_*: The completion write module issues an enqueue request to the completion queue manager

  85. cpl_queue_manager s_axis_enqueue_req_*: The enqueue request arrives at the completion queue manager module

  86. cpl_queue_manager: If the queue is not full, the queue manager starts an enqueue operation on the queue

  87. cpl_queue_manager m_axis_enqueue_resp_*: The completion queue manager sends a response containing the operation status and DMA address

  88. cpl_write s_axis_cpl_enqueue_resp_*: The response arrives at the completion write module

  89. cpl_write m_axis_req_status_*: The completion write module reports the completion write status

  90. desc_fetch m_axis_dma_write_desc_*: The completion write module issues a DMA write request

  91. dma_if_pcie_wr s_axis_write_desc_*: The request arrives at the DMA write interface

  92. dma_if_pcie_wr: The DMA write interface reads the event data from the completion write module local DMA RAM

  93. dma_if_pcie_wr: The DMA write interface issues a PCIe write request

  94. dma_if_pcie_wr m_axis_write_desc_status_*: The DMA write interface issues a status message

  95. cpl_write m_axis_desc_enqueue_commit_*: The completion write module issues an enqueue commit message

  96. cpl_queue_manager: The completion queue manager commits the enqueue operation and updates the producer pointer

  97. cpl_queue_manager m_axis_event_*: The completion queue manager issues an interrupt, if armed

  98. linux: The Linux kernel calls mqnic_irq_handler()

  99. mqnic_irq_handler() (mqnic_irq.c): The driver calls the EQ handler via the notifier chain (atomic_notifier_call_chain())

  100. mqnic_eq_int() (mqnic_eq.c): The driver calls mqnic_process_eq()

  101. mqnic_process_eq() (mqnic_eq.c): The driver processes the event queue, which calls the appropriate handler (mqnic_tx_irq())

  102. mqnic_tx_irq() (mqnic_tx.c): The driver enables NAPI polling on the queue (napi_schedule_irqoff())

  103. mqnic_eq_int() (mqnic_eq.c): The driver rearms the EQ (mqnic_arm_eq())

  104. NAPI: The Linux kernel calls mqnic_poll_tx_cq()

  105. mqnic_poll_tx_cq() (mqnic_tx.c): The driver calls mqnic_process_tx_cq()

  106. mqnic_process_tx_cq() (mqnic_tx.c): The driver reads the completion queue producer pointer from the NIC

  107. mqnic_process_tx_cq() (mqnic_tx.c): The driver reads the completion record

  108. mqnic_process_tx_cq() (mqnic_tx.c): The driver reads the sk_buff from ring->tx_info

  109. mqnic_process_tx_cq() (mqnic_tx.c): The driver completes the transmit timestamp operation

  110. mqnic_process_tx_cq() (mqnic_tx.c): The driver calls mqnic_free_tx_desc()

  111. mqnic_free_tx_desc() (mqnic_tx.c): The driver unmaps the sk_buff (dma_unmap_single()/dma_unmap_page())

  112. mqnic_free_tx_desc() (mqnic_tx.c): The driver frees the sk_buff (napi_consume_skb())

  113. mqnic_process_tx_cq() (mqnic_tx.c): The driver dequeues the completion record by incrementing the completion queue consumer pointer

  114. mqnic_process_tx_cq() (mqnic_tx.c): The driver writes the updated consumer pointer via MMIO

  115. mqnic_process_tx_cq() (mqnic_tx.c): The driver reads the queue consumer pointer from the NIC

  116. mqnic_process_tx_cq() (mqnic_tx.c): The driver increments the ring consumer pointer for in-order freed descriptors

  117. mqnic_process_tx_cq() (mqnic_tx.c): The driver wakes the queue if it was stopped (netif_tx_wake_queue())

  118. mqnic_poll_tx_cq() (mqnic_tx.c): The driver disables NAPI polling, when idle (napi_complete())

  119. mqnic_poll_tx_cq() (mqnic_tx.c): The driver rearms the CQ (mqnic_arm_cq())

7.2. Packet reception

init:

  1. mqnic_activate_rx_ring() (mqnic_rx.c): The driver calls mqnic_refill_rx_buffers()

  2. mqnic_refill_rx_buffers() (mqnic_rx.c): The driver calls mqnic_prepare_rx_desc() for each empty location in the ring

  3. mqnic_prepare_rx_desc() (mqnic_rx.c): The driver allocates memory pages (dev_alloc_pages())

  4. mqnic_prepare_rx_desc() (mqnic_rx.c): The driver maps the pages (dev_alloc_pages())

  5. mqnic_prepare_rx_desc() (mqnic_rx.c): The driver writes a pointer to the page struct in ring->rx_info

  6. mqnic_prepare_rx_desc() (mqnic_rx.c): The driver writes a descriptor with the DMA pointer and length

  7. mqnic_refill_rx_buffers() (mqnic_rx.c): The driver enqueues the descriptor by incrementing its local copy of the producer pointer

  8. mqnic_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:

  1. Packet is received and timestamped by MAC

  2. mqnic_core: data enters through receive streaming interfaces

  3. mqnic_l2_ingress: layer 2 ingress processing

  4. mqnic_app_block s_axis_direct_rx: data is presented to the application section

  5. mqnic_app_block m_axis_direct_rx: data is returned from the application section

  6. mqnic_core: Data enters per-port receive async FIFO module and is transferred to core clock domain

  7. mqnic_app_block s_axis_sync_rx: data is presented to the application section

  8. mqnic_app_block m_axis_sync_rx: data is returned from the application section

  9. mqnic_core: Data enters per-interface receive FIFO module and is placed into per-port FIFOs, then aggregated into a single stream

  10. mqnic_app_block s_axis_if_rx: data is presented to the application section

  11. mqnic_app_block m_axis_if_rx: data is returned from the application section

  12. mqnic_ingress: ingress processing

  13. rx_hash: The receive hash module computes the packet flow hash

  14. rx_checksum: The receive checksum module computes the packet payload checksum

  15. mqnic_interface_rx: A receive request is generated

  16. rx_engine: The receive hash arrives at the receive engine

  17. rx_engine: The receive checksum arrives at the receive engine

  18. rx_engine: The receive request arrives at the receive engine

  19. rx_engine m_axis_rx_desc_*: The receive engine issues a write request to the interface DMA engine

  20. mqnic_interface_rx rx_axis_*: The interface DMA module writes the packet data from AXI stream to the interface local DMA RAM

  21. rx_engine m_axis_desc_req_*: The receive engine issues a descriptor request

  22. desc_fetch: The descriptor request arrives at the descriptor fetch module

  23. desc_fetch m_axis_desc_dequeue_req_*: The descriptor fetch module issues a dequeue request to the queue manager

  24. queue_manager s_axis_dequeue_req_*: The dequeue request arrives at the queue manager module

  25. queue_manager: If the queue is not empty, the queue manager starts a dequeue operation on the queue

  26. queue_manager m_axis_dequeue_resp_*: The queue manager sends a response containing the operation status and DMA address

  27. desc_fetch m_axis_desc_dequeue_resp_*: The response arrives at the descriptor fetch module

  28. desc_fetch m_axis_req_status_*: The descriptor module reports the descriptor fetch status

  29. desc_fetch m_axis_dma_read_desc_*: The descriptor module issues a DMA read request

  30. dma_if_pcie_us_rd s_axis_read_desc_*: The request arrives at the DMA read interface

  31. dma_if_pcie_us_rd: The DMA read interface issues a PCIe read request

  32. dma_if_pcie_us_rd: The read data comes back in a completion packet and is written to the descriptor fetch local DMA RAM

  33. dma_if_pcie_us_rd m_axis_read_desc_status_*: The DMA read interface issues a status message

  34. desc_fetch m_axis_desc_dequeue_commit_*: The descriptor fetch module issues a dequeue commit message

  35. queue_manager: The queue manager commits the dequeue operation and updates the consumer pointer

  36. desc_fetch dma_read_desc_*: The descriptor fetch module issues a read request to its internal DMA module

  37. desc_fetch m_axis_desc_*: The internal DMA module reads the descriptor and transfers it via AXI stream

  38. rx_engine: The descriptor arrives at the receive engine

  39. rx_engine: The receive engine stores the descriptor data

  40. rx_engine m_axis_dma_write_desc_*: The receive engine issues a DMA write request

  41. dma_if_pcie_us_wr s_axis_write_desc_*: The request arrives at the DMA write interface

  42. dma_if_pcie_us_wr: The DMA write interface reads the packet data from the interface local DMA RAM

  43. dma_if_pcie_us_wr: The DMA write interface issues a PCIe write request

  44. dma_if_pcie_us_wr m_axis_write_desc_status_*: The DMA write interface issues a status message

  45. rx_engine m_axis_cpl_req_*: The receive engine issues a completion write request

  46. cpl_write: The completion write module writes the completion data into its local DMA RAM

  47. cpl_write m_axis_cpl_enqueue_req_*: The completion write module issues an enqueue request to the completion queue manager

  48. cpl_queue_manager s_axis_enqueue_req_*: The enqueue request arrives at the completion queue manager module

  49. cpl_queue_manager: If the queue is not full, the queue manager starts an enqueue operation on the queue

  50. cpl_queue_manager m_axis_enqueue_resp_*: The completion queue manager sends a response containing the operation status and DMA address

  51. cpl_write s_axis_cpl_enqueue_resp_*: The response arrives at the completion write module

  52. cpl_write m_axis_req_status_*: The completion write module reports the completion write status

  53. desc_fetch m_axis_dma_write_desc_*: The completion write module issues a DMA write request

  54. dma_if_pcie_us_wr s_axis_write_desc_*: The request arrives at the DMA write interface

  55. dma_if_pcie_us_wr: The DMA write interface reads the completion data from the completion write module local DMA RAM

  56. dma_if_pcie_us_wr: The DMA write interface issues a PCIe write request

  57. dma_if_pcie_us_wr m_axis_write_desc_status_*: The DMA write interface issues a status message

  58. cpl_write m_axis_desc_enqueue_commit_*: The completion write module issues an enqueue commit message

  59. cpl_queue_manager: The completion queue manager commits the enqueue operation and updates the producer pointer

  60. cpl_queue_manager m_axis_event_*: The completion queue manager issues an event, if armed

  61. cpl_write: The event arrives at the completion write module

  62. cpl_write: The completion write module writes the event data into its local DMA RAM

  63. cpl_write m_axis_cpl_enqueue_req_*: The completion write module issues an enqueue request to the completion queue manager

  64. cpl_queue_manager s_axis_enqueue_req_*: The enqueue request arrives at the completion queue manager module

  65. cpl_queue_manager: If the queue is not full, the queue manager starts an enqueue operation on the queue

  66. cpl_queue_manager m_axis_enqueue_resp_*: The completion queue manager sends a response containing the operation status and DMA address

  67. cpl_write s_axis_cpl_enqueue_resp_*: The response arrives at the completion write module

  68. cpl_write m_axis_req_status_*: The completion write module reports the completion write status

  69. desc_fetch m_axis_dma_write_desc_*: The completion write module issues a DMA write request

  70. dma_if_pcie_us_wr s_axis_write_desc_*: The request arrives at the DMA write interface

  71. dma_if_pcie_us_wr: The DMA write interface reads the event data from the completion write module local DMA RAM

  72. dma_if_pcie_us_wr: The DMA write interface issues a PCIe write request

  73. dma_if_pcie_us_wr m_axis_write_desc_status_*: The DMA write interface issues a status message

  74. cpl_write m_axis_desc_enqueue_commit_*: The completion write module issues an enqueue commit message

  75. cpl_queue_manager: The completion queue manager commits the enqueue operation and updates the producer pointer

  76. cpl_queue_manager m_axis_event_*: The completion queue manager issues an interrupt, if armed

  77. linux: The Linux kernel calls mqnic_irq_handler()

  78. mqnic_irq_handler() (mqnic_irq.c): The driver calls the EQ handler via the notifier chain (atomic_notifier_call_chain())

  79. mqnic_eq_int() (mqnic_eq.c): The driver calls mqnic_process_eq()

  80. mqnic_process_eq() (mqnic_eq.c): The driver processes the event queue, which calls the appropriate handler (mqnic_rx_irq())

  81. mqnic_rx_irq() (mqnic_rx.c): The driver enables NAPI polling on the queue (napi_schedule_irqoff())

  82. mqnic_eq_int() (mqnic_eq.c): The driver rearms the EQ (mqnic_arm_eq())

  83. NAPI: The Linux kernel calls mqnic_poll_rx_cq()

  84. mqnic_poll_rx_cq() (mqnic_rx.c): The driver calls mqnic_process_rx_cq()

  85. mqnic_process_rx_cq() (mqnic_rx.c): The driver reads the CQ producer pointer from the NIC

  86. mqnic_process_rx_cq() (mqnic_rx.c): The driver reads the completion record

  87. mqnic_process_rx_cq() (mqnic_rx.c): The driver fetches a fresh sk_buff (napi_get_frags())

  88. mqnic_process_rx_cq() (mqnic_rx.c): The driver sets the sk_buff hardware timestamp

  89. mqnic_process_rx_cq() (mqnic_rx.c): The driver unmaps the pages (dma_unmap_page())

  90. mqnic_process_rx_cq() (mqnic_rx.c): The driver associates the pages with the sk_buff (__skb_fill_page_desc())

  91. mqnic_process_rx_cq() (mqnic_rx.c): The driver sets the sk_buff length

  92. mqnic_process_rx_cq() (mqnic_rx.c): The driver hands off the sk_buff to napi_gro_frags()

  93. mqnic_process_rx_cq() (mqnic_rx.c): The driver dequeues the completion record by incrementing the CQ consumer pointer

  94. mqnic_process_rx_cq() (mqnic_rx.c): The driver writes the updated CQ consumer pointer via MMIO

  95. mqnic_process_rx_cq() (mqnic_rx.c): The driver reads the queue consumer pointer from the NIC

  96. mqnic_process_rx_cq() (mqnic_rx.c): The driver increments the ring consumer pointer for in-order freed descriptors

  97. mqnic_process_rx_cq() (mqnic_rx.c): The driver calls mqnic_refill_rx_buffers()

  98. mqnic_refill_rx_buffers() (mqnic_rx.c): The driver calls mqnic_prepare_rx_desc() for each empty location in the ring

  99. mqnic_prepare_rx_desc() (mqnic_rx.c): The driver allocates memory pages (dev_alloc_pages())

  100. mqnic_prepare_rx_desc() (mqnic_rx.c): The driver maps the pages (dev_alloc_pages())

  101. mqnic_prepare_rx_desc() (mqnic_rx.c): The driver writes a pointer to the page struct in ring->rx_info

  102. mqnic_prepare_rx_desc() (mqnic_rx.c): The driver writes a descriptor with the DMA pointer and length

  103. mqnic_refill_rx_buffers() (mqnic_rx.c): The driver enqueues the descriptor by incrementing its local copy of the producer pointer

  104. mqnic_refill_rx_buffers() (mqnic_rx.c): At the end of the loop, the driver writes the updated producer pointer to the NIC via MMIO

  105. mqnic_poll_rx_cq() (mqnic_rx.c): The driver disables NAPI polling, when idle (napi_complete())

  106. mqnic_poll_rx_cq() (mqnic_rx.c): The driver rearms the CQ (mqnic_arm_cq())