From 265035769afb94626c2f39411ede4e0aaf592312 Mon Sep 17 00:00:00 2001 From: Alex Forencich Date: Fri, 7 Jul 2023 01:19:19 -0700 Subject: [PATCH] Reorganize queue control registers Signed-off-by: Alex Forencich --- docs/source/rb/cqm_event.rst | 192 +++++++++- docs/source/rb/cqm_rx.rst | 192 +++++++++- docs/source/rb/cqm_tx.rst | 192 +++++++++- docs/source/rb/qm_rx.rst | 176 ++++++++- docs/source/rb/qm_tx.rst | 176 ++++++++- fpga/common/rtl/cpl_queue_manager.v | 235 ++++++------ fpga/common/rtl/mqnic_interface.v | 16 +- fpga/common/rtl/queue_manager.v | 163 +++++---- fpga/common/tb/cpl_queue_manager/Makefile | 2 +- .../test_cpl_queue_manager.py | 116 +++--- fpga/common/tb/mqnic.py | 342 ++++++++++-------- fpga/common/tb/queue_manager/Makefile | 2 +- .../tb/queue_manager/test_queue_manager.py | 108 +++--- modules/mqnic/mqnic.h | 37 +- modules/mqnic/mqnic_cq.c | 57 ++- modules/mqnic/mqnic_eq.c | 77 ++-- modules/mqnic/mqnic_hw.h | 82 +++-- modules/mqnic/mqnic_if.c | 16 +- modules/mqnic/mqnic_rx.c | 117 +++--- modules/mqnic/mqnic_tx.c | 112 +++--- utils/mqnic-dump.c | 140 ++++--- 21 files changed, 1734 insertions(+), 816 deletions(-) diff --git a/docs/source/rb/cqm_event.rst b/docs/source/rb/cqm_event.rst index db5a4827e..21cbc5cf4 100644 --- a/docs/source/rb/cqm_event.rst +++ b/docs/source/rb/cqm_event.rst @@ -4,7 +4,7 @@ Event queue manager register block ================================== -The event queue manager register block has a header with type 0x0000C010, version 0x00000200, and indicates the location of the event queue manager registers and number of event queues. +The event queue manager register block has a header with type 0x0000C010, version 0x00000300, and indicates the location of the event queue manager registers and number of event queues. .. table:: @@ -13,7 +13,7 @@ The event queue manager register block has a header with type 0x0000C010, versio ======== ============= ====== ====== ====== ====== ============= RBB+0x00 Type Vendor ID Type RO 0x0000C010 -------- ------------- -------------- -------------- ------------- - RBB+0x04 Version Major Minor Patch Meta RO 0x00000200 + RBB+0x04 Version Major Minor Patch Meta RO 0x00000300 -------- ------------- ------ ------ ------ ------ ------------- RBB+0x08 Next pointer Pointer to next register block RO - -------- ------------- ------------------------------ ------------- @@ -21,7 +21,7 @@ The event queue manager register block has a header with type 0x0000C010, versio -------- ------------- ------------------------------ ------------- RBB+0x10 Count Queue count RO - -------- ------------- ------------------------------ ------------- - RBB+0x14 Stride Queue control register stride RO 0x00000020 + RBB+0x14 Stride Queue control register stride RO 0x00000010 ======== ============= ============================== ============= See :ref:`rb_overview` for definitions of the standard register block header fields. @@ -59,7 +59,7 @@ See :ref:`rb_overview` for definitions of the standard register block header fie ======== ====== ====== ====== ====== ============= Address 31..24 23..16 15..8 7..0 Reset value ======== ====== ====== ====== ====== ============= - RBB+0x14 Queue control register stride RO 0x00000020 + RBB+0x14 Queue control register stride RO 0x00000010 ======== ============================== ============= Event queue manager CSRs @@ -72,15 +72,183 @@ Each queue has several associated control registers, detailed in this table: ========= ============== ====== ====== ====== ====== ============= Address Field 31..24 23..16 15..8 7..0 Reset value ========= ============== ====== ====== ====== ====== ============= - Base+0x00 Base address L Ring base address (lower 32) RW - + Base+0x00 Base addr L Ring base addr (lower), VF RW - --------- -------------- ------------------------------ ------------- - Base+0x04 Base address H Ring base address (upper 32) RW - + Base+0x04 Base addr H Ring base addr (upper) RW - --------- -------------- ------------------------------ ------------- - Base+0x08 Control 1 Active Size RW - - --------- -------------- ------ ------ ------ ------ ------------- - Base+0x0C Control 2 Arm Int index RW - - --------- -------------- ------ ------ -------------- ------------- - Base+0x10 Head pointer Head pointer RW - + Base+0x08 Control/status Control/status IRQN RO - --------- -------------- -------------- -------------- ------------- - Base+0x18 Tail pointer Tail pointer RW - + Base+0x0C Pointers Cons pointer Prod pointer RO - ========= ============== ============== ============== ============= + +.. object:: Base address + + The base address field contains the base address of the ring buffer as well as the VF ID. The base address must be aligned to a 4096 byte boundary and sits in bits 63:12, leaving room for the VF ID in bits 11:0. The base address is read-only when the queue is enabled. The VF ID field is read-only; use the set VF ID command to change the VF ID. + + .. table:: + + ========= ====== ====== ====== ====== ============= + Address 31..24 23..16 15..8 7..0 Reset value + ========= ====== ====== ====== ====== ============= + Base+0x00 Ring base addr (lower), VF RW - + --------- ------------------------------ ------------- + Base+0x04 Ring base addr (upper) RW - + ========= ============================== ============= + +.. object:: Control/status + + The control/status field contains control and status information for the queue, and the IRQN field contains the corresponding IRQ number. All fields are read-only; use commands to set the size and IRQN and to enable/disable and arm/disarm the queue. + + .. table:: + + ========= ====== ====== ====== ====== ============= + Address 31..24 23..16 15..8 7..0 Reset value + ========= ====== ====== ====== ====== ============= + Base+0x08 Control/status IRQN RO - + ========= ============== ============== ============= + + Control/status bit definitions + + .. table:: + + ===== ========= + Bit Function + ===== ========= + 0 Enable + 1 Arm + 3 Active + 15:12 Log size + ===== ========= + +.. object:: Pointers + + The pointers field contains the queue producer and consumer pointers. Bits 15:0 are the producer pointer, while bits 31:16 are the consumer pointer. Both fields are read-only; use the set prod and cons pointer commands to update the pointers. + + .. table:: + + ========= ====== ====== ====== ====== ============= + Address 31..24 23..16 15..8 7..0 Reset value + ========= ====== ====== ====== ====== ============= + Base+0x0C Cons pointer Prod pointer RO - + ========= ============== ============== ============= + +Event queue manager commands +============================ + +.. table:: + + ======================== ====== ====== ====== ====== + Command 31..24 23..16 15..8 7..0 + ======================== ====== ====== ====== ====== + Set VF ID 0x8001 VF ID + ------------------------ -------------- -------------- + Set size 0x8002 Log size + ------------------------ -------------- -------------- + Set IRQN 0xC0 IRQN + ------------------------ ------ ---------------------- + Set prod pointer 0x8080 Prod pointer + ------------------------ -------------- -------------- + Set cons pointer 0x8090 Cons pointer + ------------------------ -------------- -------------- + Set cons pointer, arm 0x8091 Cons pointer + ------------------------ -------------- -------------- + Set enable 0x400001 Enable + ------------------------ ---------------------- ------ + Set arm 0x400002 Arm + ======================== ====================== ====== + +.. object:: Set VF ID + + The set VF ID command is used to set the VF ID for the queue. Allowed when queue is disabled and inactive. + + .. table:: + + ====== ====== ====== ====== + 31..24 23..16 15..8 7..0 + ====== ====== ====== ====== + 0x8001 VF ID + ============== ============== + +.. object:: Set size + + The set size command is used to set the size of the ring buffer as the log base 2 of the number of elements. Allowed when queue is disabled and inactive. + + .. table:: + + ====== ====== ====== ====== + 31..24 23..16 15..8 7..0 + ====== ====== ====== ====== + 0x8002 Log size + ============== ============== + +.. object:: Set IRQN + + The set IRQN command is used to set the IRQ number for interrupts generated by the queue. Allowed when queue is disabled and inactive. + + .. table:: + + ====== ====== ====== ====== + 31..24 23..16 15..8 7..0 + ====== ====== ====== ====== + 0xC0 IRQN + ====== ====================== + +.. object:: Set prod pointer + + The set producer pointer command is used to set the queue producer pointer. Allowed when queue is disabled and inactive. + + .. table:: + + ====== ====== ====== ====== + 31..24 23..16 15..8 7..0 + ====== ====== ====== ====== + 0x8080 Prod pointer + ============== ============== + +.. object:: Set cons pointer + + The set consumer pointer command is used to set the queue consumer pointer. Allowed at any time. + + .. table:: + + ====== ====== ====== ====== + 31..24 23..16 15..8 7..0 + ====== ====== ====== ====== + 0x8090 Cons pointer + ============== ============== + +.. object:: Set cons pointer, arm + + The set consumer pointer, arm command is used to set the queue consumer pointer and simultaneously re-arm the queue. Allowed at any time. + + .. table:: + + ====== ====== ====== ====== + 31..24 23..16 15..8 7..0 + ====== ====== ====== ====== + 0x8091 Cons pointer + ============== ============== + +.. object:: Set enable + + The set enable command is used to enable or disable the queue. Allowed at any time. + + .. table:: + + ====== ====== ====== ====== + 31..24 23..16 15..8 7..0 + ====== ====== ====== ====== + 0x400001 Enable + ====================== ====== + +.. object:: Set arm + + The set arm command is used to arm or disarm the queue. Allowed at any time. + + .. table:: + + ====== ====== ====== ====== + 31..24 23..16 15..8 7..0 + ====== ====== ====== ====== + 0x400002 Arm + ====================== ====== diff --git a/docs/source/rb/cqm_rx.rst b/docs/source/rb/cqm_rx.rst index 8e63c6f95..5b3d3d441 100644 --- a/docs/source/rb/cqm_rx.rst +++ b/docs/source/rb/cqm_rx.rst @@ -4,7 +4,7 @@ Receive completion queue manager register block ================================================ -The receive completion queue manager register block has a header with type 0x0000C031, version 0x00000200, and indicates the location of the receive completion queue manager registers and number of completion queues. +The receive completion queue manager register block has a header with type 0x0000C031, version 0x00000300, and indicates the location of the receive completion queue manager registers and number of completion queues. .. table:: @@ -13,7 +13,7 @@ The receive completion queue manager register block has a header with type 0x000 ======== ============= ====== ====== ====== ====== ============= RBB+0x00 Type Vendor ID Type RO 0x0000C031 -------- ------------- -------------- -------------- ------------- - RBB+0x04 Version Major Minor Patch Meta RO 0x00000200 + RBB+0x04 Version Major Minor Patch Meta RO 0x00000300 -------- ------------- ------ ------ ------ ------ ------------- RBB+0x08 Next pointer Pointer to next register block RO - -------- ------------- ------------------------------ ------------- @@ -21,7 +21,7 @@ The receive completion queue manager register block has a header with type 0x000 -------- ------------- ------------------------------ ------------- RBB+0x10 Count Queue count RO - -------- ------------- ------------------------------ ------------- - RBB+0x14 Stride Queue control register stride RO 0x00000020 + RBB+0x14 Stride Queue control register stride RO 0x00000010 ======== ============= ============================== ============= See :ref:`rb_overview` for definitions of the standard register block header fields. @@ -59,7 +59,7 @@ See :ref:`rb_overview` for definitions of the standard register block header fie ======== ====== ====== ====== ====== ============= Address 31..24 23..16 15..8 7..0 Reset value ======== ====== ====== ====== ====== ============= - RBB+0x14 Queue control register stride RO 0x00000020 + RBB+0x14 Queue control register stride RO 0x00000010 ======== ============================== ============= Completion queue manager CSRs @@ -72,15 +72,183 @@ Each queue has several associated control registers, detailed in this table: ========= ============== ====== ====== ====== ====== ============= Address Field 31..24 23..16 15..8 7..0 Reset value ========= ============== ====== ====== ====== ====== ============= - Base+0x00 Base address L Ring base address (lower 32) RW - + Base+0x00 Base addr L Ring base addr (lower), VF RW - --------- -------------- ------------------------------ ------------- - Base+0x04 Base address H Ring base address (upper 32) RW - + Base+0x04 Base addr H Ring base addr (upper) RW - --------- -------------- ------------------------------ ------------- - Base+0x08 Control 1 Active Size RW - - --------- -------------- ------ ------ ------ ------ ------------- - Base+0x0C Control 2 Arm Event index RW - - --------- -------------- ------ ------ -------------- ------------- - Base+0x10 Head pointer Head pointer RW - + Base+0x08 Control/status Control/status EQN RO - --------- -------------- -------------- -------------- ------------- - Base+0x18 Tail pointer Tail pointer RW - + Base+0x0C Pointers Cons pointer Prod pointer RO - ========= ============== ============== ============== ============= + +.. object:: Base address + + The base address field contains the base address of the ring buffer as well as the VF ID. The base address must be aligned to a 4096 byte boundary and sits in bits 63:12, leaving room for the VF ID in bits 11:0. The base address is read-only when the queue is enabled. The VF ID field is read-only; use the set VF ID command to change the VF ID. + + .. table:: + + ========= ====== ====== ====== ====== ============= + Address 31..24 23..16 15..8 7..0 Reset value + ========= ====== ====== ====== ====== ============= + Base+0x00 Ring base addr (lower), VF RW - + --------- ------------------------------ ------------- + Base+0x04 Ring base addr (upper) RW - + ========= ============================== ============= + +.. object:: Control/status + + The control/status field contains control and status information for the queue, and the EQN field contains the corresponding event queue number. All fields are read-only; use commands to set the size and EQN and to enable/disable and arm/disarm the queue. + + .. table:: + + ========= ====== ====== ====== ====== ============= + Address 31..24 23..16 15..8 7..0 Reset value + ========= ====== ====== ====== ====== ============= + Base+0x08 Control/status EQN RO - + ========= ============== ============== ============= + + Control/status bit definitions + + .. table:: + + ===== ========= + Bit Function + ===== ========= + 0 Enable + 1 Arm + 3 Active + 15:12 Log size + ===== ========= + +.. object:: Pointers + + The pointers field contains the queue producer and consumer pointers. Bits 15:0 are the producer pointer, while bits 31:16 are the consumer pointer. Both fields are read-only; use the set prod and cons pointer commands to update the pointers. + + .. table:: + + ========= ====== ====== ====== ====== ============= + Address 31..24 23..16 15..8 7..0 Reset value + ========= ====== ====== ====== ====== ============= + Base+0x0C Cons pointer Prod pointer RO - + ========= ============== ============== ============= + +Completion queue manager commands +================================= + +.. table:: + + ======================== ====== ====== ====== ====== + Command 31..24 23..16 15..8 7..0 + ======================== ====== ====== ====== ====== + Set VF ID 0x8001 VF ID + ------------------------ -------------- -------------- + Set size 0x8002 Log size + ------------------------ -------------- -------------- + Set EQN 0xC0 EQN + ------------------------ ------ ---------------------- + Set prod pointer 0x8080 Prod pointer + ------------------------ -------------- -------------- + Set cons pointer 0x8090 Cons pointer + ------------------------ -------------- -------------- + Set cons pointer, arm 0x8091 Cons pointer + ------------------------ -------------- -------------- + Set enable 0x400001 Enable + ------------------------ ---------------------- ------ + Set arm 0x400002 Arm + ======================== ====================== ====== + +.. object:: Set VF ID + + The set VF ID command is used to set the VF ID for the queue. Allowed when queue is disabled and inactive. + + .. table:: + + ====== ====== ====== ====== + 31..24 23..16 15..8 7..0 + ====== ====== ====== ====== + 0x8001 VF ID + ============== ============== + +.. object:: Set size + + The set size command is used to set the size of the ring buffer as the log base 2 of the number of elements. Allowed when queue is disabled and inactive. + + .. table:: + + ====== ====== ====== ====== + 31..24 23..16 15..8 7..0 + ====== ====== ====== ====== + 0x8002 Log size + ============== ============== + +.. object:: Set EQN + + The set EQN command is used to set the EQN for events generated by the queue. Allowed when queue is disabled and inactive. + + .. table:: + + ====== ====== ====== ====== + 31..24 23..16 15..8 7..0 + ====== ====== ====== ====== + 0xC0 EQN + ====== ====================== + +.. object:: Set prod pointer + + The set producer pointer command is used to set the queue producer pointer. Allowed when queue is disabled and inactive. + + .. table:: + + ====== ====== ====== ====== + 31..24 23..16 15..8 7..0 + ====== ====== ====== ====== + 0x8080 Prod pointer + ============== ============== + +.. object:: Set cons pointer + + The set consumer pointer command is used to set the queue consumer pointer. Allowed at any time. + + .. table:: + + ====== ====== ====== ====== + 31..24 23..16 15..8 7..0 + ====== ====== ====== ====== + 0x8090 Cons pointer + ============== ============== + +.. object:: Set cons pointer, arm + + The set consumer pointer, arm command is used to set the queue consumer pointer and simultaneously re-arm the queue. Allowed at any time. + + .. table:: + + ====== ====== ====== ====== + 31..24 23..16 15..8 7..0 + ====== ====== ====== ====== + 0x8091 Cons pointer + ============== ============== + +.. object:: Set enable + + The set enable command is used to enable or disable the queue. Allowed at any time. + + .. table:: + + ====== ====== ====== ====== + 31..24 23..16 15..8 7..0 + ====== ====== ====== ====== + 0x400001 Enable + ====================== ====== + +.. object:: Set arm + + The set arm command is used to arm or disarm the queue. Allowed at any time. + + .. table:: + + ====== ====== ====== ====== + 31..24 23..16 15..8 7..0 + ====== ====== ====== ====== + 0x400002 Arm + ====================== ====== diff --git a/docs/source/rb/cqm_tx.rst b/docs/source/rb/cqm_tx.rst index 32c0bc752..5c516bfb0 100644 --- a/docs/source/rb/cqm_tx.rst +++ b/docs/source/rb/cqm_tx.rst @@ -4,7 +4,7 @@ Transmit completion queue manager register block ================================================ -The transmit completion queue manager register block has a header with type 0x0000C030, version 0x00000200, and indicates the location of the transmit completion queue manager registers and number of completion queues. +The transmit completion queue manager register block has a header with type 0x0000C030, version 0x00000300, and indicates the location of the transmit completion queue manager registers and number of completion queues. .. table:: @@ -13,7 +13,7 @@ The transmit completion queue manager register block has a header with type 0x00 ======== ============= ====== ====== ====== ====== ============= RBB+0x00 Type Vendor ID Type RO 0x0000C030 -------- ------------- -------------- -------------- ------------- - RBB+0x04 Version Major Minor Patch Meta RO 0x00000200 + RBB+0x04 Version Major Minor Patch Meta RO 0x00000300 -------- ------------- ------ ------ ------ ------ ------------- RBB+0x08 Next pointer Pointer to next register block RO - -------- ------------- ------------------------------ ------------- @@ -21,7 +21,7 @@ The transmit completion queue manager register block has a header with type 0x00 -------- ------------- ------------------------------ ------------- RBB+0x10 Count Queue count RO - -------- ------------- ------------------------------ ------------- - RBB+0x14 Stride Queue control register stride RO 0x00000020 + RBB+0x14 Stride Queue control register stride RO 0x00000010 ======== ============= ============================== ============= See :ref:`rb_overview` for definitions of the standard register block header fields. @@ -59,7 +59,7 @@ See :ref:`rb_overview` for definitions of the standard register block header fie ======== ====== ====== ====== ====== ============= Address 31..24 23..16 15..8 7..0 Reset value ======== ====== ====== ====== ====== ============= - RBB+0x14 Queue control register stride RO 0x00000020 + RBB+0x14 Queue control register stride RO 0x00000010 ======== ============================== ============= Completion queue manager CSRs @@ -72,15 +72,183 @@ Each queue has several associated control registers, detailed in this table: ========= ============== ====== ====== ====== ====== ============= Address Field 31..24 23..16 15..8 7..0 Reset value ========= ============== ====== ====== ====== ====== ============= - Base+0x00 Base address L Ring base address (lower 32) RW - + Base+0x00 Base addr L Ring base addr (lower), VF RW - --------- -------------- ------------------------------ ------------- - Base+0x04 Base address H Ring base address (upper 32) RW - + Base+0x04 Base addr H Ring base addr (upper) RW - --------- -------------- ------------------------------ ------------- - Base+0x08 Control 1 Active Size RW - - --------- -------------- ------ ------ ------ ------ ------------- - Base+0x0C Control 2 Arm Event index RW - - --------- -------------- ------ ------ -------------- ------------- - Base+0x10 Head pointer Head pointer RW - + Base+0x08 Control/status Control/status EQN RO - --------- -------------- -------------- -------------- ------------- - Base+0x18 Tail pointer Tail pointer RW - + Base+0x0C Pointers Cons pointer Prod pointer RO - ========= ============== ============== ============== ============= + +.. object:: Base address + + The base address field contains the base address of the ring buffer as well as the VF ID. The base address must be aligned to a 4096 byte boundary and sits in bits 63:12, leaving room for the VF ID in bits 11:0. The base address is read-only when the queue is enabled. The VF ID field is read-only; use the set VF ID command to change the VF ID. + + .. table:: + + ========= ====== ====== ====== ====== ============= + Address 31..24 23..16 15..8 7..0 Reset value + ========= ====== ====== ====== ====== ============= + Base+0x00 Ring base addr (lower), VF RW - + --------- ------------------------------ ------------- + Base+0x04 Ring base addr (upper) RW - + ========= ============================== ============= + +.. object:: Control/status + + The control/status field contains control and status information for the queue, and the EQN field contains the corresponding event queue number. All fields are read-only; use commands to set the size and EQN and to enable/disable and arm/disarm the queue. + + .. table:: + + ========= ====== ====== ====== ====== ============= + Address 31..24 23..16 15..8 7..0 Reset value + ========= ====== ====== ====== ====== ============= + Base+0x08 Control/status EQN RO - + ========= ============== ============== ============= + + Control/status bit definitions + + .. table:: + + ===== ========= + Bit Function + ===== ========= + 0 Enable + 1 Arm + 3 Active + 15:12 Log size + ===== ========= + +.. object:: Pointers + + The pointers field contains the queue producer and consumer pointers. Bits 15:0 are the producer pointer, while bits 31:16 are the consumer pointer. Both fields are read-only; use the set prod and cons pointer commands to update the pointers. + + .. table:: + + ========= ====== ====== ====== ====== ============= + Address 31..24 23..16 15..8 7..0 Reset value + ========= ====== ====== ====== ====== ============= + Base+0x0C Cons pointer Prod pointer RO - + ========= ============== ============== ============= + +Completion queue manager commands +================================= + +.. table:: + + ======================== ====== ====== ====== ====== + Command 31..24 23..16 15..8 7..0 + ======================== ====== ====== ====== ====== + Set VF ID 0x8001 VF ID + ------------------------ -------------- -------------- + Set size 0x8002 Log size + ------------------------ -------------- -------------- + Set EQN 0xC0 EQN + ------------------------ ------ ---------------------- + Set prod pointer 0x8080 Prod pointer + ------------------------ -------------- -------------- + Set cons pointer 0x8090 Cons pointer + ------------------------ -------------- -------------- + Set cons pointer, arm 0x8091 Cons pointer + ------------------------ -------------- -------------- + Set enable 0x400001 Enable + ------------------------ ---------------------- ------ + Set arm 0x400002 Arm + ======================== ====================== ====== + +.. object:: Set VF ID + + The set VF ID command is used to set the VF ID for the queue. Allowed when queue is disabled and inactive. + + .. table:: + + ====== ====== ====== ====== + 31..24 23..16 15..8 7..0 + ====== ====== ====== ====== + 0x8001 VF ID + ============== ============== + +.. object:: Set size + + The set size command is used to set the size of the ring buffer as the log base 2 of the number of elements. Allowed when queue is disabled and inactive. + + .. table:: + + ====== ====== ====== ====== + 31..24 23..16 15..8 7..0 + ====== ====== ====== ====== + 0x8002 Log size + ============== ============== + +.. object:: Set EQN + + The set EQN command is used to set the EQN for events generated by the queue. Allowed when queue is disabled and inactive. + + .. table:: + + ====== ====== ====== ====== + 31..24 23..16 15..8 7..0 + ====== ====== ====== ====== + 0xC0 EQN + ====== ====================== + +.. object:: Set prod pointer + + The set producer pointer command is used to set the queue producer pointer. Allowed when queue is disabled and inactive. + + .. table:: + + ====== ====== ====== ====== + 31..24 23..16 15..8 7..0 + ====== ====== ====== ====== + 0x8080 Prod pointer + ============== ============== + +.. object:: Set cons pointer + + The set consumer pointer command is used to set the queue consumer pointer. Allowed at any time. + + .. table:: + + ====== ====== ====== ====== + 31..24 23..16 15..8 7..0 + ====== ====== ====== ====== + 0x8090 Cons pointer + ============== ============== + +.. object:: Set cons pointer, arm + + The set consumer pointer, arm command is used to set the queue consumer pointer and simultaneously re-arm the queue. Allowed at any time. + + .. table:: + + ====== ====== ====== ====== + 31..24 23..16 15..8 7..0 + ====== ====== ====== ====== + 0x8091 Cons pointer + ============== ============== + +.. object:: Set enable + + The set enable command is used to enable or disable the queue. Allowed at any time. + + .. table:: + + ====== ====== ====== ====== + 31..24 23..16 15..8 7..0 + ====== ====== ====== ====== + 0x400001 Enable + ====================== ====== + +.. object:: Set arm + + The set arm command is used to arm or disarm the queue. Allowed at any time. + + .. table:: + + ====== ====== ====== ====== + 31..24 23..16 15..8 7..0 + ====== ====== ====== ====== + 0x400002 Arm + ====================== ====== diff --git a/docs/source/rb/qm_rx.rst b/docs/source/rb/qm_rx.rst index db2153b66..eac3f67af 100644 --- a/docs/source/rb/qm_rx.rst +++ b/docs/source/rb/qm_rx.rst @@ -4,7 +4,7 @@ Receive queue manager register block ===================================== -The receive queue manager register block has a header with type 0x0000C021, version 0x00000200, and indicates the location of the receive queue manager registers and number of queues. +The receive queue manager register block has a header with type 0x0000C021, version 0x00000300, and indicates the location of the receive queue manager registers and number of queues. .. table:: @@ -13,7 +13,7 @@ The receive queue manager register block has a header with type 0x0000C021, vers ======== ============= ====== ====== ====== ====== ============= RBB+0x00 Type Vendor ID Type RO 0x0000C021 -------- ------------- -------------- -------------- ------------- - RBB+0x04 Version Major Minor Patch Meta RO 0x00000200 + RBB+0x04 Version Major Minor Patch Meta RO 0x00000300 -------- ------------- ------ ------ ------ ------ ------------- RBB+0x08 Next pointer Pointer to next register block RO - -------- ------------- ------------------------------ ------------- @@ -72,15 +72,169 @@ Each queue has several associated control registers, detailed in this table: ========= ============== ====== ====== ====== ====== ============= Address Field 31..24 23..16 15..8 7..0 Reset value ========= ============== ====== ====== ====== ====== ============= - Base+0x00 Base address L Ring base address (lower 32) RW - + Base+0x00 Base addr L Ring base addr (lower), VF RW - --------- -------------- ------------------------------ ------------- - Base+0x04 Base address H Ring base address (upper 32) RW - + Base+0x04 Base addr H Ring base addr (upper) RW - --------- -------------- ------------------------------ ------------- - Base+0x08 Control 1 Active Size RW - - --------- -------------- ------ ------ ------ ------ ------------- - Base+0x0C Control 2 CQ index RW - - --------- -------------- -------------- -------------- ------------- - Base+0x10 Head pointer Head pointer RW - - --------- -------------- -------------- -------------- ------------- - Base+0x18 Tail pointer Tail pointer RW - + Base+0x08 Control/status Control/status RO - + --------- -------------- ------------------------------ ------------- + Base+0x0C Config Size CQN RO - + --------- -------------- ------ ---------------------- ------------- + Base+0x10 Pointers Cons pointer Prod pointer RO - ========= ============== ============== ============== ============= + +.. object:: Base address + + The base address field contains the base address of the ring buffer as well as the VF ID. The base address must be aligned to a 4096 byte boundary and sits in bits 63:12, leaving room for the VF ID in bits 11:0. The base address is read-only when the queue is enabled. The VF ID field is read-only; use the set VF ID command to change the VF ID. + + .. table:: + + ========= ====== ====== ====== ====== ============= + Address 31..24 23..16 15..8 7..0 Reset value + ========= ====== ====== ====== ====== ============= + Base+0x00 Ring base addr (lower), VF RW - + --------- ------------------------------ ------------- + Base+0x04 Ring base addr (upper) RW - + ========= ============================== ============= + +.. object:: Control/status + + The control/status field contains control and status information for the queue. All fields are read-only; use commands to enable/disable the queue. + + .. table:: + + ========= ====== ====== ====== ====== ============= + Address 31..24 23..16 15..8 7..0 Reset value + ========= ====== ====== ====== ====== ============= + Base+0x08 Control/status RO - + ========= ============================== ============= + + Control/status bit definitions + + .. table:: + + ===== ========= + Bit Function + ===== ========= + 0 Enable + 3 Active + ===== ========= + +.. object:: Config + + The size field contains the size of the queue, and the CQN field contains the corresponding completion queue number. All fields are read-only; use commands to set the size and CQN. + + .. table:: + + ========= ====== ====== ====== ====== ============= + Address 31..24 23..16 15..8 7..0 Reset value + ========= ====== ====== ====== ====== ============= + Base+0x0C Size CQN RO - + ========= ====== ====================== ============= + +.. object:: Pointers + + The pointers field contains the queue producer and consumer pointers. Bits 15:0 are the producer pointer, while bits 31:16 are the consumer pointer. Both fields are read-only; use the set prod and cons pointer commands to update the pointers. + + .. table:: + + ========= ====== ====== ====== ====== ============= + Address 31..24 23..16 15..8 7..0 Reset value + ========= ====== ====== ====== ====== ============= + Base+0x10 Cons pointer Prod pointer RO - + ========= ============== ============== ============= + +Queue manager commands +====================== + +Commands are used to control various aspects of queue state in an atomic manner. Commands can be written to any of the read-only registers associated with the queue (control/status, config, and pointers). + +.. table:: + + ======================== ====== ====== ====== ====== + Command 31..24 23..16 15..8 7..0 + ======================== ====== ====== ====== ====== + Set VF ID 0x8001 VF ID + ------------------------ -------------- -------------- + Set size 0x8002 size + ------------------------ -------------- -------------- + Set CQN 0xC0 CQN + ------------------------ ------ ---------------------- + Set prod pointer 0x8080 Prod pointer + ------------------------ -------------- -------------- + Set cons pointer 0x8090 Cons pointer + ------------------------ -------------- -------------- + Set enable 0x400001 Enable + ======================== ====================== ====== + +.. object:: Set VF ID + + The set VF ID command is used to set the VF ID for the queue. Allowed when queue is disabled and inactive. + + .. table:: + + ====== ====== ====== ====== + 31..24 23..16 15..8 7..0 + ====== ====== ====== ====== + 0x8001 VF ID + ============== ============== + +.. object:: Set size + + The set size command is used to set the size of the ring buffer as the log base 2 of the number of elements. Allowed when queue is disabled and inactive. + + .. table:: + + ====== ====== ====== ====== + 31..24 23..16 15..8 7..0 + ====== ====== ====== ====== + 0x8002 Log size + ============== ============== + +.. object:: Set CQN + + The set CQN command is used to set the CQN for completions generated by the queue. Allowed when queue is disabled and inactive. + + .. table:: + + ====== ====== ====== ====== + 31..24 23..16 15..8 7..0 + ====== ====== ====== ====== + 0xC0 CQN + ====== ====================== + +.. object:: Set prod pointer + + The set producer pointer command is used to set the queue producer pointer. Allowed at any time. + + .. table:: + + ====== ====== ====== ====== + 31..24 23..16 15..8 7..0 + ====== ====== ====== ====== + 0x8080 Prod pointer + ============== ============== + +.. object:: Set cons pointer + + The set consumer pointer command is used to set the queue consumer pointer. Allowed when queue is disabled and inactive. + + .. table:: + + ====== ====== ====== ====== + 31..24 23..16 15..8 7..0 + ====== ====== ====== ====== + 0x8090 Cons pointer + ============== ============== + +.. object:: Set enable + + The set enable command is used to enable or disable the queue. Allowed at any time. + + .. table:: + + ====== ====== ====== ====== + 31..24 23..16 15..8 7..0 + ====== ====== ====== ====== + 0x400001 Enable + ====================== ====== diff --git a/docs/source/rb/qm_tx.rst b/docs/source/rb/qm_tx.rst index 08c8b964e..338c60a55 100644 --- a/docs/source/rb/qm_tx.rst +++ b/docs/source/rb/qm_tx.rst @@ -4,7 +4,7 @@ Transmit queue manager register block ===================================== -The transmit queue manager register block has a header with type 0x0000C020, version 0x00000200, and indicates the location of the transmit queue manager registers and number of queues. +The transmit queue manager register block has a header with type 0x0000C020, version 0x00000300, and indicates the location of the transmit queue manager registers and number of queues. .. table:: @@ -13,7 +13,7 @@ The transmit queue manager register block has a header with type 0x0000C020, ver ======== ============= ====== ====== ====== ====== ============= RBB+0x00 Type Vendor ID Type RO 0x0000C020 -------- ------------- -------------- -------------- ------------- - RBB+0x04 Version Major Minor Patch Meta RO 0x00000200 + RBB+0x04 Version Major Minor Patch Meta RO 0x00000300 -------- ------------- ------ ------ ------ ------ ------------- RBB+0x08 Next pointer Pointer to next register block RO - -------- ------------- ------------------------------ ------------- @@ -72,15 +72,169 @@ Each queue has several associated control registers, detailed in this table: ========= ============== ====== ====== ====== ====== ============= Address Field 31..24 23..16 15..8 7..0 Reset value ========= ============== ====== ====== ====== ====== ============= - Base+0x00 Base address L Ring base address (lower 32) RW - + Base+0x00 Base addr L Ring base addr (lower), VF RW - --------- -------------- ------------------------------ ------------- - Base+0x04 Base address H Ring base address (upper 32) RW - + Base+0x04 Base addr H Ring base addr (upper) RW - --------- -------------- ------------------------------ ------------- - Base+0x08 Control 1 Active Size RW - - --------- -------------- ------ ------ ------ ------ ------------- - Base+0x0C Control 2 CQ index RW - - --------- -------------- -------------- -------------- ------------- - Base+0x10 Head pointer Head pointer RW - - --------- -------------- -------------- -------------- ------------- - Base+0x18 Tail pointer Tail pointer RW - + Base+0x08 Control/status Control/status RO - + --------- -------------- ------------------------------ ------------- + Base+0x0C Config Size CQN RO - + --------- -------------- ------ ---------------------- ------------- + Base+0x10 Pointers Cons pointer Prod pointer RO - ========= ============== ============== ============== ============= + +.. object:: Base address + + The base address field contains the base address of the ring buffer as well as the VF ID. The base address must be aligned to a 4096 byte boundary and sits in bits 63:12, leaving room for the VF ID in bits 11:0. The base address is read-only when the queue is enabled. The VF ID field is read-only; use the set VF ID command to change the VF ID. + + .. table:: + + ========= ====== ====== ====== ====== ============= + Address 31..24 23..16 15..8 7..0 Reset value + ========= ====== ====== ====== ====== ============= + Base+0x00 Ring base addr (lower), VF RW - + --------- ------------------------------ ------------- + Base+0x04 Ring base addr (upper) RW - + ========= ============================== ============= + +.. object:: Control/status + + The control/status field contains control and status information for the queue. All fields are read-only; use commands to enable/disable the queue. + + .. table:: + + ========= ====== ====== ====== ====== ============= + Address 31..24 23..16 15..8 7..0 Reset value + ========= ====== ====== ====== ====== ============= + Base+0x08 Control/status RO - + ========= ============================== ============= + + Control/status bit definitions + + .. table:: + + ===== ========= + Bit Function + ===== ========= + 0 Enable + 3 Active + ===== ========= + +.. object:: Config + + The size field contains the size of the queue, and the CQN field contains the corresponding completion queue number. All fields are read-only; use commands to set the size and CQN. + + .. table:: + + ========= ====== ====== ====== ====== ============= + Address 31..24 23..16 15..8 7..0 Reset value + ========= ====== ====== ====== ====== ============= + Base+0x0C Size CQN RO - + ========= ====== ====================== ============= + +.. object:: Pointers + + The pointers field contains the queue producer and consumer pointers. Bits 15:0 are the producer pointer, while bits 31:16 are the consumer pointer. Both fields are read-only; use the set prod and cons pointer commands to update the pointers. + + .. table:: + + ========= ====== ====== ====== ====== ============= + Address 31..24 23..16 15..8 7..0 Reset value + ========= ====== ====== ====== ====== ============= + Base+0x10 Cons pointer Prod pointer RO - + ========= ============== ============== ============= + +Queue manager commands +====================== + +Commands are used to control various aspects of queue state in an atomic manner. Commands can be written to any of the read-only registers associated with the queue (control/status, config, and pointers). + +.. table:: + + ======================== ====== ====== ====== ====== + Command 31..24 23..16 15..8 7..0 + ======================== ====== ====== ====== ====== + Set VF ID 0x8001 VF ID + ------------------------ -------------- -------------- + Set size 0x8002 size + ------------------------ -------------- -------------- + Set CQN 0xC0 CQN + ------------------------ ------ ---------------------- + Set prod pointer 0x8080 Prod pointer + ------------------------ -------------- -------------- + Set cons pointer 0x8090 Cons pointer + ------------------------ -------------- -------------- + Set enable 0x400001 Enable + ======================== ====================== ====== + +.. object:: Set VF ID + + The set VF ID command is used to set the VF ID for the queue. Allowed when queue is disabled and inactive. + + .. table:: + + ====== ====== ====== ====== + 31..24 23..16 15..8 7..0 + ====== ====== ====== ====== + 0x8001 VF ID + ============== ============== + +.. object:: Set size + + The set size command is used to set the size of the ring buffer as the log base 2 of the number of elements. Allowed when queue is disabled and inactive. + + .. table:: + + ====== ====== ====== ====== + 31..24 23..16 15..8 7..0 + ====== ====== ====== ====== + 0x8002 Log size + ============== ============== + +.. object:: Set CQN + + The set CQN command is used to set the CQN for completions generated by the queue. Allowed when queue is disabled and inactive. + + .. table:: + + ====== ====== ====== ====== + 31..24 23..16 15..8 7..0 + ====== ====== ====== ====== + 0xC0 CQN + ====== ====================== + +.. object:: Set prod pointer + + The set producer pointer command is used to set the queue producer pointer. Allowed at any time. + + .. table:: + + ====== ====== ====== ====== + 31..24 23..16 15..8 7..0 + ====== ====== ====== ====== + 0x8080 Prod pointer + ============== ============== + +.. object:: Set cons pointer + + The set consumer pointer command is used to set the queue consumer pointer. Allowed when queue is disabled and inactive. + + .. table:: + + ====== ====== ====== ====== + 31..24 23..16 15..8 7..0 + ====== ====== ====== ====== + 0x8090 Cons pointer + ============== ============== + +.. object:: Set enable + + The set enable command is used to enable or disable the queue. Allowed at any time. + + .. table:: + + ====== ====== ====== ====== + 31..24 23..16 15..8 7..0 + ====== ====== ====== ====== + 0x400001 Enable + ====================== ====== diff --git a/fpga/common/rtl/cpl_queue_manager.v b/fpga/common/rtl/cpl_queue_manager.v index 6d73086ee..4d33e1dbe 100644 --- a/fpga/common/rtl/cpl_queue_manager.v +++ b/fpga/common/rtl/cpl_queue_manager.v @@ -37,7 +37,7 @@ module cpl_queue_manager # // Width of AXI lite data bus in bits parameter AXIL_DATA_WIDTH = 32, // Width of AXI lite address bus in bits - parameter AXIL_ADDR_WIDTH = 16, + parameter AXIL_ADDR_WIDTH = QUEUE_INDEX_WIDTH+4, // Width of AXI lite wstrb (width of data bus in words) parameter AXIL_STRB_WIDTH = (AXIL_DATA_WIDTH/8) ) @@ -138,7 +138,7 @@ initial begin $finish; end - if (AXIL_ADDR_WIDTH < QUEUE_INDEX_WIDTH+5) begin + if (AXIL_ADDR_WIDTH < QUEUE_INDEX_WIDTH+4) begin $error("Error: AXI lite address width too narrow (instance %m)"); $finish; end @@ -166,7 +166,7 @@ reg [PIPELINE-1:0] op_req_pipe_reg = {PIPELINE{1'b0}}, op_req_pipe_next; reg [PIPELINE-1:0] op_commit_pipe_reg = {PIPELINE{1'b0}}, op_commit_pipe_next; reg [QUEUE_INDEX_WIDTH-1:0] queue_ram_addr_pipeline_reg[PIPELINE-1:0], queue_ram_addr_pipeline_next[PIPELINE-1:0]; -reg [2:0] axil_reg_pipeline_reg[PIPELINE-1:0], axil_reg_pipeline_next[PIPELINE-1:0]; +reg [1:0] axil_reg_pipeline_reg[PIPELINE-1:0], axil_reg_pipeline_next[PIPELINE-1:0]; reg [AXIL_DATA_WIDTH-1:0] write_data_pipeline_reg[PIPELINE-1:0], write_data_pipeline_next[PIPELINE-1:0]; reg [AXIL_STRB_WIDTH-1:0] write_strobe_pipeline_reg[PIPELINE-1:0], write_strobe_pipeline_next[PIPELINE-1:0]; reg [REQ_TAG_WIDTH-1:0] req_tag_pipeline_reg[PIPELINE-1:0], req_tag_pipeline_next[PIPELINE-1:0]; @@ -207,15 +207,15 @@ reg [QUEUE_RAM_BE_WIDTH-1:0] queue_ram_be; reg [QUEUE_RAM_WIDTH-1:0] queue_ram_read_data_reg = 0; reg [QUEUE_RAM_WIDTH-1:0] queue_ram_read_data_pipeline_reg[PIPELINE-1:1]; -wire [QUEUE_PTR_WIDTH-1:0] queue_ram_read_data_head_ptr = queue_ram_read_data_pipeline_reg[PIPELINE-1][15:0]; -wire [QUEUE_PTR_WIDTH-1:0] queue_ram_read_data_tail_ptr = queue_ram_read_data_pipeline_reg[PIPELINE-1][31:16]; +wire [QUEUE_PTR_WIDTH-1:0] queue_ram_read_data_prod_ptr = queue_ram_read_data_pipeline_reg[PIPELINE-1][15:0]; +wire [QUEUE_PTR_WIDTH-1:0] queue_ram_read_data_cons_ptr = queue_ram_read_data_pipeline_reg[PIPELINE-1][31:16]; wire [EVENT_WIDTH-1:0] queue_ram_read_data_event = queue_ram_read_data_pipeline_reg[PIPELINE-1][47:32]; wire [LOG_QUEUE_SIZE_WIDTH-1:0] queue_ram_read_data_log_size = queue_ram_read_data_pipeline_reg[PIPELINE-1][51:48]; wire queue_ram_read_data_continuous = queue_ram_read_data_pipeline_reg[PIPELINE-1][53]; wire queue_ram_read_data_armed = queue_ram_read_data_pipeline_reg[PIPELINE-1][54]; -wire queue_ram_read_data_active = queue_ram_read_data_pipeline_reg[PIPELINE-1][55]; +wire queue_ram_read_data_enable = queue_ram_read_data_pipeline_reg[PIPELINE-1][55]; wire [CL_OP_TABLE_SIZE-1:0] queue_ram_read_data_op_index = queue_ram_read_data_pipeline_reg[PIPELINE-1][63:56]; -wire [ADDR_WIDTH-1:0] queue_ram_read_data_base_addr = queue_ram_read_data_pipeline_reg[PIPELINE-1][127:64]; +wire [ADDR_WIDTH-1:0] queue_ram_read_data_base_addr = {queue_ram_read_data_pipeline_reg[PIPELINE-1][127:76], 12'd0}; reg [OP_TABLE_SIZE-1:0] op_table_active = 0; reg [OP_TABLE_SIZE-1:0] op_table_commit = 0; @@ -260,16 +260,16 @@ assign s_axil_rdata = s_axil_rdata_reg; assign s_axil_rresp = 2'b00; assign s_axil_rvalid = s_axil_rvalid_reg; -wire [QUEUE_INDEX_WIDTH-1:0] s_axil_awaddr_queue = s_axil_awaddr >> 5; -wire [2:0] s_axil_awaddr_reg = s_axil_awaddr >> 2; -wire [QUEUE_INDEX_WIDTH-1:0] s_axil_araddr_queue = s_axil_araddr >> 5; -wire [2:0] s_axil_araddr_reg = s_axil_araddr >> 2; +wire [QUEUE_INDEX_WIDTH-1:0] s_axil_awaddr_queue = s_axil_awaddr >> 4; +wire [1:0] s_axil_awaddr_reg = s_axil_awaddr >> 2; +wire [QUEUE_INDEX_WIDTH-1:0] s_axil_araddr_queue = s_axil_araddr >> 4; +wire [1:0] s_axil_araddr_reg = s_axil_araddr >> 2; wire queue_active = op_table_active[queue_ram_read_data_op_index] && op_table_queue[queue_ram_read_data_op_index] == queue_ram_addr_pipeline_reg[PIPELINE-1]; -wire queue_full_idle = ($unsigned(queue_ram_read_data_head_ptr - queue_ram_read_data_tail_ptr) & ({QUEUE_PTR_WIDTH{1'b1}} << queue_ram_read_data_log_size)) != 0; -wire queue_full_active = ($unsigned(op_table_queue_ptr[queue_ram_read_data_op_index] - queue_ram_read_data_tail_ptr) & ({QUEUE_PTR_WIDTH{1'b1}} << queue_ram_read_data_log_size)) != 0; +wire queue_full_idle = ($unsigned(queue_ram_read_data_prod_ptr - queue_ram_read_data_cons_ptr) & ({QUEUE_PTR_WIDTH{1'b1}} << queue_ram_read_data_log_size)) != 0; +wire queue_full_active = ($unsigned(op_table_queue_ptr[queue_ram_read_data_op_index] - queue_ram_read_data_cons_ptr) & ({QUEUE_PTR_WIDTH{1'b1}} << queue_ram_read_data_log_size)) != 0; wire queue_full = queue_active ? queue_full_active : queue_full_idle; -wire [QUEUE_PTR_WIDTH-1:0] queue_ram_read_active_head_ptr = queue_active ? op_table_queue_ptr[queue_ram_read_data_op_index] : queue_ram_read_data_head_ptr; +wire [QUEUE_PTR_WIDTH-1:0] queue_ram_read_active_prod_ptr = queue_active ? op_table_queue_ptr[queue_ram_read_data_op_index] : queue_ram_read_data_prod_ptr; integer i, j; @@ -348,7 +348,7 @@ always @* begin queue_ram_be = 0; op_table_start_queue = queue_ram_addr_pipeline_reg[PIPELINE-1]; - op_table_start_queue_ptr = queue_ram_read_active_head_ptr + 1; + op_table_start_queue_ptr = queue_ram_read_active_prod_ptr + 1; op_table_start_en = 1'b0; op_table_commit_ptr = s_axis_enqueue_commit_op_tag; op_table_commit_en = 1'b0; @@ -417,9 +417,9 @@ always @* begin if (op_req_pipe_reg[PIPELINE-1]) begin // request m_axis_enqueue_resp_queue_next = queue_ram_addr_pipeline_reg[PIPELINE-1]; - m_axis_enqueue_resp_ptr_next = queue_ram_read_active_head_ptr; - m_axis_enqueue_resp_phase_next = !queue_ram_read_active_head_ptr[queue_ram_read_data_log_size]; - m_axis_enqueue_resp_addr_next = queue_ram_read_data_base_addr + ((queue_ram_read_active_head_ptr & ({QUEUE_PTR_WIDTH{1'b1}} >> (QUEUE_PTR_WIDTH - queue_ram_read_data_log_size))) * CPL_SIZE); + m_axis_enqueue_resp_ptr_next = queue_ram_read_active_prod_ptr; + m_axis_enqueue_resp_phase_next = !queue_ram_read_active_prod_ptr[queue_ram_read_data_log_size]; + m_axis_enqueue_resp_addr_next = queue_ram_read_data_base_addr + ((queue_ram_read_active_prod_ptr & ({QUEUE_PTR_WIDTH{1'b1}} >> (QUEUE_PTR_WIDTH - queue_ram_read_data_log_size))) * CPL_SIZE); m_axis_enqueue_resp_event_next = queue_ram_read_data_event; m_axis_enqueue_resp_tag_next = req_tag_pipeline_reg[PIPELINE-1]; m_axis_enqueue_resp_op_tag_next = op_table_start_ptr_reg; @@ -431,9 +431,9 @@ always @* begin queue_ram_wr_en = 1'b1; op_table_start_queue = queue_ram_addr_pipeline_reg[PIPELINE-1]; - op_table_start_queue_ptr = queue_ram_read_active_head_ptr + 1; + op_table_start_queue_ptr = queue_ram_read_active_prod_ptr + 1; - if (!queue_ram_read_data_active) begin + if (!queue_ram_read_data_enable) begin // queue inactive m_axis_enqueue_resp_error_next = 1'b1; m_axis_enqueue_resp_valid_next = 1'b1; @@ -452,14 +452,14 @@ always @* begin end else if (op_commit_pipe_reg[PIPELINE-1]) begin // commit - // update head pointer + // update producer pointer queue_ram_write_ptr = queue_ram_addr_pipeline_reg[PIPELINE-1]; queue_ram_write_data[15:0] = write_data_pipeline_reg[PIPELINE-1]; queue_ram_be[1:0] = 2'b11; queue_ram_wr_en = 1'b1; queue_ram_write_data[55:48] = queue_ram_read_data_pipeline_reg[PIPELINE-1][55:48]; - // generate event on head pointer update + // generate event on producer pointer update if (queue_ram_read_data_armed) begin m_axis_event_next = queue_ram_read_data_event; m_axis_event_source_next = queue_ram_addr_pipeline_reg[PIPELINE-1]; @@ -480,102 +480,99 @@ always @* begin // TODO parametrize case (axil_reg_pipeline_reg[PIPELINE-1]) - 3'd0: begin + 2'd0: begin // base address lower 32 // base address is read-only when queue is active - if (!queue_ram_read_data_active) begin - queue_ram_write_data[95:64] = write_data_pipeline_reg[PIPELINE-1]; - queue_ram_be[11:8] = write_strobe_pipeline_reg[PIPELINE-1]; + if (!queue_ram_read_data_enable) begin + queue_ram_write_data[95:76] = write_data_pipeline_reg[PIPELINE-1][31:12]; + queue_ram_be[11:9] = write_strobe_pipeline_reg[PIPELINE-1]; end end - 3'd1: begin + 2'd1: begin // base address upper 32 // base address is read-only when queue is active - if (!queue_ram_read_data_active) begin + if (!queue_ram_read_data_enable) begin queue_ram_write_data[127:96] = write_data_pipeline_reg[PIPELINE-1]; queue_ram_be[15:12] = write_strobe_pipeline_reg[PIPELINE-1]; end end - 3'd2: begin - queue_ram_write_data[55:48] = queue_ram_read_data_pipeline_reg[PIPELINE-1][55:48]; - // log size - // log size is read-only when queue is active - if (!queue_ram_read_data_active) begin - if (write_strobe_pipeline_reg[PIPELINE-1][0]) begin - queue_ram_write_data[51:48] = write_data_pipeline_reg[PIPELINE-1][3:0]; + 2'd2, 2'd3: begin + casez (write_data_pipeline_reg[PIPELINE-1]) + 32'h8001zzzz: begin + // set VF ID + // TODO + end + 32'h8002zzzz: begin + // set size + if (!queue_ram_read_data_enable) begin + queue_ram_write_data[51:48] = write_data_pipeline_reg[PIPELINE-1][15:0]; + queue_ram_be[6] = 1'b1; + end + end + 32'hC0zzzzzz: begin + // set EQN + if (!queue_ram_read_data_enable) begin + queue_ram_write_data[47:32] = write_data_pipeline_reg[PIPELINE-1][23:0]; + queue_ram_be[5:4] = 2'b11; + end + end + 32'h8080zzzz: begin + // set producer pointer + if (!queue_ram_read_data_enable) begin + queue_ram_write_data[15:0] = write_data_pipeline_reg[PIPELINE-1][15:0]; + queue_ram_be[1:0] = 2'b11; + end + end + 32'h8090zzzz: begin + // set consumer pointer + queue_ram_write_data[31:16] = write_data_pipeline_reg[PIPELINE-1][15:0]; + queue_ram_be[3:2] = 2'b11; + end + 32'h8091zzzz: begin + // set consumer pointer, arm + queue_ram_write_data[31:16] = write_data_pipeline_reg[PIPELINE-1][15:0]; + queue_ram_be[3:2] = 2'b11; + + queue_ram_write_data[54] = 1'b1; + queue_ram_be[6] = 1'b1; + + if (queue_ram_read_data_enable && queue_ram_read_data_prod_ptr != write_data_pipeline_reg[PIPELINE-1][15:0]) begin + // armed and queue not empty + // so generate event + m_axis_event_next = queue_ram_read_data_event; + m_axis_event_source_next = queue_ram_addr_pipeline_reg[PIPELINE-1]; + m_axis_event_valid_next = 1'b1; + + queue_ram_write_data[54] = 1'b0; + queue_ram_be[6] = 1'b1; + end + end + 32'h400001zz: begin + // set enable + queue_ram_write_data[55] = write_data_pipeline_reg[PIPELINE-1][0]; queue_ram_be[6] = 1'b1; end - end - // active - if (write_strobe_pipeline_reg[PIPELINE-1][3]) begin - queue_ram_write_data[55] = write_data_pipeline_reg[PIPELINE-1][31]; - queue_ram_be[6] = 1'b1; - end - end - 3'd3: begin - // event index - // event index is read-only when queue is active - if (!queue_ram_read_data_active) begin - queue_ram_write_data[47:32] = write_data_pipeline_reg[PIPELINE-1]; - queue_ram_be[5:4] = write_strobe_pipeline_reg[PIPELINE-1]; - end + 32'h400002zz: begin + // set arm + queue_ram_write_data[54] = write_data_pipeline_reg[PIPELINE-1][0]; + queue_ram_be[6] = 1'b1; - queue_ram_write_data[55:48] = queue_ram_read_data_pipeline_reg[PIPELINE-1][55:48]; - // continuous - if (write_strobe_pipeline_reg[PIPELINE-1][3]) begin - queue_ram_write_data[53] = write_data_pipeline_reg[PIPELINE-1][30]; - queue_ram_be[6] = 1'b1; - end - // armed - if (write_strobe_pipeline_reg[PIPELINE-1][3]) begin - queue_ram_write_data[54] = write_data_pipeline_reg[PIPELINE-1][31]; - queue_ram_be[6] = 1'b1; + if (queue_ram_read_data_enable && write_data_pipeline_reg[PIPELINE-1][0] && (queue_ram_read_data_prod_ptr != queue_ram_read_data_cons_ptr)) begin + // armed and queue not empty + // so generate event + m_axis_event_next = queue_ram_read_data_event; + m_axis_event_source_next = queue_ram_addr_pipeline_reg[PIPELINE-1]; + m_axis_event_valid_next = 1'b1; - if (write_data_pipeline_reg[PIPELINE-1][31] && (queue_ram_read_data_head_ptr != queue_ram_read_data_tail_ptr)) begin - // armed and queue not empty - // so generate event - m_axis_event_next = queue_ram_read_data_event; - m_axis_event_source_next = queue_ram_addr_pipeline_reg[PIPELINE-1]; - m_axis_event_valid_next = 1'b1; - - if (!write_data_pipeline_reg[PIPELINE-1][30]) begin queue_ram_write_data[54] = 1'b0; queue_ram_be[6] = 1'b1; end end - end - end - 3'd4: begin - // head pointer - // tail pointer is read-only when queue is active - if (!queue_ram_read_data_active) begin - queue_ram_write_data[15:0] = write_data_pipeline_reg[PIPELINE-1][15:0]; - queue_ram_be[1:0] = write_strobe_pipeline_reg[PIPELINE-1][1:0]; - end - end - 3'd6: begin - // tail pointer - queue_ram_write_data[31:16] = write_data_pipeline_reg[PIPELINE-1][15:0]; - queue_ram_be[3:2] = write_strobe_pipeline_reg[PIPELINE-1][1:0]; - - // re-arm - if (write_strobe_pipeline_reg[PIPELINE-1][3] && write_data_pipeline_reg[PIPELINE-1][31]) begin - queue_ram_write_data[54] = 1'b1; - queue_ram_be[6] = 1'b1; - - if (queue_ram_read_data_head_ptr != write_data_pipeline_reg[PIPELINE-1][15:0]) begin - // armed and queue not empty - // so generate event - m_axis_event_next = queue_ram_read_data_event; - m_axis_event_source_next = queue_ram_addr_pipeline_reg[PIPELINE-1]; - m_axis_event_valid_next = 1'b1; - - if (!write_data_pipeline_reg[PIPELINE-1][30]) begin - queue_ram_write_data[54] = 1'b0; - queue_ram_be[6] = 1'b1; - end + default: begin + // invalid command + $display("Error: Invalid command 0x%x for queue %d (instance %m)", write_data_pipeline_reg[PIPELINE-1], queue_ram_addr_pipeline_reg[PIPELINE-1]); end - end + endcase end endcase end else if (op_axil_read_pipe_reg[PIPELINE-1]) begin @@ -583,35 +580,33 @@ always @* begin s_axil_rvalid_next = 1'b1; s_axil_rdata_next = 0; - // TODO parametrize case (axil_reg_pipeline_reg[PIPELINE-1]) - 3'd0: begin + 2'd0: begin + // VF ID + s_axil_rdata_next[11:0] = 0; // TODO // base address lower 32 - s_axil_rdata_next = queue_ram_read_data_base_addr[31:0]; + s_axil_rdata_next[31:12] = queue_ram_read_data_base_addr[31:12]; end - 3'd1: begin + 2'd1: begin // base address upper 32 s_axil_rdata_next = queue_ram_read_data_base_addr[63:32]; end - 3'd2: begin + 2'd2: begin + // EQN + s_axil_rdata_next[15:0] = queue_ram_read_data_event; + // control/status + s_axil_rdata_next[16] = queue_ram_read_data_enable; + s_axil_rdata_next[17] = queue_ram_read_data_armed; + s_axil_rdata_next[18] = queue_ram_read_data_continuous; + s_axil_rdata_next[19] = queue_active; // log size - s_axil_rdata_next[3:0] = queue_ram_read_data_log_size; - // active - s_axil_rdata_next[31] = queue_ram_read_data_active; + s_axil_rdata_next[31:28] = queue_ram_read_data_log_size; end - 3'd3: begin - // event index - s_axil_rdata_next[29:0] = queue_ram_read_data_event; - s_axil_rdata_next[30] = queue_ram_read_data_continuous; - s_axil_rdata_next[31] = queue_ram_read_data_armed; - end - 3'd4: begin - // head pointer - s_axil_rdata_next = queue_ram_read_data_head_ptr; - end - 3'd6: begin - // tail pointer - s_axil_rdata_next = queue_ram_read_data_tail_ptr; + 2'd3: begin + // producer pointer + s_axil_rdata_next[15:0] = queue_ram_read_data_prod_ptr; + // consumer pointer + s_axil_rdata_next[31:16] = queue_ram_read_data_cons_ptr; end endcase end diff --git a/fpga/common/rtl/mqnic_interface.v b/fpga/common/rtl/mqnic_interface.v index 3245a2d85..60c21130a 100644 --- a/fpga/common/rtl/mqnic_interface.v +++ b/fpga/common/rtl/mqnic_interface.v @@ -1157,39 +1157,39 @@ always @(posedge clk) begin RBB+8'h2C: ctrl_reg_rd_data_reg <= rx_mtu_reg; // IF ctrl: RX MTU // Queue manager (Event) RBB+8'h40: ctrl_reg_rd_data_reg <= 32'h0000C010; // Event QM: Type - RBB+8'h44: ctrl_reg_rd_data_reg <= 32'h00000200; // Event QM: Version + RBB+8'h44: ctrl_reg_rd_data_reg <= 32'h00000300; // Event QM: Version RBB+8'h48: ctrl_reg_rd_data_reg <= RB_BASE_ADDR+8'h60; // Event QM: Next header RBB+8'h4C: ctrl_reg_rd_data_reg <= AXIL_EQM_BASE_ADDR; // Event QM: Offset RBB+8'h50: ctrl_reg_rd_data_reg <= 2**EVENT_QUEUE_INDEX_WIDTH; // Event QM: Count - RBB+8'h54: ctrl_reg_rd_data_reg <= 32; // Event QM: Stride + RBB+8'h54: ctrl_reg_rd_data_reg <= 16; // Event QM: Stride // Queue manager (TX) RBB+8'h60: ctrl_reg_rd_data_reg <= 32'h0000C020; // TX QM: Type - RBB+8'h64: ctrl_reg_rd_data_reg <= 32'h00000200; // TX QM: Version + RBB+8'h64: ctrl_reg_rd_data_reg <= 32'h00000300; // TX QM: Version RBB+8'h68: ctrl_reg_rd_data_reg <= RB_BASE_ADDR+8'h80; // TX QM: Next header RBB+8'h6C: ctrl_reg_rd_data_reg <= AXIL_TX_QM_BASE_ADDR; // TX QM: Offset RBB+8'h70: ctrl_reg_rd_data_reg <= 2**TX_QUEUE_INDEX_WIDTH; // TX QM: Count RBB+8'h74: ctrl_reg_rd_data_reg <= 32; // TX QM: Stride // Queue manager (TX CPL) RBB+8'h80: ctrl_reg_rd_data_reg <= 32'h0000C030; // TX CPL QM: Type - RBB+8'h84: ctrl_reg_rd_data_reg <= 32'h00000200; // TX CPL QM: Version + RBB+8'h84: ctrl_reg_rd_data_reg <= 32'h00000300; // TX CPL QM: Version RBB+8'h88: ctrl_reg_rd_data_reg <= RB_BASE_ADDR+8'hA0; // TX CPL QM: Next header RBB+8'h8C: ctrl_reg_rd_data_reg <= AXIL_TX_CQM_BASE_ADDR; // TX CPL QM: Offset RBB+8'h90: ctrl_reg_rd_data_reg <= 2**TX_CPL_QUEUE_INDEX_WIDTH; // TX CPL QM: Count - RBB+8'h94: ctrl_reg_rd_data_reg <= 32; // TX CPL QM: Stride + RBB+8'h94: ctrl_reg_rd_data_reg <= 16; // TX CPL QM: Stride // Queue manager (RX) RBB+8'hA0: ctrl_reg_rd_data_reg <= 32'h0000C021; // RX QM: Type - RBB+8'hA4: ctrl_reg_rd_data_reg <= 32'h00000200; // RX QM: Version + RBB+8'hA4: ctrl_reg_rd_data_reg <= 32'h00000300; // RX QM: Version RBB+8'hA8: ctrl_reg_rd_data_reg <= RB_BASE_ADDR+8'hC0; // RX QM: Next header RBB+8'hAC: ctrl_reg_rd_data_reg <= AXIL_RX_QM_BASE_ADDR; // RX QM: Offset RBB+8'hB0: ctrl_reg_rd_data_reg <= 2**RX_QUEUE_INDEX_WIDTH; // RX QM: Count RBB+8'hB4: ctrl_reg_rd_data_reg <= 32; // RX QM: Stride // Queue manager (RX CPL) RBB+8'hC0: ctrl_reg_rd_data_reg <= 32'h0000C031; // RX CPL QM: Type - RBB+8'hC4: ctrl_reg_rd_data_reg <= 32'h00000200; // RX CPL QM: Version + RBB+8'hC4: ctrl_reg_rd_data_reg <= 32'h00000300; // RX CPL QM: Version RBB+8'hC8: ctrl_reg_rd_data_reg <= RX_RB_BASE_ADDR; // RX CPL QM: Next header RBB+8'hCC: ctrl_reg_rd_data_reg <= AXIL_RX_CQM_BASE_ADDR; // RX CPL QM: Offset RBB+8'hD0: ctrl_reg_rd_data_reg <= 2**RX_CPL_QUEUE_INDEX_WIDTH; // RX CPL QM: Count - RBB+8'hD4: ctrl_reg_rd_data_reg <= 32; // RX CPL QM: Stride + RBB+8'hD4: ctrl_reg_rd_data_reg <= 16; // RX CPL QM: Stride default: ctrl_reg_rd_ack_reg <= 1'b0; endcase end diff --git a/fpga/common/rtl/queue_manager.v b/fpga/common/rtl/queue_manager.v index 3ce4cf623..1e7511bd3 100644 --- a/fpga/common/rtl/queue_manager.v +++ b/fpga/common/rtl/queue_manager.v @@ -39,7 +39,7 @@ module queue_manager # // Width of AXI lite data bus in bits parameter AXIL_DATA_WIDTH = 32, // Width of AXI lite address bus in bits - parameter AXIL_ADDR_WIDTH = 16, + parameter AXIL_ADDR_WIDTH = QUEUE_INDEX_WIDTH+5, // Width of AXI lite wstrb (width of data bus in words) parameter AXIL_STRB_WIDTH = (AXIL_DATA_WIDTH/8) ) @@ -208,14 +208,14 @@ reg [QUEUE_RAM_BE_WIDTH-1:0] queue_ram_be; reg [QUEUE_RAM_WIDTH-1:0] queue_ram_read_data_reg = 0; reg [QUEUE_RAM_WIDTH-1:0] queue_ram_read_data_pipeline_reg[PIPELINE-1:1]; -wire [QUEUE_PTR_WIDTH-1:0] queue_ram_read_data_head_ptr = queue_ram_read_data_pipeline_reg[PIPELINE-1][15:0]; -wire [QUEUE_PTR_WIDTH-1:0] queue_ram_read_data_tail_ptr = queue_ram_read_data_pipeline_reg[PIPELINE-1][31:16]; +wire [QUEUE_PTR_WIDTH-1:0] queue_ram_read_data_prod_ptr = queue_ram_read_data_pipeline_reg[PIPELINE-1][15:0]; +wire [QUEUE_PTR_WIDTH-1:0] queue_ram_read_data_cons_ptr = queue_ram_read_data_pipeline_reg[PIPELINE-1][31:16]; wire [CPL_INDEX_WIDTH-1:0] queue_ram_read_data_cpl_queue = queue_ram_read_data_pipeline_reg[PIPELINE-1][47:32]; wire [LOG_QUEUE_SIZE_WIDTH-1:0] queue_ram_read_data_log_queue_size = queue_ram_read_data_pipeline_reg[PIPELINE-1][51:48]; wire [LOG_BLOCK_SIZE_WIDTH-1:0] queue_ram_read_data_log_block_size = queue_ram_read_data_pipeline_reg[PIPELINE-1][53:52]; -wire queue_ram_read_data_active = queue_ram_read_data_pipeline_reg[PIPELINE-1][55]; +wire queue_ram_read_data_enable = queue_ram_read_data_pipeline_reg[PIPELINE-1][55]; wire [CL_OP_TABLE_SIZE-1:0] queue_ram_read_data_op_index = queue_ram_read_data_pipeline_reg[PIPELINE-1][63:56]; -wire [ADDR_WIDTH-1:0] queue_ram_read_data_base_addr = queue_ram_read_data_pipeline_reg[PIPELINE-1][127:64]; +wire [ADDR_WIDTH-1:0] queue_ram_read_data_base_addr = {queue_ram_read_data_pipeline_reg[PIPELINE-1][127:76], 12'd0}; reg [OP_TABLE_SIZE-1:0] op_table_active = 0; reg [OP_TABLE_SIZE-1:0] op_table_commit = 0; @@ -266,10 +266,10 @@ wire [QUEUE_INDEX_WIDTH-1:0] s_axil_araddr_queue = s_axil_araddr >> 5; wire [2:0] s_axil_araddr_reg = s_axil_araddr >> 2; wire queue_active = op_table_active[queue_ram_read_data_op_index] && op_table_queue[queue_ram_read_data_op_index] == queue_ram_addr_pipeline_reg[PIPELINE-1]; -wire queue_empty_idle = queue_ram_read_data_head_ptr == queue_ram_read_data_tail_ptr; -wire queue_empty_active = queue_ram_read_data_head_ptr == op_table_queue_ptr[queue_ram_read_data_op_index]; +wire queue_empty_idle = queue_ram_read_data_prod_ptr == queue_ram_read_data_cons_ptr; +wire queue_empty_active = queue_ram_read_data_prod_ptr == op_table_queue_ptr[queue_ram_read_data_op_index]; wire queue_empty = queue_active ? queue_empty_active : queue_empty_idle; -wire [QUEUE_PTR_WIDTH-1:0] queue_ram_read_active_tail_ptr = queue_active ? op_table_queue_ptr[queue_ram_read_data_op_index] : queue_ram_read_data_tail_ptr; +wire [QUEUE_PTR_WIDTH-1:0] queue_ram_read_active_cons_ptr = queue_active ? op_table_queue_ptr[queue_ram_read_data_op_index] : queue_ram_read_data_cons_ptr; integer i, j; @@ -348,7 +348,7 @@ always @* begin queue_ram_be = 0; op_table_start_queue = queue_ram_addr_pipeline_reg[PIPELINE-1]; - op_table_start_queue_ptr = queue_ram_read_active_tail_ptr + 1; + op_table_start_queue_ptr = queue_ram_read_active_cons_ptr + 1; op_table_start_en = 1'b0; op_table_commit_ptr = s_axis_dequeue_commit_op_tag; op_table_commit_en = 1'b0; @@ -417,9 +417,9 @@ always @* begin if (op_req_pipe_reg[PIPELINE-1]) begin // request m_axis_dequeue_resp_queue_next = queue_ram_addr_pipeline_reg[PIPELINE-1]; - m_axis_dequeue_resp_ptr_next = queue_ram_read_active_tail_ptr; - m_axis_dequeue_resp_phase_next = !queue_ram_read_active_tail_ptr[queue_ram_read_data_log_queue_size]; - m_axis_dequeue_resp_addr_next = queue_ram_read_data_base_addr + ((queue_ram_read_active_tail_ptr & ({QUEUE_PTR_WIDTH{1'b1}} >> (QUEUE_PTR_WIDTH - queue_ram_read_data_log_queue_size))) << (CL_DESC_SIZE+queue_ram_read_data_log_block_size)); + m_axis_dequeue_resp_ptr_next = queue_ram_read_active_cons_ptr; + m_axis_dequeue_resp_phase_next = !queue_ram_read_active_cons_ptr[queue_ram_read_data_log_queue_size]; + m_axis_dequeue_resp_addr_next = queue_ram_read_data_base_addr + ((queue_ram_read_active_cons_ptr & ({QUEUE_PTR_WIDTH{1'b1}} >> (QUEUE_PTR_WIDTH - queue_ram_read_data_log_queue_size))) << (CL_DESC_SIZE+queue_ram_read_data_log_block_size)); m_axis_dequeue_resp_block_size_next = queue_ram_read_data_log_block_size; m_axis_dequeue_resp_cpl_next = queue_ram_read_data_cpl_queue; m_axis_dequeue_resp_tag_next = req_tag_pipeline_reg[PIPELINE-1]; @@ -432,9 +432,9 @@ always @* begin queue_ram_wr_en = 1'b1; op_table_start_queue = queue_ram_addr_pipeline_reg[PIPELINE-1]; - op_table_start_queue_ptr = queue_ram_read_active_tail_ptr + 1; + op_table_start_queue_ptr = queue_ram_read_active_cons_ptr + 1; - if (!queue_ram_read_data_active) begin + if (!queue_ram_read_data_enable) begin // queue inactive m_axis_dequeue_resp_error_next = 1'b1; m_axis_dequeue_resp_valid_next = 1'b1; @@ -453,7 +453,7 @@ always @* begin end else if (op_commit_pipe_reg[PIPELINE-1]) begin // commit - // update tail pointer + // update consumer pointer queue_ram_write_ptr = queue_ram_addr_pipeline_reg[PIPELINE-1]; queue_ram_write_data[31:16] = write_data_pipeline_reg[PIPELINE-1]; queue_ram_be[3:2] = 2'b11; @@ -470,67 +470,70 @@ always @* begin 3'd0: begin // base address lower 32 // base address is read-only when queue is active - if (!queue_ram_read_data_active) begin - queue_ram_write_data[95:64] = write_data_pipeline_reg[PIPELINE-1]; - queue_ram_be[11:8] = write_strobe_pipeline_reg[PIPELINE-1]; + if (!queue_ram_read_data_enable) begin + queue_ram_write_data[95:76] = write_data_pipeline_reg[PIPELINE-1][31:12]; + queue_ram_be[11:9] = write_strobe_pipeline_reg[PIPELINE-1][3:1]; end end 3'd1: begin // base address upper 32 // base address is read-only when queue is active - if (!queue_ram_read_data_active) begin + if (!queue_ram_read_data_enable) begin queue_ram_write_data[127:96] = write_data_pipeline_reg[PIPELINE-1]; queue_ram_be[15:12] = write_strobe_pipeline_reg[PIPELINE-1]; end end - 3'd2: begin - queue_ram_write_data[55:48] = queue_ram_read_data_pipeline_reg[PIPELINE-1][55:48]; - // log size - // log size is read-only when queue is active - if (!queue_ram_read_data_active) begin - if (write_strobe_pipeline_reg[PIPELINE-1][0]) begin - // log queue size - queue_ram_write_data[51:48] = write_data_pipeline_reg[PIPELINE-1][3:0]; - queue_ram_be[6] = 1'b1; + 3'd2, 3'd3, 4'd4: begin + casez (write_data_pipeline_reg[PIPELINE-1]) + 32'h8001zzzz: begin + // set VF ID + // TODO end - if (write_strobe_pipeline_reg[PIPELINE-1][1]) begin - // log desc block size - queue_ram_write_data[53:52] = write_data_pipeline_reg[PIPELINE-1][9:8]; - queue_ram_be[6] = 1'b1; + 32'h8002zzzz: begin + // set size + if (!queue_ram_read_data_enable) begin + // log queue size + queue_ram_write_data[51:48] = write_data_pipeline_reg[PIPELINE-1][7:0]; + // log desc block size + queue_ram_write_data[53:52] = write_data_pipeline_reg[PIPELINE-1][15:8]; + queue_ram_be[6] = 1'b1; + end end - end - // active - if (write_strobe_pipeline_reg[PIPELINE-1][3]) begin - queue_ram_write_data[55] = write_data_pipeline_reg[PIPELINE-1][31]; - queue_ram_be[6] = 1'b1; - end - end - 3'd3: begin - // completion queue index - // completion queue index is read-only when queue is active - if (!queue_ram_read_data_active) begin - queue_ram_write_data[47:32] = write_data_pipeline_reg[PIPELINE-1]; - queue_ram_be[5:4] = write_strobe_pipeline_reg[PIPELINE-1]; - end - end - 3'd4: begin - // head pointer - queue_ram_write_data[15:0] = write_data_pipeline_reg[PIPELINE-1]; - queue_ram_be[1:0] = write_strobe_pipeline_reg[PIPELINE-1]; + 32'hC0zzzzzz: begin + // set CQN + if (!queue_ram_read_data_enable) begin + queue_ram_write_data[47:32] = write_data_pipeline_reg[PIPELINE-1][23:0]; + queue_ram_be[5:4] = 2'b11; + end + end + 32'h8080zzzz: begin + // set producer pointer + queue_ram_write_data[15:0] = write_data_pipeline_reg[PIPELINE-1][15:0]; + queue_ram_be[1:0] = 2'b11; - // generate doorbell on queue head pointer update - m_axis_doorbell_queue_next = queue_ram_addr_pipeline_reg[PIPELINE-1]; - if (queue_ram_read_data_active) begin - m_axis_doorbell_valid_next = 1'b1; - end - end - 3'd6: begin - // tail pointer - // tail pointer is read-only when queue is active - if (!queue_ram_read_data_active) begin - queue_ram_write_data[31:16] = write_data_pipeline_reg[PIPELINE-1]; - queue_ram_be[3:2] = write_strobe_pipeline_reg[PIPELINE-1]; - end + // generate doorbell on queue producer pointer update + m_axis_doorbell_queue_next = queue_ram_addr_pipeline_reg[PIPELINE-1]; + if (queue_ram_read_data_enable) begin + m_axis_doorbell_valid_next = 1'b1; + end + end + 32'h8090zzzz: begin + // set consumer pointer + if (!queue_ram_read_data_enable) begin + queue_ram_write_data[31:16] = write_data_pipeline_reg[PIPELINE-1][15:0]; + queue_ram_be[3:2] = 2'b11; + end + end + 32'h400001zz: begin + // set enable + queue_ram_write_data[55] = write_data_pipeline_reg[PIPELINE-1][0]; + queue_ram_be[6] = 1'b1; + end + default: begin + // invalid command + $display("Error: Invalid command 0x%x for queue %d (instance %m)", write_data_pipeline_reg[PIPELINE-1], queue_ram_addr_pipeline_reg[PIPELINE-1]); + end + endcase end endcase end else if (op_axil_read_pipe_reg[PIPELINE-1]) begin @@ -541,32 +544,36 @@ always @* begin // TODO parametrize case (axil_reg_pipeline_reg[PIPELINE-1]) 3'd0: begin + // VF ID + s_axil_rdata_next[11:0] = 0; // TODO // base address lower 32 - s_axil_rdata_next = queue_ram_read_data_base_addr[31:0]; + s_axil_rdata_next[31:12] = queue_ram_read_data_base_addr[31:12]; end 3'd1: begin // base address upper 32 s_axil_rdata_next = queue_ram_read_data_base_addr[63:32]; end 3'd2: begin - // log queue size - s_axil_rdata_next[7:0] = queue_ram_read_data_log_queue_size; - // log desc block size - s_axil_rdata_next[15:8] = queue_ram_read_data_log_block_size; + // control/status + // enable + s_axil_rdata_next[0] = queue_ram_read_data_enable; // active - s_axil_rdata_next[31] = queue_ram_read_data_active; + s_axil_rdata_next[3] = queue_active; end 3'd3: begin - // completion queue index - s_axil_rdata_next = queue_ram_read_data_cpl_queue; + // config + // CQN + s_axil_rdata_next[23:0] = queue_ram_read_data_cpl_queue; + // log queue size + s_axil_rdata_next[27:24] = queue_ram_read_data_log_queue_size; + // log desc block size + s_axil_rdata_next[31:28] = queue_ram_read_data_log_block_size; end 3'd4: begin - // head pointer - s_axil_rdata_next = queue_ram_read_data_head_ptr; - end - 3'd6: begin - // tail pointer - s_axil_rdata_next = queue_ram_read_data_tail_ptr; + // producer pointer + s_axil_rdata_next[15:0] = queue_ram_read_data_prod_ptr; + // consumer pointer + s_axil_rdata_next[31:16] = queue_ram_read_data_cons_ptr; end endcase end diff --git a/fpga/common/tb/cpl_queue_manager/Makefile b/fpga/common/tb/cpl_queue_manager/Makefile index 75d2a357f..e21bf1ef3 100644 --- a/fpga/common/tb/cpl_queue_manager/Makefile +++ b/fpga/common/tb/cpl_queue_manager/Makefile @@ -26,7 +26,7 @@ export PARAM_LOG_QUEUE_SIZE_WIDTH := 4 export PARAM_CPL_SIZE := 16 export PARAM_PIPELINE := 2 export PARAM_AXIL_DATA_WIDTH := 32 -export PARAM_AXIL_ADDR_WIDTH := 16 +export PARAM_AXIL_ADDR_WIDTH := $(shell expr $(PARAM_QUEUE_INDEX_WIDTH) + 4 ) export PARAM_AXIL_STRB_WIDTH := $(shell expr $(PARAM_AXIL_DATA_WIDTH) / 8 ) ifeq ($(SIM), icarus) diff --git a/fpga/common/tb/cpl_queue_manager/test_cpl_queue_manager.py b/fpga/common/tb/cpl_queue_manager/test_cpl_queue_manager.py index 766649cc2..2222d5550 100644 --- a/fpga/common/tb/cpl_queue_manager/test_cpl_queue_manager.py +++ b/fpga/common/tb/cpl_queue_manager/test_cpl_queue_manager.py @@ -76,6 +76,27 @@ class TB(object): await RisingEdge(self.dut.clk) +MQNIC_CQ_BASE_ADDR_VF_REG = 0x00 +MQNIC_CQ_CTRL_STATUS_REG = 0x08 +MQNIC_CQ_PTR_REG = 0x0C +MQNIC_CQ_PROD_PTR_REG = 0x0C +MQNIC_CQ_CONS_PTR_REG = 0x0E + +MQNIC_CQ_ENABLE_MASK = 0x00010000 +MQNIC_CQ_ARM_MASK = 0x00020000 +MQNIC_CQ_ACTIVE_MASK = 0x00080000 +MQNIC_CQ_PTR_MASK = 0xFFFF + +MQNIC_CQ_CMD_SET_VF_ID = 0x80010000 +MQNIC_CQ_CMD_SET_SIZE = 0x80020000 +MQNIC_CQ_CMD_SET_EQN = 0xC0000000 +MQNIC_CQ_CMD_SET_PROD_PTR = 0x80800000 +MQNIC_CQ_CMD_SET_CONS_PTR = 0x80900000 +MQNIC_CQ_CMD_SET_CONS_PTR_ARM = 0x80910000 +MQNIC_CQ_CMD_SET_ENABLE = 0x40000100 +MQNIC_CQ_CMD_SET_ARM = 0x40000200 + + async def run_test(dut): OP_TABLE_SIZE = int(os.getenv("PARAM_OP_TABLE_SIZE")) @@ -88,22 +109,23 @@ async def run_test(dut): tb.log.info("Test read and write queue configuration registers") - await tb.axil_master.write_qword(0*32+0, 0x8877665544332211) # address - await tb.axil_master.write_dword(0*32+8, 0x00000004) # active, log size - await tb.axil_master.write_dword(0*32+12, 0x80000001) # armed, continuous, event - await tb.axil_master.write_dword(0*32+16, 0x00000000) # head pointer - await tb.axil_master.write_dword(0*32+24, 0x00000000) # tail pointer - await tb.axil_master.write_dword(0*32+8, 0x80000004) # active, log size + await tb.axil_master.write_dword(0*16+MQNIC_CQ_CTRL_STATUS_REG, MQNIC_CQ_CMD_SET_ENABLE | 0) + await tb.axil_master.write_qword(0*16+MQNIC_CQ_BASE_ADDR_VF_REG, 0x8877665544332000) + await tb.axil_master.write_dword(0*16+MQNIC_CQ_CTRL_STATUS_REG, MQNIC_CQ_CMD_SET_VF_ID | 0) + await tb.axil_master.write_dword(0*16+MQNIC_CQ_CTRL_STATUS_REG, MQNIC_CQ_CMD_SET_SIZE | 4) + await tb.axil_master.write_dword(0*16+MQNIC_CQ_CTRL_STATUS_REG, MQNIC_CQ_CMD_SET_EQN | 1) + await tb.axil_master.write_dword(0*16+MQNIC_CQ_CTRL_STATUS_REG, MQNIC_CQ_CMD_SET_PROD_PTR | 0) + await tb.axil_master.write_dword(0*16+MQNIC_CQ_CTRL_STATUS_REG, MQNIC_CQ_CMD_SET_CONS_PTR_ARM | 0) + await tb.axil_master.write_dword(0*16+MQNIC_CQ_CTRL_STATUS_REG, MQNIC_CQ_CMD_SET_ENABLE | 1) - assert await tb.axil_master.read_qword(0*32+0) == 0x8877665544332211 - assert await tb.axil_master.read_dword(0*32+8) == 0x80000004 - assert await tb.axil_master.read_dword(0*32+12) == 0x80000001 + assert await tb.axil_master.read_qword(0*16+MQNIC_CQ_BASE_ADDR_VF_REG) == 0x8877665544332000 + assert await tb.axil_master.read_dword(0*16+MQNIC_CQ_CTRL_STATUS_REG) == (4 << 28) | MQNIC_CQ_ENABLE_MASK | MQNIC_CQ_ARM_MASK | 1 tb.log.info("Test enqueue and dequeue") - # read head pointer - head_ptr = await tb.axil_master.read_dword(0*32+16) # head pointer - tb.log.info("Head pointer: %d", head_ptr) + # read producer pointer + prod_ptr = (await tb.axil_master.read_dword(0*16+MQNIC_CQ_PTR_REG)) >> 16 + tb.log.info("Producer pointer: %d", prod_ptr) # enqueue request await tb.enqueue_req_source.send(EnqueueReqTransaction(queue=0, tag=1)) @@ -113,9 +135,9 @@ async def run_test(dut): tb.log.info("Enqueue response: %s", resp) assert resp.queue == 0 - assert resp.ptr == head_ptr + assert resp.ptr == prod_ptr assert resp.phase == ~(resp.ptr >> 4) & 1 - assert resp.addr == 0x8877665544332211 + assert resp.addr == 0x8877665544332000 assert resp.event == 1 assert resp.tag == 1 assert not resp.full @@ -133,33 +155,34 @@ async def run_test(dut): assert event.event == 1 assert event.event_source == 0 - # read head pointer - new_head_ptr = await tb.axil_master.read_dword(0*32+16) # head pointer - tb.log.info("Head pointer: %d", new_head_ptr) + # read producer pointer + new_prod_ptr = (await tb.axil_master.read_dword(0*16+MQNIC_CQ_PTR_REG)) & MQNIC_CQ_PTR_MASK + tb.log.info("Producer pointer: %d", new_prod_ptr) - assert new_head_ptr - head_ptr == 1 + assert new_prod_ptr - prod_ptr == 1 - # increment tail pointer - tail_ptr = await tb.axil_master.read_dword(0*32+24) # tail pointer - tail_ptr += 1 - tb.log.info("Tail pointer: %d", tail_ptr) - await tb.axil_master.write_dword(0*32+24, tail_ptr) # head pointer + # increment consumer pointer + cons_ptr = (await tb.axil_master.read_dword(0*16+MQNIC_CQ_PTR_REG)) >> 16 + cons_ptr += 1 + tb.log.info("Consumer pointer: %d", cons_ptr) + await tb.axil_master.write_dword(0*16+MQNIC_CQ_CTRL_STATUS_REG, MQNIC_CQ_CMD_SET_CONS_PTR | cons_ptr) tb.log.info("Test multiple enqueue and dequeue") for k in range(4): - await tb.axil_master.write_dword(k*32+8, 0x00000004) # active, log size - await tb.axil_master.write_qword(k*32+0, 0x5555555555000000 + 0x10000*k) # address - await tb.axil_master.write_dword(k*32+8, 0x00000004) # active, log size - await tb.axil_master.write_dword(k*32+12, 0xC0000000 + k) # armed, continuous, event - await tb.axil_master.write_dword(k*32+16, 0x0000fff0) # head pointer - await tb.axil_master.write_dword(k*32+24, 0x0000fff0) # tail pointer - await tb.axil_master.write_dword(k*32+8, 0x80000004) # active, log size + await tb.axil_master.write_dword(k*16+MQNIC_CQ_CTRL_STATUS_REG, MQNIC_CQ_CMD_SET_ENABLE | 0) + await tb.axil_master.write_qword(k*16+MQNIC_CQ_BASE_ADDR_VF_REG, 0x5555555555000000 + 0x10000*k) + await tb.axil_master.write_dword(k*16+MQNIC_CQ_CTRL_STATUS_REG, MQNIC_CQ_CMD_SET_VF_ID | 0) + await tb.axil_master.write_dword(k*16+MQNIC_CQ_CTRL_STATUS_REG, MQNIC_CQ_CMD_SET_SIZE | 4) + await tb.axil_master.write_dword(k*16+MQNIC_CQ_CTRL_STATUS_REG, MQNIC_CQ_CMD_SET_EQN | k) + await tb.axil_master.write_dword(k*16+MQNIC_CQ_CTRL_STATUS_REG, MQNIC_CQ_CMD_SET_PROD_PTR | 0xfff0) + await tb.axil_master.write_dword(k*16+MQNIC_CQ_CTRL_STATUS_REG, MQNIC_CQ_CMD_SET_CONS_PTR_ARM | 0xfff0) + await tb.axil_master.write_dword(k*16+MQNIC_CQ_CTRL_STATUS_REG, MQNIC_CQ_CMD_SET_ENABLE | 1) current_tag = 1 - queue_head_ptr = [0xfff0]*4 - queue_tail_ptr = [0xfff0]*4 + queue_prod_ptr = [0xfff0]*4 + queue_cons_ptr = [0xfff0]*4 queue_depth = [0]*4 queue_uncommit_depth = [0]*4 @@ -183,17 +206,17 @@ async def run_test(dut): tb.log.info("Enqueue response: %s", resp) assert resp.queue == q - assert resp.ptr == queue_head_ptr[q] + assert resp.ptr == queue_prod_ptr[q] assert resp.phase == ~(resp.ptr >> 4) & 1 assert (resp.addr >> 16) & 0xf == q - assert (resp.addr >> 4) & 0xf == queue_head_ptr[q] & 0xf + assert (resp.addr >> 4) & 0xf == queue_prod_ptr[q] & 0xf assert resp.event == q assert resp.tag == current_tag assert not resp.error if queue_uncommit_depth[q] < 16: commit_list.append((q, resp.op_tag)) - queue_head_ptr[q] = (queue_head_ptr[q] + 1) & 0xffff + queue_prod_ptr[q] = (queue_prod_ptr[q] + 1) & MQNIC_CQ_PTR_MASK queue_uncommit_depth[q] += 1 assert not resp.full else: @@ -215,13 +238,6 @@ async def run_test(dut): queue_depth[q] += 1 - # check event - event = await tb.event_sink.recv() - tb.log.info("Event: %s", event) - - assert event.event == q - assert event.event_source == q - # dequeue for k in range(random.randrange(8)): q = random.randrange(4) @@ -229,19 +245,19 @@ async def run_test(dut): if queue_depth[q] > 0: tb.log.info("Dequeue from queue %d", q) - # increment tail pointer - tail_ptr = await tb.axil_master.read_dword(q*32+24) # tail pointer + # increment consumer pointer + cons_ptr = (await tb.axil_master.read_dword(q*16+MQNIC_CQ_PTR_REG)) >> 16 - assert tail_ptr == queue_tail_ptr[q] + assert cons_ptr == queue_cons_ptr[q] - tail_ptr = (tail_ptr + 1) & 0xffff + cons_ptr = (cons_ptr + 1) & MQNIC_CQ_PTR_MASK - queue_tail_ptr[q] = tail_ptr + queue_cons_ptr[q] = cons_ptr queue_depth[q] -= 1 queue_uncommit_depth[q] -= 1 - tb.log.info("Tail pointer: %d", tail_ptr) - await tb.axil_master.write_dword(q*32+24, tail_ptr) # tail pointer + tb.log.info("Consumer pointer: %d", cons_ptr) + await tb.axil_master.write_dword(q*16+MQNIC_CQ_CTRL_STATUS_REG, MQNIC_CQ_CMD_SET_CONS_PTR | cons_ptr) await RisingEdge(dut.clk) await RisingEdge(dut.clk) @@ -286,7 +302,7 @@ def test_cpl_queue_manager(request): parameters['CPL_SIZE'] = 16 parameters['PIPELINE'] = 2 parameters['AXIL_DATA_WIDTH'] = 32 - parameters['AXIL_ADDR_WIDTH'] = 16 + parameters['AXIL_ADDR_WIDTH'] = parameters['QUEUE_INDEX_WIDTH'] + 4 parameters['AXIL_STRB_WIDTH'] = parameters['AXIL_DATA_WIDTH'] // 8 extra_env = {f'PARAM_{k}': str(v) for k, v in parameters.items()} diff --git a/fpga/common/tb/mqnic.py b/fpga/common/tb/mqnic.py index 5f8b64e8b..d04133991 100644 --- a/fpga/common/tb/mqnic.py +++ b/fpga/common/tb/mqnic.py @@ -159,31 +159,31 @@ MQNIC_RB_RX_QUEUE_MAP_CH_REG_RSS_MASK = 0x04 MQNIC_RB_RX_QUEUE_MAP_CH_REG_APP_MASK = 0x08 MQNIC_RB_EQM_TYPE = 0x0000C010 -MQNIC_RB_EQM_VER = 0x00000200 +MQNIC_RB_EQM_VER = 0x00000300 MQNIC_RB_EQM_REG_OFFSET = 0x0C MQNIC_RB_EQM_REG_COUNT = 0x10 MQNIC_RB_EQM_REG_STRIDE = 0x14 MQNIC_RB_TX_QM_TYPE = 0x0000C020 -MQNIC_RB_TX_QM_VER = 0x00000200 +MQNIC_RB_TX_QM_VER = 0x00000300 MQNIC_RB_TX_QM_REG_OFFSET = 0x0C MQNIC_RB_TX_QM_REG_COUNT = 0x10 MQNIC_RB_TX_QM_REG_STRIDE = 0x14 MQNIC_RB_TX_CQM_TYPE = 0x0000C030 -MQNIC_RB_TX_CQM_VER = 0x00000200 +MQNIC_RB_TX_CQM_VER = 0x00000300 MQNIC_RB_TX_CQM_REG_OFFSET = 0x0C MQNIC_RB_TX_CQM_REG_COUNT = 0x10 MQNIC_RB_TX_CQM_REG_STRIDE = 0x14 MQNIC_RB_RX_QM_TYPE = 0x0000C021 -MQNIC_RB_RX_QM_VER = 0x00000200 +MQNIC_RB_RX_QM_VER = 0x00000300 MQNIC_RB_RX_QM_REG_OFFSET = 0x0C MQNIC_RB_RX_QM_REG_COUNT = 0x10 MQNIC_RB_RX_QM_REG_STRIDE = 0x14 MQNIC_RB_RX_CQM_TYPE = 0x0000C031 -MQNIC_RB_RX_CQM_VER = 0x00000200 +MQNIC_RB_RX_CQM_VER = 0x00000300 MQNIC_RB_RX_CQM_REG_OFFSET = 0x0C MQNIC_RB_RX_CQM_REG_COUNT = 0x10 MQNIC_RB_RX_CQM_REG_STRIDE = 0x14 @@ -244,35 +244,63 @@ MQNIC_RB_APP_INFO_TYPE = 0x0000C005 MQNIC_RB_APP_INFO_VER = 0x00000200 MQNIC_RB_APP_INFO_REG_ID = 0x0C -MQNIC_QUEUE_BASE_ADDR_REG = 0x00 -MQNIC_QUEUE_ACTIVE_LOG_SIZE_REG = 0x08 -MQNIC_QUEUE_CPL_QUEUE_INDEX_REG = 0x0C -MQNIC_QUEUE_HEAD_PTR_REG = 0x10 -MQNIC_QUEUE_TAIL_PTR_REG = 0x18 +MQNIC_QUEUE_BASE_ADDR_VF_REG = 0x00 +MQNIC_QUEUE_CTRL_STATUS_REG = 0x08 +MQNIC_QUEUE_SIZE_CQN_REG = 0x0C +MQNIC_QUEUE_PTR_REG = 0x10 +MQNIC_QUEUE_PROD_PTR_REG = 0x10 +MQNIC_QUEUE_CONS_PTR_REG = 0x12 -MQNIC_QUEUE_ACTIVE_MASK = 0x80000000 +MQNIC_QUEUE_ENABLE_MASK = 0x00000001 +MQNIC_QUEUE_ACTIVE_MASK = 0x00000008 +MQNIC_QUEUE_PTR_MASK = 0xFFFF -MQNIC_CQ_BASE_ADDR_REG = 0x00 -MQNIC_CQ_ACTIVE_LOG_SIZE_REG = 0x08 -MQNIC_CQ_INTERRUPT_INDEX_REG = 0x0C -MQNIC_CQ_HEAD_PTR_REG = 0x10 -MQNIC_CQ_TAIL_PTR_REG = 0x18 +MQNIC_QUEUE_CMD_SET_VF_ID = 0x80010000 +MQNIC_QUEUE_CMD_SET_SIZE = 0x80020000 +MQNIC_QUEUE_CMD_SET_CQN = 0xC0000000 +MQNIC_QUEUE_CMD_SET_PROD_PTR = 0x80800000 +MQNIC_QUEUE_CMD_SET_CONS_PTR = 0x80900000 +MQNIC_QUEUE_CMD_SET_ENABLE = 0x40000100 -MQNIC_CQ_ACTIVE_MASK = 0x80000000 +MQNIC_CQ_BASE_ADDR_VF_REG = 0x00 +MQNIC_CQ_CTRL_STATUS_REG = 0x08 +MQNIC_CQ_PTR_REG = 0x0C +MQNIC_CQ_PROD_PTR_REG = 0x0C +MQNIC_CQ_CONS_PTR_REG = 0x0E -MQNIC_CQ_ARM_MASK = 0x80000000 -MQNIC_CQ_CONT_MASK = 0x40000000 +MQNIC_CQ_ENABLE_MASK = 0x00010000 +MQNIC_CQ_ARM_MASK = 0x00020000 +MQNIC_CQ_ACTIVE_MASK = 0x00080000 +MQNIC_CQ_PTR_MASK = 0xFFFF -MQNIC_EQ_BASE_ADDR_REG = 0x00 -MQNIC_EQ_ACTIVE_LOG_SIZE_REG = 0x08 -MQNIC_EQ_INTERRUPT_INDEX_REG = 0x0C -MQNIC_EQ_HEAD_PTR_REG = 0x10 -MQNIC_EQ_TAIL_PTR_REG = 0x18 +MQNIC_CQ_CMD_SET_VF_ID = 0x80010000 +MQNIC_CQ_CMD_SET_SIZE = 0x80020000 +MQNIC_CQ_CMD_SET_EQN = 0xC0000000 +MQNIC_CQ_CMD_SET_PROD_PTR = 0x80800000 +MQNIC_CQ_CMD_SET_CONS_PTR = 0x80900000 +MQNIC_CQ_CMD_SET_CONS_PTR_ARM = 0x80910000 +MQNIC_CQ_CMD_SET_ENABLE = 0x40000100 +MQNIC_CQ_CMD_SET_ARM = 0x40000200 -MQNIC_EQ_ACTIVE_MASK = 0x80000000 +MQNIC_EQ_BASE_ADDR_VF_REG = 0x00 +MQNIC_EQ_CTRL_STATUS_REG = 0x08 +MQNIC_EQ_PTR_REG = 0x0C +MQNIC_EQ_PROD_PTR_REG = 0x0C +MQNIC_EQ_CONS_PTR_REG = 0x0E -MQNIC_EQ_ARM_MASK = 0x80000000 -MQNIC_EQ_CONT_MASK = 0x40000000 +MQNIC_EQ_ENABLE_MASK = 0x00010000 +MQNIC_EQ_ARM_MASK = 0x00020000 +MQNIC_EQ_ACTIVE_MASK = 0x00080000 +MQNIC_EQ_PTR_MASK = 0xFFFF + +MQNIC_EQ_CMD_SET_VF_ID = 0x80010000 +MQNIC_EQ_CMD_SET_SIZE = 0x80020000 +MQNIC_EQ_CMD_SET_IRQN = 0xC0000000 +MQNIC_EQ_CMD_SET_PROD_PTR = 0x80800000 +MQNIC_EQ_CMD_SET_CONS_PTR = 0x80900000 +MQNIC_EQ_CMD_SET_CONS_PTR_ARM = 0x80910000 +MQNIC_EQ_CMD_SET_ENABLE = 0x40000100 +MQNIC_EQ_CMD_SET_ARM = 0x40000200 MQNIC_EVENT_TYPE_TX_CPL = 0x0000 MQNIC_EVENT_TYPE_RX_CPL = 0x0001 @@ -399,10 +427,9 @@ class Eq: self.cq_table = {} - self.head_ptr = 0 - self.tail_ptr = 0 + self.prod_ptr = 0 + self.cons_ptr = 0 - self.hw_ptr_mask = 0xffff self.hw_regs = None async def open(self, irq, size): @@ -425,8 +452,8 @@ class Eq: self.buf[0:self.buf_size] = b'\x00'*self.buf_size - self.head_ptr = 0 - self.tail_ptr = 0 + self.prod_ptr = 0 + self.cons_ptr = 0 self.irq = irq @@ -434,13 +461,14 @@ class Eq: self.hw_regs = self.interface.eq_res.get_window(self.eqn) - await self.hw_regs.write_dword(MQNIC_EQ_ACTIVE_LOG_SIZE_REG, 0) # active, log size - await self.hw_regs.write_dword(MQNIC_EQ_BASE_ADDR_REG, self.buf_dma & 0xffffffff) # base address - await self.hw_regs.write_dword(MQNIC_EQ_BASE_ADDR_REG+4, self.buf_dma >> 32) # base address - await self.hw_regs.write_dword(MQNIC_EQ_INTERRUPT_INDEX_REG, self.irq) # interrupt index - await self.hw_regs.write_dword(MQNIC_EQ_HEAD_PTR_REG, self.head_ptr & self.hw_ptr_mask) # head pointer - await self.hw_regs.write_dword(MQNIC_EQ_TAIL_PTR_REG, self.tail_ptr & self.hw_ptr_mask) # tail pointer - await self.hw_regs.write_dword(MQNIC_EQ_ACTIVE_LOG_SIZE_REG, self.log_size | MQNIC_EQ_ACTIVE_MASK) # active, log size + await self.hw_regs.write_dword(MQNIC_EQ_CTRL_STATUS_REG, MQNIC_EQ_CMD_SET_ENABLE | 0) + await self.hw_regs.write_dword(MQNIC_EQ_BASE_ADDR_VF_REG, self.buf_dma & 0xfffff000) + await self.hw_regs.write_dword(MQNIC_EQ_BASE_ADDR_VF_REG+4, self.buf_dma >> 32) + await self.hw_regs.write_dword(MQNIC_EQ_CTRL_STATUS_REG, MQNIC_EQ_CMD_SET_SIZE | self.log_size) + await self.hw_regs.write_dword(MQNIC_EQ_CTRL_STATUS_REG, MQNIC_EQ_CMD_SET_IRQN | self.irq) + await self.hw_regs.write_dword(MQNIC_EQ_CTRL_STATUS_REG, MQNIC_EQ_CMD_SET_PROD_PTR | (self.prod_ptr & MQNIC_EQ_PTR_MASK)) + await self.hw_regs.write_dword(MQNIC_EQ_CTRL_STATUS_REG, MQNIC_EQ_CMD_SET_CONS_PTR | (self.cons_ptr & MQNIC_EQ_PTR_MASK)) + await self.hw_regs.write_dword(MQNIC_EQ_CTRL_STATUS_REG, MQNIC_EQ_CMD_SET_ENABLE | 1) self.enabled = True @@ -448,8 +476,7 @@ class Eq: if not self.hw_regs: return - await self.hw_regs.write_dword(MQNIC_EQ_ACTIVE_LOG_SIZE_REG, self.log_size) # active, log size - await self.hw_regs.write_dword(MQNIC_EQ_INTERRUPT_INDEX_REG, 0) # interrupt index + await self.hw_regs.write_dword(MQNIC_EQ_CTRL_STATUS_REG, MQNIC_EQ_CMD_SET_ENABLE | 0) # TODO free buffer @@ -474,18 +501,18 @@ class Eq: else: del self.cq_table[cq.cqn] - async def read_head_ptr(self): - val = await self.hw_regs.read_dword(MQNIC_EQ_HEAD_PTR_REG) - self.head_ptr += (val - self.head_ptr) & self.hw_ptr_mask + async def read_prod_ptr(self): + val = await self.hw_regs.read_dword(MQNIC_EQ_PTR_REG) + self.prod_ptr += ((val & MQNIC_EQ_PTR_MASK) - self.prod_ptr) & MQNIC_EQ_PTR_MASK - async def write_tail_ptr(self): - await self.hw_regs.write_dword(MQNIC_EQ_TAIL_PTR_REG, self.tail_ptr & self.hw_ptr_mask) + async def write_cons_ptr(self): + await self.hw_regs.write_dword(MQNIC_EQ_CTRL_STATUS_REG, MQNIC_EQ_CMD_SET_CONS_PTR | (self.cons_ptr & MQNIC_EQ_PTR_MASK)) async def arm(self): if not self.hw_regs: return - await self.hw_regs.write_dword(MQNIC_EQ_INTERRUPT_INDEX_REG, self.irq | MQNIC_EQ_ARM_MASK) # interrupt index + await self.hw_regs.write_dword(MQNIC_EQ_CTRL_STATUS_REG, MQNIC_EQ_CMD_SET_ARM | 1) async def process_eq(self): if not self.interface.port_up: @@ -493,15 +520,15 @@ class Eq: self.log.info("Process EQ") - eq_tail_ptr = self.tail_ptr - eq_index = eq_tail_ptr & self.size_mask + eq_cons_ptr = self.cons_ptr + eq_index = eq_cons_ptr & self.size_mask while True: event_data = struct.unpack_from("> 32) # base address - await self.hw_regs.write_dword(MQNIC_CQ_INTERRUPT_INDEX_REG, self.eq.eqn) # event index - await self.hw_regs.write_dword(MQNIC_CQ_HEAD_PTR_REG, self.head_ptr & self.hw_ptr_mask) # head pointer - await self.hw_regs.write_dword(MQNIC_CQ_TAIL_PTR_REG, self.tail_ptr & self.hw_ptr_mask) # tail pointer - await self.hw_regs.write_dword(MQNIC_CQ_ACTIVE_LOG_SIZE_REG, self.log_size | MQNIC_CQ_ACTIVE_MASK) # active, log size + await self.hw_regs.write_dword(MQNIC_CQ_CTRL_STATUS_REG, MQNIC_CQ_CMD_SET_ENABLE | 0) + await self.hw_regs.write_dword(MQNIC_CQ_BASE_ADDR_VF_REG, self.buf_dma & 0xfffff000) + await self.hw_regs.write_dword(MQNIC_CQ_BASE_ADDR_VF_REG+4, self.buf_dma >> 32) + await self.hw_regs.write_dword(MQNIC_CQ_CTRL_STATUS_REG, MQNIC_CQ_CMD_SET_SIZE | self.log_size) + await self.hw_regs.write_dword(MQNIC_CQ_CTRL_STATUS_REG, MQNIC_CQ_CMD_SET_EQN | self.eq.eqn) + await self.hw_regs.write_dword(MQNIC_CQ_CTRL_STATUS_REG, MQNIC_CQ_CMD_SET_PROD_PTR | (self.prod_ptr & MQNIC_CQ_PTR_MASK)) + await self.hw_regs.write_dword(MQNIC_CQ_CTRL_STATUS_REG, MQNIC_CQ_CMD_SET_CONS_PTR | (self.cons_ptr & MQNIC_CQ_PTR_MASK)) + await self.hw_regs.write_dword(MQNIC_CQ_CTRL_STATUS_REG, MQNIC_CQ_CMD_SET_ENABLE | 1) self.enabled = True @@ -600,8 +627,7 @@ class Cq: if not self.hw_regs: return - await self.hw_regs.write_dword(MQNIC_CQ_ACTIVE_LOG_SIZE_REG, self.log_size) # active, log size - await self.hw_regs.write_dword(MQNIC_CQ_INTERRUPT_INDEX_REG, 0) # event index + await self.hw_regs.write_dword(MQNIC_CQ_CTRL_STATUS_REG, MQNIC_CQ_CMD_SET_ENABLE | 0) # TODO free buffer @@ -618,18 +644,18 @@ class Cq: self.interface.rx_cq_res.free(self.cqn) self.cqn = None - async def read_head_ptr(self): - val = await self.hw_regs.read_dword(MQNIC_CQ_HEAD_PTR_REG) - self.head_ptr += (val - self.head_ptr) & self.hw_ptr_mask + async def read_prod_ptr(self): + val = await self.hw_regs.read_dword(MQNIC_CQ_PTR_REG) + self.prod_ptr += ((val & MQNIC_CQ_PTR_MASK) - self.prod_ptr) & MQNIC_CQ_PTR_MASK - async def write_tail_ptr(self): - await self.hw_regs.write_dword(MQNIC_CQ_TAIL_PTR_REG, self.tail_ptr & self.hw_ptr_mask) + async def write_cons_ptr(self): + await self.hw_regs.write_dword(MQNIC_CQ_CTRL_STATUS_REG, MQNIC_CQ_CMD_SET_CONS_PTR | (self.cons_ptr & MQNIC_CQ_PTR_MASK)) async def arm(self): if not self.hw_regs: return - await self.hw_regs.write_dword(MQNIC_CQ_INTERRUPT_INDEX_REG, self.eq.eqn | MQNIC_CQ_ARM_MASK) # event index + await self.hw_regs.write_dword(MQNIC_CQ_CTRL_STATUS_REG, MQNIC_CQ_CMD_SET_ARM | 1) class Txq: @@ -654,15 +680,14 @@ class Txq: self.cq = None - self.head_ptr = 0 - self.tail_ptr = 0 + self.prod_ptr = 0 + self.cons_ptr = 0 self.clean_event = Event() self.packets = 0 self.bytes = 0 - self.hw_ptr_mask = 0xffff self.hw_regs = None async def open(self, cq, size, desc_block_size): @@ -688,8 +713,8 @@ class Txq: self.buf_dma = self.buf_region.get_absolute_address(0) self.buf = self.buf_region.mem - self.head_ptr = 0 - self.tail_ptr = 0 + self.prod_ptr = 0 + self.cons_ptr = 0 self.cq = cq self.cq.src_ring = self @@ -697,13 +722,13 @@ class Txq: self.hw_regs = self.interface.txq_res.get_window(self.index) - await self.hw_regs.write_dword(MQNIC_QUEUE_ACTIVE_LOG_SIZE_REG, 0) # active, log size - await self.hw_regs.write_dword(MQNIC_QUEUE_BASE_ADDR_REG, self.buf_dma & 0xffffffff) # base address - await self.hw_regs.write_dword(MQNIC_QUEUE_BASE_ADDR_REG+4, self.buf_dma >> 32) # base address - await self.hw_regs.write_dword(MQNIC_QUEUE_CPL_QUEUE_INDEX_REG, self.cq.cqn) # completion queue index - await self.hw_regs.write_dword(MQNIC_QUEUE_HEAD_PTR_REG, self.head_ptr & self.hw_ptr_mask) # head pointer - await self.hw_regs.write_dword(MQNIC_QUEUE_TAIL_PTR_REG, self.tail_ptr & self.hw_ptr_mask) # tail pointer - await self.hw_regs.write_dword(MQNIC_QUEUE_ACTIVE_LOG_SIZE_REG, self.log_queue_size | (self.log_desc_block_size << 8)) # active, log desc block size, log queue size + await self.hw_regs.write_dword(MQNIC_QUEUE_CTRL_STATUS_REG, MQNIC_QUEUE_CMD_SET_ENABLE | 0) + await self.hw_regs.write_dword(MQNIC_QUEUE_BASE_ADDR_VF_REG, self.buf_dma & 0xfffff000) + await self.hw_regs.write_dword(MQNIC_QUEUE_BASE_ADDR_VF_REG+4, self.buf_dma >> 32) + await self.hw_regs.write_dword(MQNIC_QUEUE_CTRL_STATUS_REG, MQNIC_QUEUE_CMD_SET_SIZE | (self.log_desc_block_size << 8) | self.log_queue_size) + await self.hw_regs.write_dword(MQNIC_QUEUE_CTRL_STATUS_REG, MQNIC_QUEUE_CMD_SET_CQN | self.cq.cqn) + await self.hw_regs.write_dword(MQNIC_QUEUE_CTRL_STATUS_REG, MQNIC_QUEUE_CMD_SET_PROD_PTR | (self.prod_ptr & MQNIC_QUEUE_PTR_MASK)) + await self.hw_regs.write_dword(MQNIC_QUEUE_CTRL_STATUS_REG, MQNIC_QUEUE_CMD_SET_CONS_PTR | (self.cons_ptr & MQNIC_QUEUE_PTR_MASK)) async def close(self): if not self.hw_regs: @@ -728,7 +753,7 @@ class Txq: if not self.hw_regs: raise Exception("Not open") - await self.hw_regs.write_dword(MQNIC_QUEUE_ACTIVE_LOG_SIZE_REG, self.log_queue_size | (self.log_desc_block_size << 8) | MQNIC_QUEUE_ACTIVE_MASK) # active, log desc block size, log queue size + await self.hw_regs.write_dword(MQNIC_QUEUE_CTRL_STATUS_REG, MQNIC_QUEUE_CMD_SET_ENABLE | 1) self.enabled = True @@ -736,22 +761,22 @@ class Txq: if not self.hw_regs: return - await self.hw_regs.write_dword(MQNIC_QUEUE_ACTIVE_LOG_SIZE_REG, self.log_queue_size | (self.log_desc_block_size << 8)) # active, log desc block size, log queue size + await self.hw_regs.write_dword(MQNIC_QUEUE_CTRL_STATUS_REG, MQNIC_QUEUE_CMD_SET_ENABLE | 0) self.enabled = False def empty(self): - return self.head_ptr == self.tail_ptr + return self.prod_ptr == self.cons_ptr def full(self): - return self.head_ptr - self.tail_ptr >= self.full_size + return self.prod_ptr - self.cons_ptr >= self.full_size - async def read_tail_ptr(self): - val = await self.hw_regs.read_dword(MQNIC_QUEUE_TAIL_PTR_REG) - self.tail_ptr += (val - self.tail_ptr) & self.hw_ptr_mask + async def read_cons_ptr(self): + val = await self.hw_regs.read_dword(MQNIC_QUEUE_PTR_REG) + self.cons_ptr += ((val >> 16) - self.cons_ptr) & MQNIC_QUEUE_PTR_MASK - async def write_head_ptr(self): - await self.hw_regs.write_dword(MQNIC_QUEUE_HEAD_PTR_REG, self.head_ptr & self.hw_ptr_mask) + async def write_prod_ptr(self): + await self.hw_regs.write_dword(MQNIC_QUEUE_CTRL_STATUS_REG, MQNIC_QUEUE_CMD_SET_PROD_PTR | (self.prod_ptr & MQNIC_QUEUE_PTR_MASK)) def free_desc(self, index): pkt = self.tx_info[index] @@ -760,9 +785,9 @@ class Txq: def free_buf(self): while not self.empty(): - index = self.tail_ptr & self.size_mask + index = self.cons_ptr & self.size_mask self.free_desc(index) - self.tail_ptr += 1 + self.cons_ptr += 1 @staticmethod async def process_tx_cq(cq): @@ -776,8 +801,8 @@ class Txq: return # process completion queue - cq_tail_ptr = cq.tail_ptr - cq_index = cq_tail_ptr & cq.size_mask + cq_cons_ptr = cq.cons_ptr + cq_index = cq_cons_ptr & cq.size_mask while True: cpl_data = struct.unpack_from("> 32) # base address - await self.hw_regs.write_dword(MQNIC_QUEUE_CPL_QUEUE_INDEX_REG, self.cq.cqn) # completion queue index - await self.hw_regs.write_dword(MQNIC_QUEUE_HEAD_PTR_REG, self.head_ptr & self.hw_ptr_mask) # head pointer - await self.hw_regs.write_dword(MQNIC_QUEUE_TAIL_PTR_REG, self.tail_ptr & self.hw_ptr_mask) # tail pointer - await self.hw_regs.write_dword(MQNIC_QUEUE_ACTIVE_LOG_SIZE_REG, self.log_queue_size | (self.log_desc_block_size << 8)) # active, log desc block size, log queue size + await self.hw_regs.write_dword(MQNIC_QUEUE_CTRL_STATUS_REG, MQNIC_QUEUE_CMD_SET_ENABLE | 0) + await self.hw_regs.write_dword(MQNIC_QUEUE_BASE_ADDR_VF_REG, self.buf_dma & 0xfffff000) + await self.hw_regs.write_dword(MQNIC_QUEUE_BASE_ADDR_VF_REG+4, self.buf_dma >> 32) + await self.hw_regs.write_dword(MQNIC_QUEUE_CTRL_STATUS_REG, MQNIC_QUEUE_CMD_SET_SIZE | (self.log_desc_block_size << 8) | self.log_queue_size) + await self.hw_regs.write_dword(MQNIC_QUEUE_CTRL_STATUS_REG, MQNIC_QUEUE_CMD_SET_CQN | self.cq.cqn) + await self.hw_regs.write_dword(MQNIC_QUEUE_CTRL_STATUS_REG, MQNIC_QUEUE_CMD_SET_PROD_PTR | (self.prod_ptr & MQNIC_QUEUE_PTR_MASK)) + await self.hw_regs.write_dword(MQNIC_QUEUE_CTRL_STATUS_REG, MQNIC_QUEUE_CMD_SET_CONS_PTR | (self.cons_ptr & MQNIC_QUEUE_PTR_MASK)) await self.refill_buffers() @@ -911,7 +935,7 @@ class Rxq: if not self.hw_regs: raise Exception("Not open") - await self.hw_regs.write_dword(MQNIC_QUEUE_ACTIVE_LOG_SIZE_REG, self.log_queue_size | (self.log_desc_block_size << 8) | MQNIC_QUEUE_ACTIVE_MASK) # active, log desc block size, log queue size + await self.hw_regs.write_dword(MQNIC_QUEUE_CTRL_STATUS_REG, MQNIC_QUEUE_CMD_SET_ENABLE | 1) self.enabled = True @@ -919,22 +943,22 @@ class Rxq: if not self.hw_regs: return - await self.hw_regs.write_dword(MQNIC_QUEUE_ACTIVE_LOG_SIZE_REG, self.log_queue_size | (self.log_desc_block_size << 8)) # active, log desc block size, log queue size + await self.hw_regs.write_dword(MQNIC_QUEUE_CTRL_STATUS_REG, MQNIC_QUEUE_CMD_SET_ENABLE | 0) self.enabled = False def empty(self): - return self.head_ptr == self.tail_ptr + return self.prod_ptr == self.cons_ptr def full(self): - return self.head_ptr - self.tail_ptr >= self.full_size + return self.prod_ptr - self.cons_ptr >= self.full_size - async def read_tail_ptr(self): - val = await self.hw_regs.read_dword(MQNIC_QUEUE_TAIL_PTR_REG) - self.tail_ptr += (val - self.tail_ptr) & self.hw_ptr_mask + async def read_cons_ptr(self): + val = await self.hw_regs.read_dword(MQNIC_QUEUE_PTR_REG) + self.cons_ptr += ((val >> 16) - self.cons_ptr) & MQNIC_QUEUE_PTR_MASK - async def write_head_ptr(self): - await self.hw_regs.write_dword(MQNIC_QUEUE_HEAD_PTR_REG, self.head_ptr & self.hw_ptr_mask) + async def write_prod_ptr(self): + await self.hw_regs.write_dword(MQNIC_QUEUE_CTRL_STATUS_REG, MQNIC_QUEUE_CMD_SET_PROD_PTR | (self.prod_ptr & MQNIC_QUEUE_PTR_MASK)) def free_desc(self, index): pkt = self.rx_info[index] @@ -943,9 +967,9 @@ class Rxq: def free_buf(self): while not self.empty(): - index = self.tail_ptr & self.size_mask + index = self.cons_ptr & self.size_mask self.free_desc(index) - self.tail_ptr += 1 + self.cons_ptr += 1 def prepare_desc(self, index): pkt = self.driver.alloc_pkt() @@ -962,16 +986,16 @@ class Rxq: offset += seg async def refill_buffers(self): - missing = self.size - (self.head_ptr - self.tail_ptr) + missing = self.size - (self.prod_ptr - self.cons_ptr) if missing < 8: return for k in range(missing): - self.prepare_desc(self.head_ptr & self.size_mask) - self.head_ptr += 1 + self.prepare_desc(self.prod_ptr & self.size_mask) + self.prod_ptr += 1 - await self.write_head_ptr() + await self.write_prod_ptr() @staticmethod async def process_rx_cq(cq): @@ -985,8 +1009,8 @@ class Rxq: return # process completion queue - cq_tail_ptr = cq.tail_ptr - cq_index = cq_tail_ptr & cq.size_mask + cq_cons_ptr = cq.cons_ptr + cq_index = cq_cons_ptr & cq.size_mask while True: cpl_data = struct.unpack_from("> 16 + tb.log.info("Consumer pointer: %d", cons_ptr) # dequeue request await tb.dequeue_req_source.send(DequeueReqTransaction(queue=0, tag=1)) @@ -125,9 +146,9 @@ async def run_test(dut): tb.log.info("Dequeue response: %s", resp) assert resp.queue == 0 - assert resp.ptr == tail_ptr + assert resp.ptr == cons_ptr assert resp.phase == ~(resp.ptr >> 4) & 1 - assert resp.addr == 0x8877665544332211 + assert resp.addr == 0x8877665544332000 assert resp.block_size == 0 assert resp.cpl == 1 assert resp.tag == 1 @@ -139,27 +160,28 @@ async def run_test(dut): await Timer(100, 'ns') - # read tail pointer - new_tail_ptr = await tb.axil_master.read_dword(0*32+24) # tail pointer - tb.log.info("Tail pointer: %d", new_tail_ptr) + # read consumer pointer + new_cons_ptr = (await tb.axil_master.read_dword(0*32+MQNIC_QUEUE_PTR_REG)) >> 16 + tb.log.info("Consumer pointer: %d", new_cons_ptr) - assert new_tail_ptr - tail_ptr == 1 + assert new_cons_ptr - cons_ptr == 1 tb.log.info("Test multiple enqueue and dequeue") for k in range(4): - await tb.axil_master.write_dword(k*32+8, 0x00000004) # active, log size - await tb.axil_master.write_qword(k*32+0, 0x5555555555000000 + 0x10000*k) # address - await tb.axil_master.write_dword(k*32+8, 0x00000004) # active, log size - await tb.axil_master.write_dword(k*32+12, 0x00000000 + k) # completion queue index - await tb.axil_master.write_dword(k*32+16, 0x0000fff0) # head pointer - await tb.axil_master.write_dword(k*32+24, 0x0000fff0) # tail pointer - await tb.axil_master.write_dword(k*32+8, 0x80000004) # active, log size + await tb.axil_master.write_dword(k*32+MQNIC_QUEUE_CTRL_STATUS_REG, MQNIC_QUEUE_CMD_SET_ENABLE | 0) + await tb.axil_master.write_qword(k*32+MQNIC_QUEUE_BASE_ADDR_VF_REG, 0x5555555555000000 + 0x10000*k) + await tb.axil_master.write_dword(k*32+MQNIC_QUEUE_CTRL_STATUS_REG, MQNIC_QUEUE_CMD_SET_VF_ID | 0) + await tb.axil_master.write_dword(k*32+MQNIC_QUEUE_CTRL_STATUS_REG, MQNIC_QUEUE_CMD_SET_SIZE | 4) + await tb.axil_master.write_dword(k*32+MQNIC_QUEUE_CTRL_STATUS_REG, MQNIC_QUEUE_CMD_SET_CQN | k) + await tb.axil_master.write_dword(k*32+MQNIC_QUEUE_CTRL_STATUS_REG, MQNIC_QUEUE_CMD_SET_PROD_PTR | 0xfff0) + await tb.axil_master.write_dword(k*32+MQNIC_QUEUE_CTRL_STATUS_REG, MQNIC_QUEUE_CMD_SET_CONS_PTR | 0xfff0) + await tb.axil_master.write_dword(k*32+MQNIC_QUEUE_CTRL_STATUS_REG, MQNIC_QUEUE_CMD_SET_ENABLE | 1) current_tag = 1 - queue_head_ptr = [0xfff0]*4 - queue_tail_ptr = [0xfff0]*4 + queue_prod_ptr = [0xfff0]*4 + queue_cons_ptr = [0xfff0]*4 queue_depth = [0]*4 queue_uncommit_depth = [0]*4 @@ -175,19 +197,19 @@ async def run_test(dut): if queue_depth[q] < 16: tb.log.info("Enqueue into queue %d", q) - # increment head pointer - head_ptr = await tb.axil_master.read_dword(q*32+16) # head pointer + # increment producer pointer + prod_ptr = (await tb.axil_master.read_dword(q*32+MQNIC_QUEUE_PTR_REG)) & MQNIC_QUEUE_PTR_MASK - assert head_ptr == queue_head_ptr[q] + assert prod_ptr == queue_prod_ptr[q] - head_ptr = (head_ptr + 1) & 0xffff + prod_ptr = (prod_ptr + 1) & MQNIC_QUEUE_PTR_MASK - queue_head_ptr[q] = head_ptr + queue_prod_ptr[q] = prod_ptr queue_depth[q] += 1 queue_uncommit_depth[q] += 1 - tb.log.info("Head pointer: %d", head_ptr) - await tb.axil_master.write_dword(q*32+16, head_ptr) # head pointer + tb.log.info("Producer pointer: %d", prod_ptr) + await tb.axil_master.write_dword(q*32+MQNIC_QUEUE_CTRL_STATUS_REG, MQNIC_QUEUE_CMD_SET_PROD_PTR | prod_ptr) # check doorbell event db = await tb.doorbell_sink.recv() @@ -210,10 +232,10 @@ async def run_test(dut): tb.log.info("Dequeue response: %s", resp) assert resp.queue == q - assert resp.ptr == queue_tail_ptr[q] + assert resp.ptr == queue_cons_ptr[q] assert resp.phase == ~(resp.ptr >> 4) & 1 assert (resp.addr >> 16) & 0xf == q - assert (resp.addr >> 4) & 0xf == queue_tail_ptr[q] & 0xf + assert (resp.addr >> 4) & 0xf == queue_cons_ptr[q] & 0xf assert resp.block_size == 0 assert resp.cpl == q assert resp.tag == current_tag @@ -221,7 +243,7 @@ async def run_test(dut): if queue_uncommit_depth[q]: commit_list.append((q, resp.op_tag)) - queue_tail_ptr[q] = (queue_tail_ptr[q] + 1) & 0xffff + queue_cons_ptr[q] = (queue_cons_ptr[q] + 1) & MQNIC_QUEUE_PTR_MASK queue_uncommit_depth[q] -= 1 assert not resp.empty else: @@ -287,7 +309,7 @@ def test_queue_manager(request): parameters['LOG_BLOCK_SIZE_WIDTH'] = 2 parameters['PIPELINE'] = 2 parameters['AXIL_DATA_WIDTH'] = 32 - parameters['AXIL_ADDR_WIDTH'] = 16 + parameters['AXIL_ADDR_WIDTH'] = parameters['QUEUE_INDEX_WIDTH'] + 5 parameters['AXIL_STRB_WIDTH'] = parameters['AXIL_DATA_WIDTH'] // 8 extra_env = {f'PARAM_{k}': str(v) for k, v in parameters.items()} diff --git a/modules/mqnic/mqnic.h b/modules/mqnic/mqnic.h index e3fdb003e..6d45173fe 100644 --- a/modules/mqnic/mqnic.h +++ b/modules/mqnic/mqnic.h @@ -222,14 +222,14 @@ struct mqnic_rx_info { struct mqnic_ring { // written on enqueue (i.e. start_xmit) - u32 head_ptr; + u32 prod_ptr; u64 bytes; u64 packets; u64 dropped_packets; struct netdev_queue *tx_queue; // written from completion - u32 tail_ptr ____cacheline_aligned_in_smp; + u32 cons_ptr ____cacheline_aligned_in_smp; u64 ts_s; u8 ts_valid; @@ -263,16 +263,13 @@ struct mqnic_ring { struct mqnic_cq *cq; int enabled; - u32 hw_ptr_mask; u8 __iomem *hw_addr; - u8 __iomem *hw_head_ptr; - u8 __iomem *hw_tail_ptr; } ____cacheline_aligned_in_smp; struct mqnic_cq { - u32 head_ptr; + u32 prod_ptr; - u32 tail_ptr; + u32 cons_ptr; u32 size; u32 size_mask; @@ -293,16 +290,13 @@ struct mqnic_cq { void (*handler)(struct mqnic_cq *cq); - u32 hw_ptr_mask; u8 __iomem *hw_addr; - u8 __iomem *hw_head_ptr; - u8 __iomem *hw_tail_ptr; }; struct mqnic_eq { - u32 head_ptr; + u32 prod_ptr; - u32 tail_ptr; + u32 cons_ptr; u32 size; u32 size_mask; @@ -325,10 +319,7 @@ struct mqnic_eq { spinlock_t table_lock; struct radix_tree_root cq_table; - u32 hw_ptr_mask; u8 __iomem *hw_addr; - u8 __iomem *hw_head_ptr; - u8 __iomem *hw_tail_ptr; }; struct mqnic_sched { @@ -576,8 +567,8 @@ int mqnic_open_eq(struct mqnic_eq *eq, struct mqnic_irq *irq, int size); void mqnic_close_eq(struct mqnic_eq *eq); int mqnic_eq_attach_cq(struct mqnic_eq *eq, struct mqnic_cq *cq); void mqnic_eq_detach_cq(struct mqnic_eq *eq, struct mqnic_cq *cq); -void mqnic_eq_read_head_ptr(struct mqnic_eq *eq); -void mqnic_eq_write_tail_ptr(struct mqnic_eq *eq); +void mqnic_eq_read_prod_ptr(struct mqnic_eq *eq); +void mqnic_eq_write_cons_ptr(struct mqnic_eq *eq); void mqnic_arm_eq(struct mqnic_eq *eq); void mqnic_process_eq(struct mqnic_eq *eq); @@ -586,8 +577,8 @@ struct mqnic_cq *mqnic_create_cq(struct mqnic_if *interface); void mqnic_destroy_cq(struct mqnic_cq *cq); int mqnic_open_cq(struct mqnic_cq *cq, struct mqnic_eq *eq, int size, int is_txcq); void mqnic_close_cq(struct mqnic_cq *cq); -void mqnic_cq_read_head_ptr(struct mqnic_cq *cq); -void mqnic_cq_write_tail_ptr(struct mqnic_cq *cq); +void mqnic_cq_read_prod_ptr(struct mqnic_cq *cq); +void mqnic_cq_write_cons_ptr(struct mqnic_cq *cq); void mqnic_arm_cq(struct mqnic_cq *cq); // mqnic_tx.c @@ -600,8 +591,8 @@ int mqnic_enable_tx_ring(struct mqnic_ring *ring); void mqnic_disable_tx_ring(struct mqnic_ring *ring); bool mqnic_is_tx_ring_empty(const struct mqnic_ring *ring); bool mqnic_is_tx_ring_full(const struct mqnic_ring *ring); -void mqnic_tx_read_tail_ptr(struct mqnic_ring *ring); -void mqnic_tx_write_head_ptr(struct mqnic_ring *ring); +void mqnic_tx_read_cons_ptr(struct mqnic_ring *ring); +void mqnic_tx_write_prod_ptr(struct mqnic_ring *ring); void mqnic_free_tx_desc(struct mqnic_ring *ring, int index, int napi_budget); int mqnic_free_tx_buf(struct mqnic_ring *ring); int mqnic_process_tx_cq(struct mqnic_cq *cq, int napi_budget); @@ -619,8 +610,8 @@ int mqnic_enable_rx_ring(struct mqnic_ring *ring); void mqnic_disable_rx_ring(struct mqnic_ring *ring); bool mqnic_is_rx_ring_empty(const struct mqnic_ring *ring); bool mqnic_is_rx_ring_full(const struct mqnic_ring *ring); -void mqnic_rx_read_tail_ptr(struct mqnic_ring *ring); -void mqnic_rx_write_head_ptr(struct mqnic_ring *ring); +void mqnic_rx_read_cons_ptr(struct mqnic_ring *ring); +void mqnic_rx_write_prod_ptr(struct mqnic_ring *ring); void mqnic_free_rx_desc(struct mqnic_ring *ring, int index); int mqnic_free_rx_buf(struct mqnic_ring *ring); int mqnic_prepare_rx_desc(struct mqnic_ring *ring, int index); diff --git a/modules/mqnic/mqnic_cq.c b/modules/mqnic/mqnic_cq.c index ccf6535c6..2cab4a757 100644 --- a/modules/mqnic/mqnic_cq.c +++ b/modules/mqnic/mqnic_cq.c @@ -20,12 +20,9 @@ struct mqnic_cq *mqnic_create_cq(struct mqnic_if *interface) cq->enabled = 0; cq->hw_addr = NULL; - cq->hw_ptr_mask = 0xffff; - cq->hw_head_ptr = NULL; - cq->hw_tail_ptr = NULL; - cq->head_ptr = 0; - cq->tail_ptr = 0; + cq->prod_ptr = 0; + cq->cons_ptr = 0; return cq; } @@ -71,26 +68,32 @@ int mqnic_open_cq(struct mqnic_cq *cq, struct mqnic_eq *eq, int size, int is_txc cq->hw_addr = mqnic_res_get_addr(cq->interface->tx_cq_res, cq->cqn); else cq->hw_addr = mqnic_res_get_addr(cq->interface->rx_cq_res, cq->cqn); - cq->hw_head_ptr = cq->hw_addr + MQNIC_CQ_HEAD_PTR_REG; - cq->hw_tail_ptr = cq->hw_addr + MQNIC_CQ_TAIL_PTR_REG; - cq->head_ptr = 0; - cq->tail_ptr = 0; + cq->prod_ptr = 0; + cq->cons_ptr = 0; memset(cq->buf, 1, cq->buf_size); // deactivate queue - iowrite32(0, cq->hw_addr + MQNIC_CQ_ACTIVE_LOG_SIZE_REG); + iowrite32(MQNIC_CQ_CMD_SET_ENABLE | 0, cq->hw_addr + MQNIC_CQ_CTRL_STATUS_REG); // set base address - iowrite32(cq->buf_dma_addr, cq->hw_addr + MQNIC_CQ_BASE_ADDR_REG + 0); - iowrite32(cq->buf_dma_addr >> 32, cq->hw_addr + MQNIC_CQ_BASE_ADDR_REG + 4); - // set EQN - iowrite32(cq->eq->eqn, cq->hw_addr + MQNIC_CQ_INTERRUPT_INDEX_REG); - // set pointers - iowrite32(cq->head_ptr & cq->hw_ptr_mask, cq->hw_addr + MQNIC_CQ_HEAD_PTR_REG); - iowrite32(cq->tail_ptr & cq->hw_ptr_mask, cq->hw_addr + MQNIC_CQ_TAIL_PTR_REG); + iowrite32((cq->buf_dma_addr & 0xfffff000), + cq->hw_addr + MQNIC_CQ_BASE_ADDR_VF_REG + 0); + iowrite32(cq->buf_dma_addr >> 32, + cq->hw_addr + MQNIC_CQ_BASE_ADDR_VF_REG + 4); // set size - iowrite32(ilog2(cq->size) | MQNIC_CQ_ACTIVE_MASK, cq->hw_addr + MQNIC_CQ_ACTIVE_LOG_SIZE_REG); + iowrite32(MQNIC_CQ_CMD_SET_SIZE | ilog2(cq->size), + cq->hw_addr + MQNIC_CQ_CTRL_STATUS_REG); + // set EQN + iowrite32(MQNIC_CQ_CMD_SET_EQN | cq->eq->eqn, + cq->hw_addr + MQNIC_CQ_CTRL_STATUS_REG); + // set pointers + iowrite32(MQNIC_CQ_CMD_SET_PROD_PTR | (cq->prod_ptr & MQNIC_CQ_PTR_MASK), + cq->hw_addr + MQNIC_CQ_CTRL_STATUS_REG); + iowrite32(MQNIC_CQ_CMD_SET_CONS_PTR | (cq->cons_ptr & MQNIC_CQ_PTR_MASK), + cq->hw_addr + MQNIC_CQ_CTRL_STATUS_REG); + // activate queue + iowrite32(MQNIC_CQ_CMD_SET_ENABLE | 1, cq->hw_addr + MQNIC_CQ_CTRL_STATUS_REG); cq->enabled = 1; @@ -105,9 +108,7 @@ void mqnic_close_cq(struct mqnic_cq *cq) { if (cq->hw_addr) { // deactivate queue - iowrite32(ilog2(cq->size), cq->hw_addr + MQNIC_CQ_ACTIVE_LOG_SIZE_REG); - // disarm queue - iowrite32(0, cq->hw_addr + MQNIC_CQ_INTERRUPT_INDEX_REG); + iowrite32(MQNIC_CQ_CMD_SET_ENABLE | 0, cq->hw_addr + MQNIC_CQ_CTRL_STATUS_REG); } if (cq->eq) { @@ -116,8 +117,6 @@ void mqnic_close_cq(struct mqnic_cq *cq) } cq->hw_addr = NULL; - cq->hw_head_ptr = NULL; - cq->hw_tail_ptr = NULL; if (cq->buf) { dma_free_coherent(cq->dev, cq->buf_size, cq->buf, cq->buf_dma_addr); @@ -135,14 +134,15 @@ void mqnic_close_cq(struct mqnic_cq *cq) cq->enabled = 0; } -void mqnic_cq_read_head_ptr(struct mqnic_cq *cq) +void mqnic_cq_read_prod_ptr(struct mqnic_cq *cq) { - cq->head_ptr += (ioread32(cq->hw_head_ptr) - cq->head_ptr) & cq->hw_ptr_mask; + cq->prod_ptr += ((ioread32(cq->hw_addr + MQNIC_CQ_PTR_REG) >> 16) - cq->prod_ptr) & MQNIC_CQ_PTR_MASK; } -void mqnic_cq_write_tail_ptr(struct mqnic_cq *cq) +void mqnic_cq_write_cons_ptr(struct mqnic_cq *cq) { - iowrite32(cq->tail_ptr & cq->hw_ptr_mask, cq->hw_tail_ptr); + iowrite32(MQNIC_CQ_CMD_SET_CONS_PTR | (cq->cons_ptr & MQNIC_CQ_PTR_MASK), + cq->hw_addr + MQNIC_CQ_CTRL_STATUS_REG); } void mqnic_arm_cq(struct mqnic_cq *cq) @@ -150,6 +150,5 @@ void mqnic_arm_cq(struct mqnic_cq *cq) if (!cq->enabled) return; - iowrite32(cq->eq->eqn | MQNIC_CQ_ARM_MASK, - cq->hw_addr + MQNIC_CQ_INTERRUPT_INDEX_REG); + iowrite32(MQNIC_CQ_CMD_SET_ARM | 1, cq->hw_addr + MQNIC_CQ_CTRL_STATUS_REG); } diff --git a/modules/mqnic/mqnic_eq.c b/modules/mqnic/mqnic_eq.c index 6517342f8..2bd7d3643 100644 --- a/modules/mqnic/mqnic_eq.c +++ b/modules/mqnic/mqnic_eq.c @@ -32,12 +32,9 @@ struct mqnic_eq *mqnic_create_eq(struct mqnic_if *interface) eq->irq_nb.notifier_call = mqnic_eq_int; eq->hw_addr = NULL; - eq->hw_ptr_mask = 0xffff; - eq->hw_head_ptr = NULL; - eq->hw_tail_ptr = NULL; - eq->head_ptr = 0; - eq->tail_ptr = 0; + eq->prod_ptr = 0; + eq->cons_ptr = 0; spin_lock_init(&eq->table_lock); @@ -83,28 +80,32 @@ int mqnic_open_eq(struct mqnic_eq *eq, struct mqnic_irq *irq, int size) eq->irq = irq; eq->hw_addr = mqnic_res_get_addr(eq->interface->eq_res, eq->eqn); - eq->hw_head_ptr = eq->hw_addr + MQNIC_EQ_HEAD_PTR_REG; - eq->hw_tail_ptr = eq->hw_addr + MQNIC_EQ_TAIL_PTR_REG; - eq->head_ptr = 0; - eq->tail_ptr = 0; + eq->prod_ptr = 0; + eq->cons_ptr = 0; memset(eq->buf, 1, eq->buf_size); // deactivate queue - iowrite32(0, eq->hw_addr + MQNIC_EQ_ACTIVE_LOG_SIZE_REG); + iowrite32(MQNIC_EQ_CMD_SET_ENABLE | 0, eq->hw_addr + MQNIC_EQ_CTRL_STATUS_REG); // set base address - iowrite32(eq->buf_dma_addr, eq->hw_addr + MQNIC_EQ_BASE_ADDR_REG + 0); - iowrite32(eq->buf_dma_addr >> 32, eq->hw_addr + MQNIC_EQ_BASE_ADDR_REG + 4); - // set interrupt index - iowrite32(eq->irq->index, eq->hw_addr + MQNIC_EQ_INTERRUPT_INDEX_REG); - // set pointers - iowrite32(eq->head_ptr & eq->hw_ptr_mask, eq->hw_addr + MQNIC_EQ_HEAD_PTR_REG); - iowrite32(eq->tail_ptr & eq->hw_ptr_mask, eq->hw_addr + MQNIC_EQ_TAIL_PTR_REG); + iowrite32((eq->buf_dma_addr & 0xfffff000), + eq->hw_addr + MQNIC_EQ_BASE_ADDR_VF_REG + 0); + iowrite32(eq->buf_dma_addr >> 32, + eq->hw_addr + MQNIC_EQ_BASE_ADDR_VF_REG + 4); // set size - iowrite32(ilog2(eq->size), eq->hw_addr + MQNIC_EQ_ACTIVE_LOG_SIZE_REG); - // set size and activate queue - iowrite32(ilog2(eq->size) | MQNIC_EQ_ACTIVE_MASK, eq->hw_addr + MQNIC_EQ_ACTIVE_LOG_SIZE_REG); + iowrite32(MQNIC_EQ_CMD_SET_SIZE | ilog2(eq->size), + eq->hw_addr + MQNIC_EQ_CTRL_STATUS_REG); + // set IRQN + iowrite32(MQNIC_EQ_CMD_SET_IRQN | eq->irq->index, + eq->hw_addr + MQNIC_EQ_CTRL_STATUS_REG); + // set pointers + iowrite32(MQNIC_EQ_CMD_SET_PROD_PTR | (eq->prod_ptr & MQNIC_EQ_PTR_MASK), + eq->hw_addr + MQNIC_EQ_CTRL_STATUS_REG); + iowrite32(MQNIC_EQ_CMD_SET_CONS_PTR | (eq->cons_ptr & MQNIC_EQ_PTR_MASK), + eq->hw_addr + MQNIC_EQ_CTRL_STATUS_REG); + // activate queue + iowrite32(MQNIC_EQ_CMD_SET_ENABLE | 1, eq->hw_addr + MQNIC_EQ_CTRL_STATUS_REG); eq->enabled = 1; @@ -121,9 +122,7 @@ void mqnic_close_eq(struct mqnic_eq *eq) if (eq->hw_addr) { // deactivate queue - iowrite32(ilog2(eq->size), eq->hw_addr + MQNIC_EQ_ACTIVE_LOG_SIZE_REG); - // disarm queue - iowrite32(0, eq->hw_addr + MQNIC_EQ_INTERRUPT_INDEX_REG); + iowrite32(MQNIC_EQ_CMD_SET_ENABLE | 0, eq->hw_addr + MQNIC_EQ_CTRL_STATUS_REG); } // unregister interrupt @@ -133,8 +132,6 @@ void mqnic_close_eq(struct mqnic_eq *eq) eq->irq = NULL; eq->hw_addr = NULL; - eq->hw_head_ptr = NULL; - eq->hw_tail_ptr = NULL; if (eq->buf) { dma_free_coherent(eq->dev, eq->buf_size, eq->buf, eq->buf_dma_addr); @@ -184,14 +181,15 @@ void mqnic_eq_detach_cq(struct mqnic_eq *eq, struct mqnic_cq *cq) } } -void mqnic_eq_read_head_ptr(struct mqnic_eq *eq) +void mqnic_eq_read_prod_ptr(struct mqnic_eq *eq) { - eq->head_ptr += (ioread32(eq->hw_head_ptr) - eq->head_ptr) & eq->hw_ptr_mask; + eq->prod_ptr += ((ioread32(eq->hw_addr + MQNIC_EQ_PTR_REG) & MQNIC_EQ_PTR_MASK) - eq->prod_ptr) & MQNIC_EQ_PTR_MASK; } -void mqnic_eq_write_tail_ptr(struct mqnic_eq *eq) +void mqnic_eq_write_cons_ptr(struct mqnic_eq *eq) { - iowrite32(eq->tail_ptr & eq->hw_ptr_mask, eq->hw_tail_ptr); + iowrite32(MQNIC_EQ_CMD_SET_CONS_PTR | (eq->cons_ptr & MQNIC_EQ_PTR_MASK), + eq->hw_addr + MQNIC_EQ_CTRL_STATUS_REG); } void mqnic_arm_eq(struct mqnic_eq *eq) @@ -199,7 +197,7 @@ void mqnic_arm_eq(struct mqnic_eq *eq) if (!eq->enabled) return; - iowrite32(eq->irq->index | MQNIC_EQ_ARM_MASK, eq->hw_addr + MQNIC_EQ_INTERRUPT_INDEX_REG); + iowrite32(MQNIC_EQ_CMD_SET_ARM | 1, eq->hw_addr + MQNIC_EQ_CTRL_STATUS_REG); } void mqnic_process_eq(struct mqnic_eq *eq) @@ -208,18 +206,17 @@ void mqnic_process_eq(struct mqnic_eq *eq) struct mqnic_event *event; struct mqnic_cq *cq; u32 eq_index; - u32 eq_tail_ptr; + u32 eq_cons_ptr; int done = 0; int cqn; - // read head pointer from NIC - eq_tail_ptr = eq->tail_ptr; - eq_index = eq_tail_ptr & eq->size_mask; + eq_cons_ptr = eq->cons_ptr; + eq_index = eq_cons_ptr & eq->size_mask; while (1) { event = (struct mqnic_event *)(eq->buf + eq_index * eq->stride); - if (!!(event->phase & cpu_to_le32(0x80000000)) == !!(eq_tail_ptr & eq->size)) + if (!!(event->phase & cpu_to_le32(0x80000000)) == !!(eq_cons_ptr & eq->size)) break; dma_rmb(); @@ -270,11 +267,11 @@ void mqnic_process_eq(struct mqnic_eq *eq) done++; - eq_tail_ptr++; - eq_index = eq_tail_ptr & eq->size_mask; + eq_cons_ptr++; + eq_index = eq_cons_ptr & eq->size_mask; } - // update eq tail - eq->tail_ptr = eq_tail_ptr; - mqnic_eq_write_tail_ptr(eq); + // update EQ consumer pointer + eq->cons_ptr = eq_cons_ptr; + mqnic_eq_write_cons_ptr(eq); } diff --git a/modules/mqnic/mqnic_hw.h b/modules/mqnic/mqnic_hw.h index 132ee0798..af974b9f6 100644 --- a/modules/mqnic/mqnic_hw.h +++ b/modules/mqnic/mqnic_hw.h @@ -198,31 +198,31 @@ #define MQNIC_RB_RX_QUEUE_MAP_CH_REG_APP_MASK 0x08 #define MQNIC_RB_EQM_TYPE 0x0000C010 -#define MQNIC_RB_EQM_VER 0x00000200 +#define MQNIC_RB_EQM_VER 0x00000300 #define MQNIC_RB_EQM_REG_OFFSET 0x0C #define MQNIC_RB_EQM_REG_COUNT 0x10 #define MQNIC_RB_EQM_REG_STRIDE 0x14 #define MQNIC_RB_TX_QM_TYPE 0x0000C020 -#define MQNIC_RB_TX_QM_VER 0x00000200 +#define MQNIC_RB_TX_QM_VER 0x00000300 #define MQNIC_RB_TX_QM_REG_OFFSET 0x0C #define MQNIC_RB_TX_QM_REG_COUNT 0x10 #define MQNIC_RB_TX_QM_REG_STRIDE 0x14 #define MQNIC_RB_TX_CQM_TYPE 0x0000C030 -#define MQNIC_RB_TX_CQM_VER 0x00000200 +#define MQNIC_RB_TX_CQM_VER 0x00000300 #define MQNIC_RB_TX_CQM_REG_OFFSET 0x0C #define MQNIC_RB_TX_CQM_REG_COUNT 0x10 #define MQNIC_RB_TX_CQM_REG_STRIDE 0x14 #define MQNIC_RB_RX_QM_TYPE 0x0000C021 -#define MQNIC_RB_RX_QM_VER 0x00000200 +#define MQNIC_RB_RX_QM_VER 0x00000300 #define MQNIC_RB_RX_QM_REG_OFFSET 0x0C #define MQNIC_RB_RX_QM_REG_COUNT 0x10 #define MQNIC_RB_RX_QM_REG_STRIDE 0x14 #define MQNIC_RB_RX_CQM_TYPE 0x0000C031 -#define MQNIC_RB_RX_CQM_VER 0x00000200 +#define MQNIC_RB_RX_CQM_VER 0x00000300 #define MQNIC_RB_RX_CQM_REG_OFFSET 0x0C #define MQNIC_RB_RX_CQM_REG_COUNT 0x10 #define MQNIC_RB_RX_CQM_REG_STRIDE 0x14 @@ -283,35 +283,63 @@ #define MQNIC_RB_APP_INFO_VER 0x00000200 #define MQNIC_RB_APP_INFO_REG_ID 0x0C -#define MQNIC_QUEUE_BASE_ADDR_REG 0x00 -#define MQNIC_QUEUE_ACTIVE_LOG_SIZE_REG 0x08 -#define MQNIC_QUEUE_CPL_QUEUE_INDEX_REG 0x0C -#define MQNIC_QUEUE_HEAD_PTR_REG 0x10 -#define MQNIC_QUEUE_TAIL_PTR_REG 0x18 +#define MQNIC_QUEUE_BASE_ADDR_VF_REG 0x00 +#define MQNIC_QUEUE_CTRL_STATUS_REG 0x08 +#define MQNIC_QUEUE_SIZE_CQN_REG 0x0C +#define MQNIC_QUEUE_PTR_REG 0x10 +#define MQNIC_QUEUE_PROD_PTR_REG 0x10 +#define MQNIC_QUEUE_CONS_PTR_REG 0x12 -#define MQNIC_QUEUE_ACTIVE_MASK 0x80000000 +#define MQNIC_QUEUE_ENABLE_MASK 0x00000001 +#define MQNIC_QUEUE_ACTIVE_MASK 0x00000008 +#define MQNIC_QUEUE_PTR_MASK 0xFFFF -#define MQNIC_CQ_BASE_ADDR_REG 0x00 -#define MQNIC_CQ_ACTIVE_LOG_SIZE_REG 0x08 -#define MQNIC_CQ_INTERRUPT_INDEX_REG 0x0C -#define MQNIC_CQ_HEAD_PTR_REG 0x10 -#define MQNIC_CQ_TAIL_PTR_REG 0x18 +#define MQNIC_QUEUE_CMD_SET_VF_ID 0x80010000 +#define MQNIC_QUEUE_CMD_SET_SIZE 0x80020000 +#define MQNIC_QUEUE_CMD_SET_CQN 0xC0000000 +#define MQNIC_QUEUE_CMD_SET_PROD_PTR 0x80800000 +#define MQNIC_QUEUE_CMD_SET_CONS_PTR 0x80900000 +#define MQNIC_QUEUE_CMD_SET_ENABLE 0x40000100 -#define MQNIC_CQ_ACTIVE_MASK 0x80000000 +#define MQNIC_CQ_BASE_ADDR_VF_REG 0x00 +#define MQNIC_CQ_CTRL_STATUS_REG 0x08 +#define MQNIC_CQ_PTR_REG 0x0C +#define MQNIC_CQ_PROD_PTR_REG 0x0C +#define MQNIC_CQ_CONS_PTR_REG 0x0E -#define MQNIC_CQ_ARM_MASK 0x80000000 -#define MQNIC_CQ_CONT_MASK 0x40000000 +#define MQNIC_CQ_ENABLE_MASK 0x00010000 +#define MQNIC_CQ_ARM_MASK 0x00020000 +#define MQNIC_CQ_ACTIVE_MASK 0x00080000 +#define MQNIC_CQ_PTR_MASK 0xFFFF -#define MQNIC_EQ_BASE_ADDR_REG 0x00 -#define MQNIC_EQ_ACTIVE_LOG_SIZE_REG 0x08 -#define MQNIC_EQ_INTERRUPT_INDEX_REG 0x0C -#define MQNIC_EQ_HEAD_PTR_REG 0x10 -#define MQNIC_EQ_TAIL_PTR_REG 0x18 +#define MQNIC_CQ_CMD_SET_VF_ID 0x80010000 +#define MQNIC_CQ_CMD_SET_SIZE 0x80020000 +#define MQNIC_CQ_CMD_SET_EQN 0xC0000000 +#define MQNIC_CQ_CMD_SET_PROD_PTR 0x80800000 +#define MQNIC_CQ_CMD_SET_CONS_PTR 0x80900000 +#define MQNIC_CQ_CMD_SET_CONS_PTR_ARM 0x80910000 +#define MQNIC_CQ_CMD_SET_ENABLE 0x40000100 +#define MQNIC_CQ_CMD_SET_ARM 0x40000200 -#define MQNIC_EQ_ACTIVE_MASK 0x80000000 +#define MQNIC_EQ_BASE_ADDR_VF_REG 0x00 +#define MQNIC_EQ_CTRL_STATUS_REG 0x08 +#define MQNIC_EQ_PTR_REG 0x0C +#define MQNIC_EQ_PROD_PTR_REG 0x0C +#define MQNIC_EQ_CONS_PTR_REG 0x0E -#define MQNIC_EQ_ARM_MASK 0x80000000 -#define MQNIC_EQ_CONT_MASK 0x40000000 +#define MQNIC_EQ_ENABLE_MASK 0x00010000 +#define MQNIC_EQ_ARM_MASK 0x00020000 +#define MQNIC_EQ_ACTIVE_MASK 0x00080000 +#define MQNIC_EQ_PTR_MASK 0xFFFF + +#define MQNIC_EQ_CMD_SET_VF_ID 0x80010000 +#define MQNIC_EQ_CMD_SET_SIZE 0x80020000 +#define MQNIC_EQ_CMD_SET_IRQN 0xC0000000 +#define MQNIC_EQ_CMD_SET_PROD_PTR 0x80800000 +#define MQNIC_EQ_CMD_SET_CONS_PTR 0x80900000 +#define MQNIC_EQ_CMD_SET_CONS_PTR_ARM 0x80910000 +#define MQNIC_EQ_CMD_SET_ENABLE 0x40000100 +#define MQNIC_EQ_CMD_SET_ARM 0x40000200 #define MQNIC_EVENT_TYPE_TX_CPL 0x0000 #define MQNIC_EVENT_TYPE_RX_CPL 0x0001 diff --git a/modules/mqnic/mqnic_if.c b/modules/mqnic/mqnic_if.c index 7dc6ceb06..3198cceca 100644 --- a/modules/mqnic/mqnic_if.c +++ b/modules/mqnic/mqnic_if.c @@ -210,9 +210,9 @@ struct mqnic_if *mqnic_create_interface(struct mqnic_dev *mdev, int index, u8 __ } // determine desc block size - iowrite32(0xf << 8, mqnic_res_get_addr(interface->txq_res, 0) + MQNIC_QUEUE_ACTIVE_LOG_SIZE_REG); - interface->max_desc_block_size = 1 << ((ioread32(mqnic_res_get_addr(interface->txq_res, 0) + MQNIC_QUEUE_ACTIVE_LOG_SIZE_REG) >> 8) & 0xf); - iowrite32(0, mqnic_res_get_addr(interface->txq_res, 0) + MQNIC_QUEUE_ACTIVE_LOG_SIZE_REG); + iowrite32(MQNIC_QUEUE_CMD_SET_SIZE | 0xff00, mqnic_res_get_addr(interface->txq_res, 0) + MQNIC_QUEUE_CTRL_STATUS_REG); + interface->max_desc_block_size = 1 << ((ioread32(mqnic_res_get_addr(interface->txq_res, 0) + MQNIC_QUEUE_SIZE_CQN_REG) >> 28) & 0xf); + iowrite32(MQNIC_QUEUE_CMD_SET_SIZE | 0x0000, mqnic_res_get_addr(interface->txq_res, 0) + MQNIC_QUEUE_CTRL_STATUS_REG); dev_info(dev, "Max desc block size: %d", interface->max_desc_block_size); @@ -222,19 +222,19 @@ struct mqnic_if *mqnic_create_interface(struct mqnic_dev *mdev, int index, u8 __ // disable queues for (k = 0; k < mqnic_res_get_count(interface->eq_res); k++) - iowrite32(0, mqnic_res_get_addr(interface->eq_res, k) + MQNIC_EQ_ACTIVE_LOG_SIZE_REG); + iowrite32(MQNIC_EQ_CMD_SET_ENABLE | 0, mqnic_res_get_addr(interface->eq_res, k) + MQNIC_EQ_CTRL_STATUS_REG); for (k = 0; k < mqnic_res_get_count(interface->txq_res); k++) - iowrite32(0, mqnic_res_get_addr(interface->txq_res, k) + MQNIC_QUEUE_ACTIVE_LOG_SIZE_REG); + iowrite32(MQNIC_QUEUE_CMD_SET_ENABLE | 0, mqnic_res_get_addr(interface->txq_res, k) + MQNIC_QUEUE_CTRL_STATUS_REG); for (k = 0; k < mqnic_res_get_count(interface->tx_cq_res); k++) - iowrite32(0, mqnic_res_get_addr(interface->tx_cq_res, k) + MQNIC_CQ_ACTIVE_LOG_SIZE_REG); + iowrite32(MQNIC_CQ_CMD_SET_ENABLE | 0, mqnic_res_get_addr(interface->tx_cq_res, k) + MQNIC_CQ_CTRL_STATUS_REG); for (k = 0; k < mqnic_res_get_count(interface->rxq_res); k++) - iowrite32(0, mqnic_res_get_addr(interface->rxq_res, k) + MQNIC_QUEUE_ACTIVE_LOG_SIZE_REG); + iowrite32(MQNIC_QUEUE_CMD_SET_ENABLE | 0, mqnic_res_get_addr(interface->rxq_res, k) + MQNIC_QUEUE_CTRL_STATUS_REG); for (k = 0; k < mqnic_res_get_count(interface->rx_cq_res); k++) - iowrite32(0, mqnic_res_get_addr(interface->rx_cq_res, k) + MQNIC_CQ_ACTIVE_LOG_SIZE_REG); + iowrite32(MQNIC_CQ_CMD_SET_ENABLE | 0, mqnic_res_get_addr(interface->rx_cq_res, k) + MQNIC_CQ_CTRL_STATUS_REG); // create ports for (k = 0; k < interface->port_count; k++) { diff --git a/modules/mqnic/mqnic_rx.c b/modules/mqnic/mqnic_rx.c index d3cd4569b..170465cd4 100644 --- a/modules/mqnic/mqnic_rx.c +++ b/modules/mqnic/mqnic_rx.c @@ -20,12 +20,9 @@ struct mqnic_ring *mqnic_create_rx_ring(struct mqnic_if *interface) ring->enabled = 0; ring->hw_addr = NULL; - ring->hw_ptr_mask = 0xffff; - ring->hw_head_ptr = NULL; - ring->hw_tail_ptr = NULL; - ring->head_ptr = 0; - ring->tail_ptr = 0; + ring->prod_ptr = 0; + ring->cons_ptr = 0; return ring; } @@ -76,30 +73,34 @@ int mqnic_open_rx_ring(struct mqnic_ring *ring, struct mqnic_priv *priv, cq->handler = mqnic_rx_irq; ring->hw_addr = mqnic_res_get_addr(ring->interface->rxq_res, ring->index); - ring->hw_head_ptr = ring->hw_addr + MQNIC_QUEUE_HEAD_PTR_REG; - ring->hw_tail_ptr = ring->hw_addr + MQNIC_QUEUE_TAIL_PTR_REG; - ring->head_ptr = 0; - ring->tail_ptr = 0; + ring->prod_ptr = 0; + ring->cons_ptr = 0; // deactivate queue - iowrite32(0, ring->hw_addr + MQNIC_QUEUE_ACTIVE_LOG_SIZE_REG); + iowrite32(MQNIC_QUEUE_CMD_SET_ENABLE | 0, + ring->hw_addr + MQNIC_QUEUE_CTRL_STATUS_REG); // set base address - iowrite32(ring->buf_dma_addr, ring->hw_addr + MQNIC_QUEUE_BASE_ADDR_REG + 0); - iowrite32(ring->buf_dma_addr >> 32, ring->hw_addr + MQNIC_QUEUE_BASE_ADDR_REG + 4); - // set CQN - iowrite32(ring->cq->cqn, ring->hw_addr + MQNIC_QUEUE_CPL_QUEUE_INDEX_REG); - // set pointers - iowrite32(ring->head_ptr & ring->hw_ptr_mask, ring->hw_addr + MQNIC_QUEUE_HEAD_PTR_REG); - iowrite32(ring->tail_ptr & ring->hw_ptr_mask, ring->hw_addr + MQNIC_QUEUE_TAIL_PTR_REG); + iowrite32((ring->buf_dma_addr & 0xfffff000), + ring->hw_addr + MQNIC_QUEUE_BASE_ADDR_VF_REG + 0); + iowrite32(ring->buf_dma_addr >> 32, + ring->hw_addr + MQNIC_QUEUE_BASE_ADDR_VF_REG + 4); // set size - iowrite32(ilog2(ring->size) | (ring->log_desc_block_size << 8), - ring->hw_addr + MQNIC_QUEUE_ACTIVE_LOG_SIZE_REG); + iowrite32(MQNIC_QUEUE_CMD_SET_SIZE | ilog2(ring->size) | (ring->log_desc_block_size << 8), + ring->hw_addr + MQNIC_QUEUE_CTRL_STATUS_REG); + // set CQN + iowrite32(MQNIC_QUEUE_CMD_SET_CQN | ring->cq->cqn, + ring->hw_addr + MQNIC_QUEUE_CTRL_STATUS_REG); + // set pointers + iowrite32(MQNIC_QUEUE_CMD_SET_PROD_PTR | (ring->prod_ptr & MQNIC_QUEUE_PTR_MASK), + ring->hw_addr + MQNIC_QUEUE_CTRL_STATUS_REG); + iowrite32(MQNIC_QUEUE_CMD_SET_CONS_PTR | (ring->cons_ptr & MQNIC_QUEUE_PTR_MASK), + ring->hw_addr + MQNIC_QUEUE_CTRL_STATUS_REG); ret = mqnic_refill_rx_buffers(ring); if (ret) { netdev_err(priv->ndev, "failed to allocate RX buffer for RX queue index %d (of %u total) entry index %u (of %u total)", - ring->index, priv->rxq_count, ring->head_ptr, ring->size); + ring->index, priv->rxq_count, ring->prod_ptr, ring->size); if (ret == -ENOMEM) netdev_err(priv->ndev, "machine might not have enough DMA-capable RAM; try to decrease number of RX channels (currently %u) and/or RX ring parameters (entries; currently %u) and/or module parameter \"num_rxq_entries\" (currently %u)", priv->rxq_count, ring->size, mqnic_num_rxq_entries); @@ -127,8 +128,6 @@ void mqnic_close_rx_ring(struct mqnic_ring *ring) ring->cq = NULL; ring->hw_addr = NULL; - ring->hw_head_ptr = NULL; - ring->hw_tail_ptr = NULL; if (ring->buf) { mqnic_free_rx_buf(ring); @@ -153,8 +152,8 @@ int mqnic_enable_rx_ring(struct mqnic_ring *ring) return -EINVAL; // enable queue - iowrite32(ilog2(ring->size) | (ring->log_desc_block_size << 8) | MQNIC_QUEUE_ACTIVE_MASK, - ring->hw_addr + MQNIC_QUEUE_ACTIVE_LOG_SIZE_REG); + iowrite32(MQNIC_QUEUE_CMD_SET_ENABLE | 1, + ring->hw_addr + MQNIC_QUEUE_CTRL_STATUS_REG); ring->enabled = 1; @@ -165,8 +164,8 @@ void mqnic_disable_rx_ring(struct mqnic_ring *ring) { // disable queue if (ring->hw_addr) { - iowrite32(ilog2(ring->size) | (ring->log_desc_block_size << 8), - ring->hw_addr + MQNIC_QUEUE_ACTIVE_LOG_SIZE_REG); + iowrite32(MQNIC_QUEUE_CMD_SET_ENABLE | 0, + ring->hw_addr + MQNIC_QUEUE_CTRL_STATUS_REG); } ring->enabled = 0; @@ -174,33 +173,37 @@ void mqnic_disable_rx_ring(struct mqnic_ring *ring) bool mqnic_is_rx_ring_empty(const struct mqnic_ring *ring) { - return ring->head_ptr == ring->tail_ptr; + return ring->prod_ptr == ring->cons_ptr; } bool mqnic_is_rx_ring_full(const struct mqnic_ring *ring) { - return ring->head_ptr - ring->tail_ptr >= ring->size; + return ring->prod_ptr - ring->cons_ptr >= ring->size; } -void mqnic_rx_read_tail_ptr(struct mqnic_ring *ring) +void mqnic_rx_read_cons_ptr(struct mqnic_ring *ring) { - ring->tail_ptr += (ioread32(ring->hw_tail_ptr) - ring->tail_ptr) & ring->hw_ptr_mask; + ring->cons_ptr += ((ioread32(ring->hw_addr + MQNIC_QUEUE_PTR_REG) >> 16) - ring->cons_ptr) & MQNIC_QUEUE_PTR_MASK; } -void mqnic_rx_write_head_ptr(struct mqnic_ring *ring) +void mqnic_rx_write_prod_ptr(struct mqnic_ring *ring) { - iowrite32(ring->head_ptr & ring->hw_ptr_mask, ring->hw_head_ptr); + iowrite32(MQNIC_QUEUE_CMD_SET_PROD_PTR | (ring->prod_ptr & MQNIC_QUEUE_PTR_MASK), + ring->hw_addr + MQNIC_QUEUE_CTRL_STATUS_REG); } void mqnic_free_rx_desc(struct mqnic_ring *ring, int index) { struct mqnic_rx_info *rx_info = &ring->rx_info[index]; - struct page *page = rx_info->page; + // struct page *page = rx_info->page; + + if (!rx_info->page) + return; dma_unmap_page(ring->dev, dma_unmap_addr(rx_info, dma_addr), dma_unmap_len(rx_info, len), DMA_FROM_DEVICE); rx_info->dma_addr = 0; - __free_pages(page, rx_info->page_order); + __free_pages(rx_info->page, rx_info->page_order); rx_info->page = NULL; } @@ -210,9 +213,9 @@ int mqnic_free_rx_buf(struct mqnic_ring *ring) int cnt = 0; while (!mqnic_is_rx_ring_empty(ring)) { - index = ring->tail_ptr & ring->size_mask; + index = ring->cons_ptr & ring->size_mask; mqnic_free_rx_desc(ring, index); - ring->tail_ptr++; + ring->cons_ptr++; cnt++; } @@ -267,22 +270,22 @@ int mqnic_prepare_rx_desc(struct mqnic_ring *ring, int index) int mqnic_refill_rx_buffers(struct mqnic_ring *ring) { - u32 missing = ring->size - (ring->head_ptr - ring->tail_ptr); + u32 missing = ring->size - (ring->prod_ptr - ring->cons_ptr); int ret = 0; if (missing < 8) return 0; for (; missing-- > 0;) { - ret = mqnic_prepare_rx_desc(ring, ring->head_ptr & ring->size_mask); + ret = mqnic_prepare_rx_desc(ring, ring->prod_ptr & ring->size_mask); if (ret) break; - ring->head_ptr++; + ring->prod_ptr++; } // enqueue on NIC dma_wmb(); - mqnic_rx_write_head_ptr(ring); + mqnic_rx_write_prod_ptr(ring); return ret; } @@ -298,9 +301,9 @@ int mqnic_process_rx_cq(struct mqnic_cq *cq, int napi_budget) struct sk_buff *skb; struct page *page; u32 cq_index; - u32 cq_tail_ptr; + u32 cq_cons_ptr; u32 ring_index; - u32 ring_tail_ptr; + u32 ring_cons_ptr; int done = 0; int budget = napi_budget; u32 len; @@ -309,13 +312,13 @@ int mqnic_process_rx_cq(struct mqnic_cq *cq, int napi_budget) return done; // process completion queue - cq_tail_ptr = cq->tail_ptr; - cq_index = cq_tail_ptr & cq->size_mask; + cq_cons_ptr = cq->cons_ptr; + cq_index = cq_cons_ptr & cq->size_mask; while (done < budget) { cpl = (struct mqnic_cpl *)(cq->buf + cq_index * cq->stride); - if (!!(cpl->phase & cpu_to_le32(0x80000000)) == !!(cq_tail_ptr & cq->size)) + if (!!(cpl->phase & cpu_to_le32(0x80000000)) == !!(cq_cons_ptr & cq->size)) break; dma_rmb(); @@ -377,30 +380,30 @@ int mqnic_process_rx_cq(struct mqnic_cq *cq, int napi_budget) done++; - cq_tail_ptr++; - cq_index = cq_tail_ptr & cq->size_mask; + cq_cons_ptr++; + cq_index = cq_cons_ptr & cq->size_mask; } - // update CQ tail - cq->tail_ptr = cq_tail_ptr; - mqnic_cq_write_tail_ptr(cq); + // update CQ consumer pointer + cq->cons_ptr = cq_cons_ptr; + mqnic_cq_write_cons_ptr(cq); // process ring - ring_tail_ptr = READ_ONCE(rx_ring->tail_ptr); - ring_index = ring_tail_ptr & rx_ring->size_mask; + ring_cons_ptr = READ_ONCE(rx_ring->cons_ptr); + ring_index = ring_cons_ptr & rx_ring->size_mask; - while (ring_tail_ptr != rx_ring->head_ptr) { + while (ring_cons_ptr != rx_ring->prod_ptr) { rx_info = &rx_ring->rx_info[ring_index]; if (rx_info->page) break; - ring_tail_ptr++; - ring_index = ring_tail_ptr & rx_ring->size_mask; + ring_cons_ptr++; + ring_index = ring_cons_ptr & rx_ring->size_mask; } - // update ring tail - WRITE_ONCE(rx_ring->tail_ptr, ring_tail_ptr); + // update consumer pointer + WRITE_ONCE(rx_ring->cons_ptr, ring_cons_ptr); // replenish buffers mqnic_refill_rx_buffers(rx_ring); diff --git a/modules/mqnic/mqnic_tx.c b/modules/mqnic/mqnic_tx.c index 965463c00..d405d597e 100644 --- a/modules/mqnic/mqnic_tx.c +++ b/modules/mqnic/mqnic_tx.c @@ -21,12 +21,9 @@ struct mqnic_ring *mqnic_create_tx_ring(struct mqnic_if *interface) ring->enabled = 0; ring->hw_addr = NULL; - ring->hw_ptr_mask = 0xffff; - ring->hw_head_ptr = NULL; - ring->hw_tail_ptr = NULL; - ring->head_ptr = 0; - ring->tail_ptr = 0; + ring->prod_ptr = 0; + ring->cons_ptr = 0; return ring; } @@ -77,25 +74,29 @@ int mqnic_open_tx_ring(struct mqnic_ring *ring, struct mqnic_priv *priv, cq->handler = mqnic_tx_irq; ring->hw_addr = mqnic_res_get_addr(ring->interface->txq_res, ring->index); - ring->hw_head_ptr = ring->hw_addr + MQNIC_QUEUE_HEAD_PTR_REG; - ring->hw_tail_ptr = ring->hw_addr + MQNIC_QUEUE_TAIL_PTR_REG; - ring->head_ptr = 0; - ring->tail_ptr = 0; + ring->prod_ptr = 0; + ring->cons_ptr = 0; // deactivate queue - iowrite32(0, ring->hw_addr + MQNIC_QUEUE_ACTIVE_LOG_SIZE_REG); + iowrite32(MQNIC_QUEUE_CMD_SET_ENABLE | 0, + ring->hw_addr + MQNIC_QUEUE_CTRL_STATUS_REG); // set base address - iowrite32(ring->buf_dma_addr, ring->hw_addr + MQNIC_QUEUE_BASE_ADDR_REG + 0); - iowrite32(ring->buf_dma_addr >> 32, ring->hw_addr + MQNIC_QUEUE_BASE_ADDR_REG + 4); - // set CQN - iowrite32(ring->cq->cqn, ring->hw_addr + MQNIC_QUEUE_CPL_QUEUE_INDEX_REG); - // set pointers - iowrite32(ring->head_ptr & ring->hw_ptr_mask, ring->hw_addr + MQNIC_QUEUE_HEAD_PTR_REG); - iowrite32(ring->tail_ptr & ring->hw_ptr_mask, ring->hw_addr + MQNIC_QUEUE_TAIL_PTR_REG); + iowrite32((ring->buf_dma_addr & 0xfffff000), + ring->hw_addr + MQNIC_QUEUE_BASE_ADDR_VF_REG + 0); + iowrite32(ring->buf_dma_addr >> 32, + ring->hw_addr + MQNIC_QUEUE_BASE_ADDR_VF_REG + 4); // set size - iowrite32(ilog2(ring->size) | (ring->log_desc_block_size << 8), - ring->hw_addr + MQNIC_QUEUE_ACTIVE_LOG_SIZE_REG); + iowrite32(MQNIC_QUEUE_CMD_SET_SIZE | ilog2(ring->size) | (ring->log_desc_block_size << 8), + ring->hw_addr + MQNIC_QUEUE_CTRL_STATUS_REG); + // set CQN + iowrite32(MQNIC_QUEUE_CMD_SET_CQN | ring->cq->cqn, + ring->hw_addr + MQNIC_QUEUE_CTRL_STATUS_REG); + // set pointers + iowrite32(MQNIC_QUEUE_CMD_SET_PROD_PTR | (ring->prod_ptr & MQNIC_QUEUE_PTR_MASK), + ring->hw_addr + MQNIC_QUEUE_CTRL_STATUS_REG); + iowrite32(MQNIC_QUEUE_CMD_SET_CONS_PTR | (ring->cons_ptr & MQNIC_QUEUE_PTR_MASK), + ring->hw_addr + MQNIC_QUEUE_CTRL_STATUS_REG); return 0; @@ -117,8 +118,6 @@ void mqnic_close_tx_ring(struct mqnic_ring *ring) ring->cq = NULL; ring->hw_addr = NULL; - ring->hw_head_ptr = NULL; - ring->hw_tail_ptr = NULL; if (ring->buf) { mqnic_free_tx_buf(ring); @@ -143,8 +142,8 @@ int mqnic_enable_tx_ring(struct mqnic_ring *ring) return -EINVAL; // enable queue - iowrite32(ilog2(ring->size) | (ring->log_desc_block_size << 8) | MQNIC_QUEUE_ACTIVE_MASK, - ring->hw_addr + MQNIC_QUEUE_ACTIVE_LOG_SIZE_REG); + iowrite32(MQNIC_QUEUE_CMD_SET_ENABLE | 1, + ring->hw_addr + MQNIC_QUEUE_CTRL_STATUS_REG); ring->enabled = 1; @@ -155,8 +154,8 @@ void mqnic_disable_tx_ring(struct mqnic_ring *ring) { // disable queue if (ring->hw_addr) { - iowrite32(ilog2(ring->size) | (ring->log_desc_block_size << 8), - ring->hw_addr + MQNIC_QUEUE_ACTIVE_LOG_SIZE_REG); + iowrite32(MQNIC_QUEUE_CMD_SET_ENABLE | 0, + ring->hw_addr + MQNIC_QUEUE_CTRL_STATUS_REG); } ring->enabled = 0; @@ -164,22 +163,23 @@ void mqnic_disable_tx_ring(struct mqnic_ring *ring) bool mqnic_is_tx_ring_empty(const struct mqnic_ring *ring) { - return ring->head_ptr == ring->tail_ptr; + return ring->prod_ptr == ring->cons_ptr; } bool mqnic_is_tx_ring_full(const struct mqnic_ring *ring) { - return ring->head_ptr - ring->tail_ptr >= ring->full_size; + return ring->prod_ptr - ring->cons_ptr >= ring->full_size; } -void mqnic_tx_read_tail_ptr(struct mqnic_ring *ring) +void mqnic_tx_read_cons_ptr(struct mqnic_ring *ring) { - ring->tail_ptr += (ioread32(ring->hw_tail_ptr) - ring->tail_ptr) & ring->hw_ptr_mask; + ring->cons_ptr += ((ioread32(ring->hw_addr + MQNIC_QUEUE_PTR_REG) >> 16) - ring->cons_ptr) & MQNIC_QUEUE_PTR_MASK; } -void mqnic_tx_write_head_ptr(struct mqnic_ring *ring) +void mqnic_tx_write_prod_ptr(struct mqnic_ring *ring) { - iowrite32(ring->head_ptr & ring->hw_ptr_mask, ring->hw_head_ptr); + iowrite32(MQNIC_QUEUE_CMD_SET_PROD_PTR | (ring->prod_ptr & MQNIC_QUEUE_PTR_MASK), + ring->hw_addr + MQNIC_QUEUE_CTRL_STATUS_REG); } void mqnic_free_tx_desc(struct mqnic_ring *ring, int index, int napi_budget) @@ -209,9 +209,9 @@ int mqnic_free_tx_buf(struct mqnic_ring *ring) int cnt = 0; while (!mqnic_is_tx_ring_empty(ring)) { - index = ring->tail_ptr & ring->size_mask; + index = ring->cons_ptr & ring->size_mask; mqnic_free_tx_desc(ring, index, 0); - ring->tail_ptr++; + ring->cons_ptr++; cnt++; } @@ -227,9 +227,9 @@ int mqnic_process_tx_cq(struct mqnic_cq *cq, int napi_budget) struct mqnic_cpl *cpl; struct skb_shared_hwtstamps hwts; u32 cq_index; - u32 cq_tail_ptr; + u32 cq_cons_ptr; u32 ring_index; - u32 ring_tail_ptr; + u32 ring_cons_ptr; u32 packets = 0; u32 bytes = 0; int done = 0; @@ -242,13 +242,13 @@ int mqnic_process_tx_cq(struct mqnic_cq *cq, int napi_budget) netdev_txq_bql_complete_prefetchw(tx_ring->tx_queue); // process completion queue - cq_tail_ptr = cq->tail_ptr; - cq_index = cq_tail_ptr & cq->size_mask; + cq_cons_ptr = cq->cons_ptr; + cq_index = cq_cons_ptr & cq->size_mask; while (done < budget) { cpl = (struct mqnic_cpl *)(cq->buf + cq_index * cq->stride); - if (!!(cpl->phase & cpu_to_le32(0x80000000)) == !!(cq_tail_ptr & cq->size)) + if (!!(cpl->phase & cpu_to_le32(0x80000000)) == !!(cq_cons_ptr & cq->size)) break; dma_rmb(); @@ -270,30 +270,30 @@ int mqnic_process_tx_cq(struct mqnic_cq *cq, int napi_budget) done++; - cq_tail_ptr++; - cq_index = cq_tail_ptr & cq->size_mask; + cq_cons_ptr++; + cq_index = cq_cons_ptr & cq->size_mask; } - // update CQ tail - cq->tail_ptr = cq_tail_ptr; - mqnic_cq_write_tail_ptr(cq); + // update CQ consumer pointer + cq->cons_ptr = cq_cons_ptr; + mqnic_cq_write_cons_ptr(cq); // process ring - ring_tail_ptr = READ_ONCE(tx_ring->tail_ptr); - ring_index = ring_tail_ptr & tx_ring->size_mask; + ring_cons_ptr = READ_ONCE(tx_ring->cons_ptr); + ring_index = ring_cons_ptr & tx_ring->size_mask; - while (ring_tail_ptr != tx_ring->head_ptr) { + while (ring_cons_ptr != tx_ring->prod_ptr) { tx_info = &tx_ring->tx_info[ring_index]; if (tx_info->skb) break; - ring_tail_ptr++; - ring_index = ring_tail_ptr & tx_ring->size_mask; + ring_cons_ptr++; + ring_index = ring_cons_ptr & tx_ring->size_mask; } - // update ring tail - WRITE_ONCE(tx_ring->tail_ptr, ring_tail_ptr); + // update consumer pointer + WRITE_ONCE(tx_ring->cons_ptr, ring_cons_ptr); // BQL //netdev_tx_completed_queue(tx_ring->tx_queue, packets, bytes); @@ -406,7 +406,7 @@ netdev_tx_t mqnic_start_xmit(struct sk_buff *skb, struct net_device *ndev) int ring_index; u32 index; bool stop_queue; - u32 tail_ptr; + u32 cons_ptr; if (unlikely(!priv->port_up)) goto tx_drop; @@ -421,12 +421,12 @@ netdev_tx_t mqnic_start_xmit(struct sk_buff *skb, struct net_device *ndev) // unknown TX queue goto tx_drop; - tail_ptr = READ_ONCE(ring->tail_ptr); + cons_ptr = READ_ONCE(ring->cons_ptr); // prefetch for BQL netdev_txq_bql_enqueue_prefetchw(ring->tx_queue); - index = ring->head_ptr & ring->size_mask; + index = ring->prod_ptr & ring->size_mask; tx_desc = (struct mqnic_desc *)(ring->buf + index * ring->stride); @@ -478,7 +478,7 @@ netdev_tx_t mqnic_start_xmit(struct sk_buff *skb, struct net_device *ndev) ring->bytes += skb->len; // enqueue - ring->head_ptr++; + ring->prod_ptr++; skb_tx_timestamp(skb); @@ -500,14 +500,14 @@ netdev_tx_t mqnic_start_xmit(struct sk_buff *skb, struct net_device *ndev) if (unlikely(!skb->xmit_more || stop_queue)) { #endif dma_wmb(); - mqnic_tx_write_head_ptr(ring); + mqnic_tx_write_prod_ptr(ring); } // check if queue restarted if (unlikely(stop_queue)) { smp_rmb(); - tail_ptr = READ_ONCE(ring->tail_ptr); + cons_ptr = READ_ONCE(ring->cons_ptr); if (unlikely(!mqnic_is_tx_ring_full(ring))) netif_tx_wake_queue(ring->tx_queue); diff --git a/utils/mqnic-dump.c b/utils/mqnic-dump.c index 04acaf0fe..4ff5fcec5 100644 --- a/utils/mqnic-dump.c +++ b/utils/mqnic-dump.c @@ -357,116 +357,140 @@ int main(int argc, char *argv[]) } printf("TXQ info\n"); - printf(" Queue Base Address E B LS CPL Head Tail Len\n"); + printf(" Queue Base Address En A B LS CQN Prod Cons Len\n"); for (int k = 0; k < mqnic_res_get_count(dev_interface->txq_res); k++) { + uint32_t val; volatile uint8_t *base = mqnic_res_get_addr(dev_interface->txq_res, k); - uint8_t active = (mqnic_reg_read32(base, MQNIC_QUEUE_ACTIVE_LOG_SIZE_REG) & MQNIC_QUEUE_ACTIVE_MASK) != 0; + val = mqnic_reg_read32(base, MQNIC_QUEUE_CTRL_STATUS_REG); + uint8_t enable = (val & MQNIC_QUEUE_ENABLE_MASK) != 0; + uint8_t active = (val & MQNIC_QUEUE_ACTIVE_MASK) != 0; - if (!active && !verbose) + if (!enable && !verbose) continue; - uint64_t base_addr = (uint64_t)mqnic_reg_read32(base, MQNIC_QUEUE_BASE_ADDR_REG) + ((uint64_t)mqnic_reg_read32(base, MQNIC_QUEUE_BASE_ADDR_REG+4) << 32); - uint8_t log_desc_block_size = (mqnic_reg_read32(base, MQNIC_QUEUE_ACTIVE_LOG_SIZE_REG) >> 8) & 0xff; - uint8_t log_queue_size = mqnic_reg_read32(base, MQNIC_QUEUE_ACTIVE_LOG_SIZE_REG) & 0xff; - uint32_t cpl_queue_index = mqnic_reg_read32(base, MQNIC_QUEUE_CPL_QUEUE_INDEX_REG); - uint32_t head_ptr = mqnic_reg_read32(base, MQNIC_QUEUE_HEAD_PTR_REG); - uint32_t tail_ptr = mqnic_reg_read32(base, MQNIC_QUEUE_TAIL_PTR_REG); - uint32_t occupancy = (head_ptr - tail_ptr) & 0xffff; + uint64_t base_addr = (uint64_t)mqnic_reg_read32(base, MQNIC_QUEUE_BASE_ADDR_VF_REG) + ((uint64_t)mqnic_reg_read32(base, MQNIC_QUEUE_BASE_ADDR_VF_REG+4) << 32); + base_addr &= 0xfffffffffffff000; + val = mqnic_reg_read32(base, MQNIC_QUEUE_SIZE_CQN_REG); + uint32_t cqn = val & 0xffffff; + uint8_t log_queue_size = (val >> 24) & 0xf; + uint8_t log_desc_block_size = (val >> 28) & 0xf; + val = mqnic_reg_read32(base, MQNIC_QUEUE_PTR_REG); + uint32_t prod_ptr = val & MQNIC_QUEUE_PTR_MASK; + uint32_t cons_ptr = (val >> 16) & MQNIC_QUEUE_PTR_MASK; + uint32_t occupancy = (prod_ptr - cons_ptr) & MQNIC_QUEUE_PTR_MASK; - printf("TXQ %4d 0x%016lx %d %d %2d %4d %6d %6d %6d\n", k, base_addr, active, log_desc_block_size, log_queue_size, cpl_queue_index, head_ptr, tail_ptr, occupancy); + printf("TXQ %4d 0x%016lx %d %d %d %2d %4d %6d %6d %6d\n", k, base_addr, enable, active, log_desc_block_size, log_queue_size, cqn, prod_ptr, cons_ptr, occupancy); } printf("TX CQ info\n"); - printf(" Queue Base Address E LS A C Int Head Tail Len\n"); + printf(" Queue Base Address En A LS A EQN Prod Cons Len\n"); for (int k = 0; k < mqnic_res_get_count(dev_interface->tx_cq_res); k++) { + uint32_t val; volatile uint8_t *base = mqnic_res_get_addr(dev_interface->tx_cq_res, k); - uint8_t active = (mqnic_reg_read32(base, MQNIC_CQ_ACTIVE_LOG_SIZE_REG) & MQNIC_CQ_ACTIVE_MASK) != 0; + val = mqnic_reg_read32(base, MQNIC_CQ_CTRL_STATUS_REG); + uint32_t eqn = val & 0xffff; + uint8_t enable = (val & MQNIC_CQ_ENABLE_MASK) != 0; + uint8_t armed = (val & MQNIC_CQ_ARM_MASK) != 0; + uint8_t active = (val & MQNIC_CQ_ACTIVE_MASK) != 0; + uint8_t log_queue_size = (val >> 28) & 0xf; - if (!active && !verbose) + if (!enable && !verbose) continue; - uint64_t base_addr = (uint64_t)mqnic_reg_read32(base, MQNIC_CQ_BASE_ADDR_REG) + ((uint64_t)mqnic_reg_read32(base, MQNIC_CQ_BASE_ADDR_REG+4) << 32); - uint8_t log_queue_size = mqnic_reg_read32(base, MQNIC_CQ_ACTIVE_LOG_SIZE_REG) & 0xff; - uint8_t armed = (mqnic_reg_read32(base, MQNIC_CQ_INTERRUPT_INDEX_REG) & MQNIC_CQ_ARM_MASK) != 0; - uint8_t continuous = (mqnic_reg_read32(base, MQNIC_CQ_INTERRUPT_INDEX_REG) & MQNIC_CQ_CONT_MASK) != 0; - uint32_t interrupt_index = mqnic_reg_read32(base, MQNIC_CQ_INTERRUPT_INDEX_REG) & 0xffff; - uint32_t head_ptr = mqnic_reg_read32(base, MQNIC_CQ_HEAD_PTR_REG); - uint32_t tail_ptr = mqnic_reg_read32(base, MQNIC_CQ_TAIL_PTR_REG); - uint32_t occupancy = (head_ptr - tail_ptr) & 0xffff; + uint64_t base_addr = (uint64_t)mqnic_reg_read32(base, MQNIC_CQ_BASE_ADDR_VF_REG) + ((uint64_t)mqnic_reg_read32(base, MQNIC_CQ_BASE_ADDR_VF_REG+4) << 32); + base_addr &= 0xfffffffffffff000; + val = mqnic_reg_read32(base, MQNIC_CQ_PTR_REG); + uint32_t prod_ptr = val & MQNIC_CQ_PTR_MASK; + uint32_t cons_ptr = (val >> 16) & MQNIC_CQ_PTR_MASK; + uint32_t occupancy = (prod_ptr - cons_ptr) & MQNIC_CQ_PTR_MASK; - printf("TX CQ %4d 0x%016lx %d %2d %d %d %4d %6d %6d %6d\n", k, base_addr, active, log_queue_size, armed, continuous, interrupt_index, head_ptr, tail_ptr, occupancy); + printf("TXCQ %4d 0x%016lx %d %d %2d %d %4d %6d %6d %6d\n", k, base_addr, enable, active, log_queue_size, armed, eqn, prod_ptr, cons_ptr, occupancy); } printf("RXQ info\n"); - printf(" Queue Base Address E B LS CPL Head Tail Len\n"); + printf(" Queue Base Address En A B LS CQN Prod Cons Len\n"); for (int k = 0; k < mqnic_res_get_count(dev_interface->rxq_res); k++) { + uint32_t val; volatile uint8_t *base = mqnic_res_get_addr(dev_interface->rxq_res, k); - uint8_t active = (mqnic_reg_read32(base, MQNIC_QUEUE_ACTIVE_LOG_SIZE_REG) & MQNIC_QUEUE_ACTIVE_MASK) != 0; + val = mqnic_reg_read32(base, MQNIC_QUEUE_CTRL_STATUS_REG); + uint8_t enable = (val & MQNIC_QUEUE_ENABLE_MASK) != 0; + uint8_t active = (val & MQNIC_QUEUE_ACTIVE_MASK) != 0; - if (!active && !verbose) + if (!enable && !verbose) continue; - uint64_t base_addr = (uint64_t)mqnic_reg_read32(base, MQNIC_QUEUE_BASE_ADDR_REG) + ((uint64_t)mqnic_reg_read32(base, MQNIC_QUEUE_BASE_ADDR_REG+4) << 32); - uint8_t log_desc_block_size = (mqnic_reg_read32(base, MQNIC_QUEUE_ACTIVE_LOG_SIZE_REG) >> 8) & 0xff; - uint8_t log_queue_size = mqnic_reg_read32(base, MQNIC_QUEUE_ACTIVE_LOG_SIZE_REG) & 0xff; - uint32_t cpl_queue_index = mqnic_reg_read32(base, MQNIC_QUEUE_CPL_QUEUE_INDEX_REG); - uint32_t head_ptr = mqnic_reg_read32(base, MQNIC_QUEUE_HEAD_PTR_REG); - uint32_t tail_ptr = mqnic_reg_read32(base, MQNIC_QUEUE_TAIL_PTR_REG); - uint32_t occupancy = (head_ptr - tail_ptr) & 0xffff; + uint64_t base_addr = (uint64_t)mqnic_reg_read32(base, MQNIC_QUEUE_BASE_ADDR_VF_REG) + ((uint64_t)mqnic_reg_read32(base, MQNIC_QUEUE_BASE_ADDR_VF_REG+4) << 32); + base_addr &= 0xfffffffffffff000; + val = mqnic_reg_read32(base, MQNIC_QUEUE_SIZE_CQN_REG); + uint32_t cqn = val & 0xffffff; + uint8_t log_queue_size = (val >> 24) & 0xf; + uint8_t log_desc_block_size = (val >> 28) & 0xf; + val = mqnic_reg_read32(base, MQNIC_QUEUE_PTR_REG); + uint32_t prod_ptr = val & MQNIC_QUEUE_PTR_MASK; + uint32_t cons_ptr = (val >> 16) & MQNIC_QUEUE_PTR_MASK; + uint32_t occupancy = (prod_ptr - cons_ptr) & MQNIC_QUEUE_PTR_MASK; - printf("RXQ %4d 0x%016lx %d %d %2d %4d %6d %6d %6d\n", k, base_addr, active, log_desc_block_size, log_queue_size, cpl_queue_index, head_ptr, tail_ptr, occupancy); + printf("RXQ %4d 0x%016lx %d %d %d %2d %4d %6d %6d %6d\n", k, base_addr, enable, active, log_desc_block_size, log_queue_size, cqn, prod_ptr, cons_ptr, occupancy); } printf("RX CQ info\n"); - printf(" Queue Base Address E LS A C Int Head Tail Len\n"); + printf(" Queue Base Address En A LS A EQN Prod Cons Len\n"); for (int k = 0; k < mqnic_res_get_count(dev_interface->rx_cq_res); k++) { + uint32_t val; volatile uint8_t *base = mqnic_res_get_addr(dev_interface->rx_cq_res, k); - uint8_t active = (mqnic_reg_read32(base, MQNIC_CQ_ACTIVE_LOG_SIZE_REG) & MQNIC_CQ_ACTIVE_MASK) != 0; + val = mqnic_reg_read32(base, MQNIC_CQ_CTRL_STATUS_REG); + uint32_t eqn = val & 0xffff; + uint8_t enable = (val & MQNIC_CQ_ENABLE_MASK) != 0; + uint8_t armed = (val & MQNIC_CQ_ARM_MASK) != 0; + uint8_t active = (val & MQNIC_CQ_ACTIVE_MASK) != 0; + uint8_t log_queue_size = (val >> 28) & 0xf; - if (!active && !verbose) + if (!enable && !verbose) continue; - uint64_t base_addr = (uint64_t)mqnic_reg_read32(base, MQNIC_CQ_BASE_ADDR_REG) + ((uint64_t)mqnic_reg_read32(base, MQNIC_CQ_BASE_ADDR_REG+4) << 32); - uint8_t log_queue_size = mqnic_reg_read32(base, MQNIC_CQ_ACTIVE_LOG_SIZE_REG) & 0xff; - uint8_t armed = (mqnic_reg_read32(base, MQNIC_CQ_INTERRUPT_INDEX_REG) & MQNIC_CQ_ARM_MASK) != 0; - uint8_t continuous = (mqnic_reg_read32(base, MQNIC_CQ_INTERRUPT_INDEX_REG) & MQNIC_CQ_CONT_MASK) != 0; - uint32_t interrupt_index = mqnic_reg_read32(base, MQNIC_CQ_INTERRUPT_INDEX_REG) & 0xffff; - uint32_t head_ptr = mqnic_reg_read32(base, MQNIC_CQ_HEAD_PTR_REG); - uint32_t tail_ptr = mqnic_reg_read32(base, MQNIC_CQ_TAIL_PTR_REG); - uint32_t occupancy = (head_ptr - tail_ptr) & 0xffff; + uint64_t base_addr = (uint64_t)mqnic_reg_read32(base, MQNIC_CQ_BASE_ADDR_VF_REG) + ((uint64_t)mqnic_reg_read32(base, MQNIC_CQ_BASE_ADDR_VF_REG+4) << 32); + base_addr &= 0xfffffffffffff000; + val = mqnic_reg_read32(base, MQNIC_CQ_PTR_REG); + uint32_t prod_ptr = val & MQNIC_CQ_PTR_MASK; + uint32_t cons_ptr = (val >> 16) & MQNIC_CQ_PTR_MASK; + uint32_t occupancy = (prod_ptr - cons_ptr) & MQNIC_CQ_PTR_MASK; - printf("RX CQ %4d 0x%016lx %d %2d %d %d %4d %6d %6d %6d\n", k, base_addr, active, log_queue_size, armed, continuous, interrupt_index, head_ptr, tail_ptr, occupancy); + printf("RXCQ %4d 0x%016lx %d %d %2d %d %4d %6d %6d %6d\n", k, base_addr, enable, active, log_queue_size, armed, eqn, prod_ptr, cons_ptr, occupancy); } printf("EQ info\n"); - printf(" Queue Base Address E LS A C Int Head Tail Len\n"); + printf(" Queue Base Address En A LS A IRQ Prod Cons Len\n"); for (int k = 0; k < mqnic_res_get_count(dev_interface->eq_res); k++) { + uint32_t val; volatile uint8_t *base = mqnic_res_get_addr(dev_interface->eq_res, k); - uint8_t active = (mqnic_reg_read32(base, MQNIC_EQ_ACTIVE_LOG_SIZE_REG) & MQNIC_EQ_ACTIVE_MASK) != 0; + val = mqnic_reg_read32(base, MQNIC_EQ_CTRL_STATUS_REG); + uint32_t irq = val & 0xffff; + uint8_t enable = (val & MQNIC_EQ_ENABLE_MASK) != 0; + uint8_t armed = (val & MQNIC_EQ_ARM_MASK) != 0; + uint8_t active = (val & MQNIC_EQ_ACTIVE_MASK) != 0; + uint8_t log_queue_size = (val >> 28) & 0xf; - if (!active && !verbose) + if (!enable && !verbose) continue; - uint64_t base_addr = (uint64_t)mqnic_reg_read32(base, MQNIC_EQ_BASE_ADDR_REG) + ((uint64_t)mqnic_reg_read32(base, MQNIC_EQ_BASE_ADDR_REG+4) << 32); - uint8_t log_queue_size = mqnic_reg_read32(base, MQNIC_EQ_ACTIVE_LOG_SIZE_REG) & 0xff; - uint8_t armed = (mqnic_reg_read32(base, MQNIC_EQ_INTERRUPT_INDEX_REG) & MQNIC_EQ_ARM_MASK) != 0; - uint8_t continuous = (mqnic_reg_read32(base, MQNIC_EQ_INTERRUPT_INDEX_REG) & MQNIC_EQ_CONT_MASK) != 0; - uint32_t interrupt_index = mqnic_reg_read32(base, MQNIC_EQ_INTERRUPT_INDEX_REG) & 0xffff; - uint32_t head_ptr = mqnic_reg_read32(base, MQNIC_EQ_HEAD_PTR_REG); - uint32_t tail_ptr = mqnic_reg_read32(base, MQNIC_EQ_TAIL_PTR_REG); - uint32_t occupancy = (head_ptr - tail_ptr) & 0xffff; + uint64_t base_addr = (uint64_t)mqnic_reg_read32(base, MQNIC_EQ_BASE_ADDR_VF_REG) + ((uint64_t)mqnic_reg_read32(base, MQNIC_EQ_BASE_ADDR_VF_REG+4) << 32); + base_addr &= 0xfffffffffffff000; + val = mqnic_reg_read32(base, MQNIC_EQ_PTR_REG); + uint32_t prod_ptr = val & MQNIC_EQ_PTR_MASK; + uint32_t cons_ptr = (val >> 16) & MQNIC_EQ_PTR_MASK; + uint32_t occupancy = (prod_ptr - cons_ptr) & MQNIC_EQ_PTR_MASK; - printf("EQ %4d 0x%016lx %d %2d %d %d %4d %6d %6d %6d\n", k, base_addr, active, log_queue_size, armed, continuous, interrupt_index, head_ptr, tail_ptr, occupancy); + printf("EQ %4d 0x%016lx %d %d %2d %d %4d %6d %6d %6d\n", k, base_addr, enable, active, log_queue_size, armed, irq, prod_ptr, cons_ptr, occupancy); } if (verbose)