1
0
mirror of https://github.com/corundum/corundum.git synced 2025-01-16 08:12:53 +08:00

Reorganize queue control registers

Signed-off-by: Alex Forencich <alex@alexforencich.com>
This commit is contained in:
Alex Forencich 2023-07-07 01:19:19 -07:00
parent 56c89640e0
commit 265035769a
21 changed files with 1734 additions and 816 deletions

View File

@ -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
====================== ======

View File

@ -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
====================== ======

View File

@ -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
====================== ======

View File

@ -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
====================== ======

View File

@ -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
====================== ======

View File

@ -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

View File

@ -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

View File

@ -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

View File

@ -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)

View File

@ -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()}

View File

@ -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("<HHLLLLLLL", self.buf, eq_index*self.stride)
self.log.info("EQ %d index %d data: %s", self.eqn, eq_index, repr(event_data))
if bool(event_data[-1] & 0x80000000) == bool(eq_tail_ptr & self.size):
if bool(event_data[-1] & 0x80000000) == bool(eq_cons_ptr & self.size):
self.log.info("EQ %d empty", self.eqn)
break
@ -516,11 +543,11 @@ class Eq:
await cq.handler(cq)
await cq.arm()
eq_tail_ptr += 1
eq_index = eq_tail_ptr & self.size_mask
eq_cons_ptr += 1
eq_index = eq_cons_ptr & self.size_mask
self.tail_ptr = eq_tail_ptr
await self.write_tail_ptr()
self.cons_ptr = eq_cons_ptr
await self.write_cons_ptr()
class Cq:
@ -545,10 +572,9 @@ class Cq:
self.src_ring = None
self.handler = None
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, eq, size, is_txcq=True):
@ -575,8 +601,8 @@ class Cq:
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
eq.attach_cq(self)
self.eq = eq
@ -586,13 +612,14 @@ class Cq:
else:
self.hw_regs = self.interface.rx_cq_res.get_window(self.cqn)
await self.hw_regs.write_dword(MQNIC_CQ_ACTIVE_LOG_SIZE_REG, 0) # active, log size
await self.hw_regs.write_dword(MQNIC_CQ_BASE_ADDR_REG, self.buf_dma & 0xffffffff) # base address
await self.hw_regs.write_dword(MQNIC_CQ_BASE_ADDR_REG+4, self.buf_dma >> 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("<HHHxxLHHLBBHLL", cq.buf, cq_index*cq.stride)
@ -785,7 +810,7 @@ class Txq:
interface.log.info("CQ %d index %d data: %s", cq.cqn, cq_index, repr(cpl_data))
if bool(cpl_data[-1] & 0x80000000) == bool(cq_tail_ptr & cq.size):
if bool(cpl_data[-1] & 0x80000000) == bool(cq_cons_ptr & cq.size):
interface.log.info("CQ %d empty", cq.cqn)
break
@ -793,24 +818,24 @@ class Txq:
ring.free_desc(ring_index)
cq_tail_ptr += 1
cq_index = cq_tail_ptr & cq.size_mask
cq_cons_ptr += 1
cq_index = cq_cons_ptr & cq.size_mask
cq.tail_ptr = cq_tail_ptr
await cq.write_tail_ptr()
cq.cons_ptr = cq_cons_ptr
await cq.write_cons_ptr()
# process ring
ring_tail_ptr = ring.tail_ptr
ring_index = ring_tail_ptr & ring.size_mask
ring_cons_ptr = ring.cons_ptr
ring_index = ring_cons_ptr & ring.size_mask
while (ring_tail_ptr != ring.head_ptr):
while (ring_cons_ptr != ring.prod_ptr):
if ring.tx_info[ring_index]:
break
ring_tail_ptr += 1
ring_index = ring_tail_ptr & ring.size_mask
ring_cons_ptr += 1
ring_index = ring_cons_ptr & ring.size_mask
ring.tail_ptr = ring_tail_ptr
ring.cons_ptr = ring_cons_ptr
ring.clean_event.set()
@ -837,13 +862,12 @@ class Rxq:
self.cq = None
self.head_ptr = 0
self.tail_ptr = 0
self.prod_ptr = 0
self.cons_ptr = 0
self.packets = 0
self.bytes = 0
self.hw_ptr_mask = 0xffff
self.hw_regs = None
async def open(self, cq, size, desc_block_size):
@ -869,8 +893,8 @@ class Rxq:
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
@ -878,13 +902,13 @@ class Rxq:
self.hw_regs = self.interface.rxq_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))
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("<HHHxxLHHLBBHLL", cq.buf, cq_index*cq.stride)
@ -994,7 +1018,7 @@ class Rxq:
interface.log.info("CQ %d index %d data: %s", cq.cqn, cq_index, repr(cpl_data))
if bool(cpl_data[-1] & 0x80000000) == bool(cq_tail_ptr & cq.size):
if bool(cpl_data[-1] & 0x80000000) == bool(cq_cons_ptr & cq.size):
interface.log.info("CQ %d empty", cq.cqn)
break
@ -1017,24 +1041,24 @@ class Rxq:
ring.free_desc(ring_index)
cq_tail_ptr += 1
cq_index = cq_tail_ptr & cq.size_mask
cq_cons_ptr += 1
cq_index = cq_cons_ptr & cq.size_mask
cq.tail_ptr = cq_tail_ptr
await cq.write_tail_ptr()
cq.cons_ptr = cq_cons_ptr
await cq.write_cons_ptr()
# process ring
ring_tail_ptr = ring.tail_ptr
ring_index = ring_tail_ptr & ring.size_mask
ring_cons_ptr = ring.cons_ptr
ring_index = ring_cons_ptr & ring.size_mask
while (ring_tail_ptr != ring.head_ptr):
while (ring_cons_ptr != ring.prod_ptr):
if ring.rx_info[ring_index]:
break
ring_tail_ptr += 1
ring_index = ring_tail_ptr & ring.size_mask
ring_cons_ptr += 1
ring_index = ring_cons_ptr & ring.size_mask
ring.tail_ptr = ring_tail_ptr
ring.cons_ptr = ring_cons_ptr
# replenish buffers
await ring.refill_buffers()
@ -1313,19 +1337,19 @@ class Interface:
# ensure all queues are disabled
for k in range(self.eq_res.get_count()):
await self.eq_res.get_window(k).write_dword(MQNIC_EQ_ACTIVE_LOG_SIZE_REG, 0)
await self.eq_res.get_window(k).write_dword(MQNIC_EQ_CTRL_STATUS_REG, MQNIC_QUEUE_CMD_SET_ENABLE | 0)
for k in range(self.txq_res.get_count()):
await self.txq_res.get_window(k).write_dword(MQNIC_QUEUE_ACTIVE_LOG_SIZE_REG, 0)
await self.txq_res.get_window(k).write_dword(MQNIC_QUEUE_CTRL_STATUS_REG, MQNIC_QUEUE_CMD_SET_ENABLE | 0)
for k in range(self.tx_cq_res.get_count()):
await self.tx_cq_res.get_window(k).write_dword(MQNIC_CQ_ACTIVE_LOG_SIZE_REG, 0)
await self.tx_cq_res.get_window(k).write_dword(MQNIC_CQ_CTRL_STATUS_REG, MQNIC_QUEUE_CMD_SET_ENABLE | 0)
for k in range(self.rxq_res.get_count()):
await self.rxq_res.get_window(k).write_dword(MQNIC_QUEUE_ACTIVE_LOG_SIZE_REG, 0)
await self.rxq_res.get_window(k).write_dword(MQNIC_QUEUE_CTRL_STATUS_REG, MQNIC_QUEUE_CMD_SET_ENABLE | 0)
for k in range(self.rx_cq_res.get_count()):
await self.rx_cq_res.get_window(k).write_dword(MQNIC_CQ_ACTIVE_LOG_SIZE_REG, 0)
await self.rx_cq_res.get_window(k).write_dword(MQNIC_CQ_CTRL_STATUS_REG, MQNIC_QUEUE_CMD_SET_ENABLE | 0)
# create ports
self.ports = []
@ -1430,14 +1454,14 @@ class Interface:
while True:
# check for space in ring
if ring.head_ptr - ring.tail_ptr < ring.full_size:
if ring.prod_ptr - ring.cons_ptr < ring.full_size:
break
# wait for space
ring.clean_event.clear()
await ring.clean_event.wait()
index = ring.head_ptr & ring.size_mask
index = ring.prod_ptr & ring.size_mask
ring.packets += 1
ring.bytes += len(data)
@ -1468,9 +1492,9 @@ class Interface:
struct.pack_into("<4xLQ", ring.buf, index*ring.stride+k*MQNIC_DESC_SIZE, seg, ptr+offset if seg else 0)
offset += seg
ring.head_ptr += 1
ring.prod_ptr += 1
await ring.write_head_ptr()
await ring.write_prod_ptr()
async def set_mtu(self, mtu):
await self.if_ctrl_rb.write_dword(MQNIC_RB_IF_CTRL_REG_TX_MTU, mtu)

