@@ -25,6 +25,18 @@
/* AQM Virtual Function Registers */
#define AQMQ_QSZX(_i) (0x20008UL + ((_i) * 0x40000UL))
+/* ZQM virtual function registers */
+#define ZQMQ_DRBLX(_i) (0x30000UL + ((_i) * 0x40000UL))
+#define ZQMQ_QSZX(_i) (0x30008UL + ((_i) * 0x40000UL))
+#define ZQMQ_BADRX(_i) (0x30010UL + ((_i) * 0x40000UL))
+#define ZQMQ_NXT_CMDX(_i) (0x30018UL + ((_i) * 0x40000UL))
+#define ZQMQ_CMD_CNTX(_i) (0x30020UL + ((_i) * 0x40000UL))
+#define ZQMQ_CMP_THRX(_i) (0x30028UL + ((_i) * 0x40000UL))
+#define ZQMQ_CMP_CNTX(_i) (0x30030UL + ((_i) * 0x40000UL))
+#define ZQMQ_TIM_LDX(_i) (0x30038UL + ((_i) * 0x40000UL))
+#define ZQMQ_ENX(_i) (0x30048UL + ((_i) * 0x40000UL))
+#define ZQMQ_ACTIVITY_STATX(_i) (0x30050UL + ((_i) * 0x40000UL))
+
static inline uint64_t
nitrox_read_csr(uint8_t *bar_addr, uint64_t offset)
{
@@ -9,6 +9,7 @@
#include "nitrox_hal.h"
#include "nitrox_csr.h"
+#include "nitrox_logs.h"
#define MAX_VF_QUEUES 8
#define MAX_PF_QUEUES 64
@@ -164,6 +165,121 @@ setup_nps_pkt_solicit_output_port(uint8_t *bar_addr, uint16_t port)
}
}
+int
+zqmq_input_ring_disable(uint8_t *bar_addr, uint16_t ring)
+{
+ union zqmq_activity_stat zqmq_activity_stat;
+ union zqmq_en zqmq_en;
+ union zqmq_cmp_cnt zqmq_cmp_cnt;
+ uint64_t reg_addr;
+ int max_retries = 5;
+
+ /* clear queue enable */
+ reg_addr = ZQMQ_ENX(ring);
+ zqmq_en.u64 = nitrox_read_csr(bar_addr, reg_addr);
+ zqmq_en.s.queue_enable = 0;
+ nitrox_write_csr(bar_addr, reg_addr, zqmq_en.u64);
+ rte_delay_us_block(100);
+
+ /* wait for queue active to clear */
+ reg_addr = ZQMQ_ACTIVITY_STATX(ring);
+ zqmq_activity_stat.u64 = nitrox_read_csr(bar_addr, reg_addr);
+ while (zqmq_activity_stat.s.queue_active && max_retries--) {
+ rte_delay_ms(10);
+ zqmq_activity_stat.u64 = nitrox_read_csr(bar_addr, reg_addr);
+ }
+
+ if (zqmq_activity_stat.s.queue_active) {
+ NITROX_LOG(ERR, "Failed to disable zqmq ring %d\n", ring);
+ return -EBUSY;
+ }
+
+ /* clear commands completed count */
+ reg_addr = ZQMQ_CMP_CNTX(ring);
+ zqmq_cmp_cnt.u64 = nitrox_read_csr(bar_addr, reg_addr);
+ nitrox_write_csr(bar_addr, reg_addr, zqmq_cmp_cnt.u64);
+ rte_delay_us_block(CSR_DELAY);
+ return 0;
+}
+
+int
+setup_zqmq_input_ring(uint8_t *bar_addr, uint16_t ring, uint32_t rsize,
+ phys_addr_t raddr)
+{
+ union zqmq_drbl zqmq_drbl;
+ union zqmq_qsz zqmq_qsz;
+ union zqmq_en zqmq_en;
+ union zqmq_cmp_thr zqmq_cmp_thr;
+ union zqmq_tim_ld zqmq_tim_ld;
+ uint64_t reg_addr = 0;
+ int max_retries = 5;
+ int err = 0;
+
+ err = zqmq_input_ring_disable(bar_addr, ring);
+ if (err)
+ return err;
+
+ /* clear doorbell count */
+ reg_addr = ZQMQ_DRBLX(ring);
+ zqmq_drbl.u64 = 0;
+ zqmq_drbl.s.dbell_count = 0xFFFFFFFF;
+ nitrox_write_csr(bar_addr, reg_addr, zqmq_drbl.u64);
+ rte_delay_us_block(CSR_DELAY);
+
+ reg_addr = ZQMQ_NXT_CMDX(ring);
+ nitrox_write_csr(bar_addr, reg_addr, 0);
+ rte_delay_us_block(CSR_DELAY);
+
+ /* write queue length */
+ reg_addr = ZQMQ_QSZX(ring);
+ zqmq_qsz.u64 = 0;
+ zqmq_qsz.s.host_queue_size = rsize;
+ nitrox_write_csr(bar_addr, reg_addr, zqmq_qsz.u64);
+ rte_delay_us_block(CSR_DELAY);
+
+ /* write queue base address */
+ reg_addr = ZQMQ_BADRX(ring);
+ nitrox_write_csr(bar_addr, reg_addr, raddr);
+ rte_delay_us_block(CSR_DELAY);
+
+ /* write commands completed threshold */
+ reg_addr = ZQMQ_CMP_THRX(ring);
+ zqmq_cmp_thr.u64 = 0;
+ zqmq_cmp_thr.s.commands_completed_threshold = 0;
+ nitrox_write_csr(bar_addr, reg_addr, zqmq_cmp_thr.u64);
+ rte_delay_us_block(CSR_DELAY);
+
+ /* write timer load value */
+ reg_addr = ZQMQ_TIM_LDX(ring);
+ zqmq_tim_ld.u64 = 0;
+ zqmq_tim_ld.s.timer_load_value = 0;
+ nitrox_write_csr(bar_addr, reg_addr, zqmq_tim_ld.u64);
+ rte_delay_us_block(CSR_DELAY);
+
+ reg_addr = ZQMQ_ENX(ring);
+ zqmq_en.u64 = nitrox_read_csr(bar_addr, reg_addr);
+ zqmq_en.s.queue_enable = 1;
+ nitrox_write_csr(bar_addr, reg_addr, zqmq_en.u64);
+ rte_delay_us_block(100);
+
+ /* enable queue */
+ zqmq_en.u64 = 0;
+ zqmq_en.u64 = nitrox_read_csr(bar_addr, reg_addr);
+ while (!zqmq_en.s.queue_enable && max_retries--) {
+ rte_delay_ms(10);
+ zqmq_en.u64 = nitrox_read_csr(bar_addr, reg_addr);
+ }
+
+ if (!zqmq_en.s.queue_enable) {
+ NITROX_LOG(ERR, "Failed to enable zqmq ring %d\n", ring);
+ err = -EFAULT;
+ } else {
+ err = 0;
+ }
+
+ return err;
+}
+
int
vf_get_vf_config_mode(uint8_t *bar_addr)
{
@@ -146,6 +146,101 @@ union aqmq_qsz {
} s;
};
+union zqmq_activity_stat {
+ uint64_t u64;
+ struct {
+#if RTE_BYTE_ORDER == RTE_BIG_ENDIAN
+ uint64_t raz : 63;
+ uint64_t queue_active : 1;
+#else
+ uint64_t queue_active : 1;
+ uint64_t raz : 63;
+#endif
+ } s;
+};
+
+union zqmq_en {
+ uint64_t u64;
+ struct {
+#if RTE_BYTE_ORDER == RTE_BIG_ENDIAN
+ uint64_t raz : 63;
+ uint64_t queue_enable : 1;
+#else
+ uint64_t queue_enable : 1;
+ uint64_t raz : 63;
+#endif
+ } s;
+};
+
+union zqmq_cmp_cnt {
+ uint64_t u64;
+ struct {
+#if RTE_BYTE_ORDER == RTE_BIG_ENDIAN
+ uint64_t raz : 30;
+ uint64_t resend : 1;
+ uint64_t completion_status : 1;
+ uint64_t commands_completed_count: 32;
+#else
+ uint64_t commands_completed_count: 32;
+ uint64_t completion_status : 1;
+ uint64_t resend : 1;
+ uint64_t raz : 30;
+#endif
+ } s;
+};
+
+union zqmq_drbl {
+ uint64_t u64;
+ struct {
+#if RTE_BYTE_ORDER == RTE_BIG_ENDIAN
+ uint64_t raz : 32;
+ uint64_t dbell_count : 32;
+#else
+ uint64_t dbell_count : 32;
+ uint64_t raz : 32;
+#endif
+ } s;
+};
+
+union zqmq_qsz {
+ uint64_t u64;
+ struct {
+#if RTE_BYTE_ORDER == RTE_BIG_ENDIAN
+ uint64_t raz : 32;
+ uint64_t host_queue_size: 32;
+#else
+ uint64_t host_queue_size: 32;
+ uint64_t raz : 32;
+#endif
+ } s;
+};
+
+union zqmq_cmp_thr {
+ uint64_t u64;
+ struct {
+#if RTE_BYTE_ORDER == RTE_BIG_ENDIAN
+ uint64_t raz : 32;
+ uint64_t commands_completed_threshold : 32;
+#else
+ uint64_t commands_completed_threshold : 32;
+ uint64_t raz : 32;
+#endif
+ } s;
+};
+
+union zqmq_tim_ld {
+ uint64_t u64;
+ struct {
+#if RTE_BYTE_ORDER == RTE_BIG_ENDIAN
+ uint64_t raz : 32;
+ uint64_t timer_load_value: 32;
+#else
+ uint64_t timer_load_value: 32;
+ uint64_t raz : 32;
+#endif
+ } s;
+};
+
enum nitrox_vf_mode {
NITROX_MODE_PF = 0x0,
NITROX_MODE_VF16 = 0x1,
@@ -154,6 +249,23 @@ enum nitrox_vf_mode {
NITROX_MODE_VF128 = 0x4,
};
+static inline int
+inc_zqmq_next_cmd(uint8_t *bar_addr, uint16_t ring)
+{
+ uint64_t reg_addr = 0;
+ uint64_t val;
+
+ reg_addr = ZQMQ_NXT_CMDX(ring);
+ val = nitrox_read_csr(bar_addr, reg_addr);
+ val++;
+ nitrox_write_csr(bar_addr, reg_addr, val);
+ rte_delay_us_block(CSR_DELAY);
+ if (nitrox_read_csr(bar_addr, reg_addr) != val)
+ return -EIO;
+
+ return 0;
+}
+
int vf_get_vf_config_mode(uint8_t *bar_addr);
int vf_config_mode_to_nr_queues(enum nitrox_vf_mode vf_mode);
void setup_nps_pkt_input_ring(uint8_t *bar_addr, uint16_t ring, uint32_t rsize,
@@ -161,5 +273,8 @@ void setup_nps_pkt_input_ring(uint8_t *bar_addr, uint16_t ring, uint32_t rsize,
void setup_nps_pkt_solicit_output_port(uint8_t *bar_addr, uint16_t port);
void nps_pkt_input_ring_disable(uint8_t *bar_addr, uint16_t ring);
void nps_pkt_solicited_port_disable(uint8_t *bar_addr, uint16_t port);
+int setup_zqmq_input_ring(uint8_t *bar_addr, uint16_t ring, uint32_t rsize,
+ phys_addr_t raddr);
+int zqmq_input_ring_disable(uint8_t *bar_addr, uint16_t ring);
#endif /* _NITROX_HAL_H_ */
@@ -2,7 +2,7 @@
* Copyright(C) 2019 Marvell International Ltd.
*/
-#include <rte_cryptodev.h>
+#include <rte_memzone.h>
#include <rte_malloc.h>
#include "nitrox_qp.h"
@@ -20,6 +20,7 @@ nitrox_setup_cmdq(struct nitrox_qp *qp, uint8_t *bar_addr,
const struct rte_memzone *mz;
size_t cmdq_size = qp->count * instr_size;
uint64_t offset;
+ int err = 0;
snprintf(mz_name, sizeof(mz_name), "%s_cmdq_%d", dev_name, qp->qno);
mz = rte_memzone_reserve_aligned(mz_name, cmdq_size, socket_id,
@@ -32,14 +33,34 @@ nitrox_setup_cmdq(struct nitrox_qp *qp, uint8_t *bar_addr,
return -ENOMEM;
}
+ switch (qp->type) {
+ case NITROX_QUEUE_SE:
+ offset = NPS_PKT_IN_INSTR_BAOFF_DBELLX(qp->qno);
+ qp->cmdq.dbell_csr_addr = NITROX_CSR_ADDR(bar_addr, offset);
+ setup_nps_pkt_input_ring(bar_addr, qp->qno, qp->count,
+ mz->iova);
+ setup_nps_pkt_solicit_output_port(bar_addr, qp->qno);
+ break;
+ case NITROX_QUEUE_ZIP:
+ offset = ZQMQ_DRBLX(qp->qno);
+ qp->cmdq.dbell_csr_addr = NITROX_CSR_ADDR(bar_addr, offset);
+ err = setup_zqmq_input_ring(bar_addr, qp->qno, qp->count,
+ mz->iova);
+ break;
+ default:
+ NITROX_LOG(ERR, "Invalid queue type %d\n", qp->type);
+ err = -EINVAL;
+ break;
+ }
+
+ if (err) {
+ rte_memzone_free(mz);
+ return err;
+ }
+
qp->cmdq.mz = mz;
- offset = NPS_PKT_IN_INSTR_BAOFF_DBELLX(qp->qno);
- qp->cmdq.dbell_csr_addr = NITROX_CSR_ADDR(bar_addr, offset);
qp->cmdq.ring = mz->addr;
qp->cmdq.instr_size = instr_size;
- setup_nps_pkt_input_ring(bar_addr, qp->qno, qp->count, mz->iova);
- setup_nps_pkt_solicit_output_port(bar_addr, qp->qno);
-
return 0;
}
@@ -62,8 +83,23 @@ nitrox_setup_ridq(struct nitrox_qp *qp, int socket_id)
static int
nitrox_release_cmdq(struct nitrox_qp *qp, uint8_t *bar_addr)
{
- nps_pkt_solicited_port_disable(bar_addr, qp->qno);
- nps_pkt_input_ring_disable(bar_addr, qp->qno);
+ int err = 0;
+
+ switch (qp->type) {
+ case NITROX_QUEUE_SE:
+ nps_pkt_solicited_port_disable(bar_addr, qp->qno);
+ nps_pkt_input_ring_disable(bar_addr, qp->qno);
+ break;
+ case NITROX_QUEUE_ZIP:
+ err = zqmq_input_ring_disable(bar_addr, qp->qno);
+ break;
+ default:
+ err = -EINVAL;
+ }
+
+ if (err)
+ return err;
+
return rte_memzone_free(qp->cmdq.mz);
}
@@ -83,6 +119,7 @@ nitrox_qp_setup(struct nitrox_qp *qp, uint8_t *bar_addr, const char *dev_name,
return -EINVAL;
}
+ qp->bar_addr = bar_addr;
qp->count = count;
qp->head = qp->tail = 0;
rte_atomic16_init(&qp->pending_count);
@@ -8,9 +8,16 @@
#include <stdbool.h>
#include <rte_io.h>
+#include "nitrox_hal.h"
struct nitrox_softreq;
+enum nitrox_queue_type {
+ NITROX_QUEUE_SE,
+ NITROX_QUEUE_AE,
+ NITROX_QUEUE_ZIP,
+};
+
struct command_queue {
const struct rte_memzone *mz;
uint8_t *dbell_csr_addr;
@@ -22,14 +29,23 @@ struct rid {
struct nitrox_softreq *sr;
};
+struct nitrox_qp_stats {
+ uint64_t enqueued_count;
+ uint64_t dequeued_count;
+ uint64_t enqueue_err_count;
+ uint64_t dequeue_err_count;
+};
+
struct nitrox_qp {
+ enum nitrox_queue_type type;
+ uint8_t *bar_addr;
struct command_queue cmdq;
struct rid *ridq;
uint32_t count;
uint32_t head;
uint32_t tail;
struct rte_mempool *sr_mp;
- struct rte_cryptodev_stats stats;
+ struct nitrox_qp_stats stats;
uint16_t qno;
rte_atomic16_t pending_count;
};
@@ -89,6 +105,23 @@ nitrox_qp_enqueue(struct nitrox_qp *qp, void *instr, struct nitrox_softreq *sr)
rte_atomic16_inc(&qp->pending_count);
}
+static inline int
+nitrox_qp_enqueue_sr(struct nitrox_qp *qp, struct nitrox_softreq *sr)
+{
+ uint32_t head = qp->head % qp->count;
+ int err;
+
+ err = inc_zqmq_next_cmd(qp->bar_addr, qp->qno);
+ if (unlikely(err))
+ return err;
+
+ qp->head++;
+ qp->ridq[head].sr = sr;
+ rte_smp_wmb();
+ rte_atomic16_inc(&qp->pending_count);
+ return 0;
+}
+
static inline void
nitrox_qp_dequeue(struct nitrox_qp *qp)
{