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:
parent
56c89640e0
commit
265035769a
@ -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
|
||||
====================== ======
|
||||
|
@ -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
|
||||
====================== ======
|
||||
|
@ -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
|
||||
====================== ======
|
||||
|
@ -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
|
||||
====================== ======
|
||||
|
@ -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
|
||||
====================== ======
|
||||
|
@ -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
|
||||
|
@ -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
|
||||
|
@ -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
|
||||
|
@ -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)
|
||||
|
@ -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()}
|
||||
|
@ -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)
|
||||
|
@ -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)
|
||||
|
@ -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()}
|
||||
|
@ -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);
|
||||
|
@ -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);
|
||||
}
|
||||
|
@ -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);
|
||||
}
|
||||
|
@ -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
|
||||
|
@ -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++) {
|
||||
|
@ -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);
|
||||
|
@ -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);
|
||||
|
@ -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)
|
||||
|
Loading…
x
Reference in New Issue
Block a user