View File

@ -27,7 +27,7 @@ export PARAM_DESC_SIZE := 16
export PARAM_LOG_BLOCK_SIZE_WIDTH := 2
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) + 5 )
export PARAM_AXIL_STRB_WIDTH := $(shell expr $(PARAM_AXIL_DATA_WIDTH) / 8 )
ifeq ($(SIM), icarus)

View File

@ -76,6 +76,25 @@ class TB(object):
await RisingEdge(self.dut.clk)
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_ENABLE_MASK = 0x00000001
MQNIC_QUEUE_ACTIVE_MASK = 0x00000008
MQNIC_QUEUE_PTR_MASK = 0xFFFF
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
async def run_test(dut):
OP_TABLE_SIZE = int(os.getenv("PARAM_OP_TABLE_SIZE"))
@ -88,24 +107,26 @@ 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, 0x00000001) # completion queue index
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*32+MQNIC_QUEUE_CTRL_STATUS_REG, MQNIC_QUEUE_CMD_SET_ENABLE | 0)
await tb.axil_master.write_qword(0*32+MQNIC_QUEUE_BASE_ADDR_VF_REG, 0x8877665544332000)
await tb.axil_master.write_dword(0*32+MQNIC_QUEUE_CTRL_STATUS_REG, MQNIC_QUEUE_CMD_SET_VF_ID | 0)
await tb.axil_master.write_dword(0*32+MQNIC_QUEUE_CTRL_STATUS_REG, MQNIC_QUEUE_CMD_SET_SIZE | 4)
await tb.axil_master.write_dword(0*32+MQNIC_QUEUE_CTRL_STATUS_REG, MQNIC_QUEUE_CMD_SET_CQN | 1)
await tb.axil_master.write_dword(0*32+MQNIC_QUEUE_CTRL_STATUS_REG, MQNIC_QUEUE_CMD_SET_PROD_PTR | 0)
await tb.axil_master.write_dword(0*32+MQNIC_QUEUE_CTRL_STATUS_REG, MQNIC_QUEUE_CMD_SET_CONS_PTR | 0)
await tb.axil_master.write_dword(0*32+MQNIC_QUEUE_CTRL_STATUS_REG, MQNIC_QUEUE_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) == 0x00000001
assert await tb.axil_master.read_qword(0*32+MQNIC_QUEUE_BASE_ADDR_VF_REG) == 0x8877665544332000
assert await tb.axil_master.read_dword(0*32+MQNIC_QUEUE_CTRL_STATUS_REG) == MQNIC_QUEUE_ENABLE_MASK
assert await tb.axil_master.read_dword(0*32+MQNIC_QUEUE_SIZE_CQN_REG) == 0x04000001
tb.log.info("Test enqueue and dequeue")
# increment head pointer
head_ptr = await tb.axil_master.read_dword(0*32+16) # head pointer
head_ptr += 1
tb.log.info("Head pointer: %d", head_ptr)
await tb.axil_master.write_dword(0*32+16, head_ptr) # head pointer
# increment producer pointer
prod_ptr = (await tb.axil_master.read_dword(0*32+MQNIC_QUEUE_PTR_REG)) & MQNIC_QUEUE_PTR_MASK
prod_ptr += 1
tb.log.info("Producer pointer: %d", prod_ptr)
await tb.axil_master.write_dword(0*32+MQNIC_QUEUE_CTRL_STATUS_REG, MQNIC_QUEUE_CMD_SET_PROD_PTR | prod_ptr)
# check for doorbell
db = await tb.doorbell_sink.recv()
@ -113,9 +134,9 @@ async def run_test(dut):
assert db.queue == 0
# read tail pointer
tail_ptr = await tb.axil_master.read_dword(0*32+24) # tail pointer
tb.log.info("Tail pointer: %d", tail_ptr)
# read consumer pointer
cons_ptr = (await tb.axil_master.read_dword(0*32+MQNIC_QUEUE_PTR_REG)) >> 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()}

View File

@ -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);

View File

@ -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);
}

View File

@ -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);
}

View File

@ -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

View File

@ -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++) {

View File

@ -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);

View File

@ -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);

View File

@ -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)