@@ -7,7 +7,9 @@ sources = [
'spnic_hwif.c',
'spnic_mbox.c',
'spnic_mgmt.c',
- 'spnic_nic_event.c'
+ 'spnic_nic_event.c',
+ 'spnic_cmdq.c',
+ 'spnic_hw_comm.c',
]
extra_flags = []
new file mode 100644
@@ -0,0 +1,202 @@
+/* SPDX-License-Identifier: BSD-3-Clause
+ * Copyright(c) 2021 Ramaxel Memory Technology, Ltd
+ */
+
+#include <rte_mbuf.h>
+
+#include "spnic_compat.h"
+#include "spnic_hwdev.h"
+#include "spnic_hwif.h"
+#include "spnic_wq.h"
+#include "spnic_cmd.h"
+#include "spnic_mgmt.h"
+#include "spnic_cmdq.h"
+
+#define CMDQ_CTXT_CURR_WQE_PAGE_PFN_SHIFT 0
+#define CMDQ_CTXT_EQ_ID_SHIFT 53
+#define CMDQ_CTXT_CEQ_ARM_SHIFT 61
+#define CMDQ_CTXT_CEQ_EN_SHIFT 62
+#define CMDQ_CTXT_HW_BUSY_BIT_SHIFT 63
+
+#define CMDQ_CTXT_CURR_WQE_PAGE_PFN_MASK 0xFFFFFFFFFFFFF
+#define CMDQ_CTXT_EQ_ID_MASK 0xFF
+#define CMDQ_CTXT_CEQ_ARM_MASK 0x1
+#define CMDQ_CTXT_CEQ_EN_MASK 0x1
+#define CMDQ_CTXT_HW_BUSY_BIT_MASK 0x1
+
+#define CMDQ_CTXT_PAGE_INFO_SET(val, member) \
+ (((u64)(val) & CMDQ_CTXT_##member##_MASK) << CMDQ_CTXT_##member##_SHIFT)
+
+#define CMDQ_CTXT_WQ_BLOCK_PFN_SHIFT 0
+#define CMDQ_CTXT_CI_SHIFT 52
+
+#define CMDQ_CTXT_WQ_BLOCK_PFN_MASK 0xFFFFFFFFFFFFF
+#define CMDQ_CTXT_CI_MASK 0xFFF
+
+#define CMDQ_CTXT_BLOCK_INFO_SET(val, member) \
+ (((u64)(val) & CMDQ_CTXT_##member##_MASK) << CMDQ_CTXT_##member##_SHIFT)
+
+#define WAIT_CMDQ_ENABLE_TIMEOUT 300
+
+static int init_cmdq(struct spnic_cmdq *cmdq, struct spnic_hwdev *hwdev,
+ struct spnic_wq *wq, enum spnic_cmdq_type q_type)
+{
+ void *db_base = NULL;
+ int err = 0;
+ size_t errcode_size;
+ size_t cmd_infos_size;
+
+ cmdq->wq = wq;
+ cmdq->cmdq_type = q_type;
+ cmdq->wrapped = 1;
+
+ rte_spinlock_init(&cmdq->cmdq_lock);
+
+ errcode_size = wq->q_depth * sizeof(*cmdq->errcode);
+ cmdq->errcode = rte_zmalloc(NULL, errcode_size, 0);
+ if (!cmdq->errcode) {
+ PMD_DRV_LOG(ERR, "Allocate errcode for cmdq failed");
+ return -ENOMEM;
+ }
+
+ cmd_infos_size = wq->q_depth * sizeof(*cmdq->cmd_infos);
+ cmdq->cmd_infos = rte_zmalloc(NULL, cmd_infos_size, 0);
+ if (!cmdq->cmd_infos) {
+ PMD_DRV_LOG(ERR, "Allocate cmd info for cmdq failed");
+ err = -ENOMEM;
+ goto cmd_infos_err;
+ }
+
+ err = spnic_alloc_db_addr(hwdev, &db_base, NULL);
+ if (err)
+ goto alloc_db_err;
+
+ cmdq->db_base = (u8 *)db_base;
+
+ return 0;
+
+alloc_db_err:
+ rte_free(cmdq->cmd_infos);
+
+cmd_infos_err:
+ rte_free(cmdq->errcode);
+
+ return err;
+}
+
+static void free_cmdq(struct spnic_hwdev *hwdev, struct spnic_cmdq *cmdq)
+{
+ spnic_free_db_addr(hwdev, cmdq->db_base, NULL);
+ rte_free(cmdq->cmd_infos);
+ rte_free(cmdq->errcode);
+}
+
+static int spnic_set_cmdq_ctxts(struct spnic_hwdev *hwdev)
+{
+ struct spnic_cmdqs *cmdqs = hwdev->cmdqs;
+ struct spnic_cmd_cmdq_ctxt cmdq_ctxt;
+ enum spnic_cmdq_type cmdq_type;
+ u16 out_size = sizeof(cmdq_ctxt);
+ int err;
+
+ cmdq_type = SPNIC_CMDQ_SYNC;
+ for (; cmdq_type < SPNIC_MAX_CMDQ_TYPES; cmdq_type++) {
+ memset(&cmdq_ctxt, 0, sizeof(cmdq_ctxt));
+ memcpy(&cmdq_ctxt.ctxt_info, &cmdqs->cmdq[cmdq_type].cmdq_ctxt,
+ sizeof(cmdq_ctxt.ctxt_info));
+ cmdq_ctxt.func_idx = spnic_global_func_id(hwdev);
+ cmdq_ctxt.cmdq_id = cmdq_type;
+
+ err = spnic_msg_to_mgmt_sync(hwdev, SPNIC_MOD_COMM,
+ MGMT_CMD_SET_CMDQ_CTXT,
+ &cmdq_ctxt, sizeof(cmdq_ctxt),
+ &cmdq_ctxt, &out_size, 0);
+ if (err || !out_size || cmdq_ctxt.status) {
+ PMD_DRV_LOG(ERR, "Set cmdq ctxt failed, err: %d, status: 0x%x, out_size: 0x%x",
+ err, cmdq_ctxt.status, out_size);
+ return -EFAULT;
+ }
+ }
+
+ cmdqs->status |= SPNIC_CMDQ_ENABLE;
+
+ return 0;
+}
+
+int spnic_reinit_cmdq_ctxts(struct spnic_hwdev *hwdev)
+{
+ return spnic_set_cmdq_ctxts(hwdev);
+}
+
+int spnic_cmdqs_init(struct spnic_hwdev *hwdev)
+{
+ struct spnic_cmdqs *cmdqs = NULL;
+ enum spnic_cmdq_type type, cmdq_type;
+ char cmdq_pool_name[RTE_MEMPOOL_NAMESIZE];
+ int err;
+
+ cmdqs = rte_zmalloc(NULL, sizeof(*cmdqs), 0);
+ if (!cmdqs)
+ return -ENOMEM;
+
+ hwdev->cmdqs = cmdqs;
+ cmdqs->hwdev = hwdev;
+
+ memset(cmdq_pool_name, 0, RTE_MEMPOOL_NAMESIZE);
+ snprintf(cmdq_pool_name, sizeof(cmdq_pool_name), "spnic_cmdq_%u",
+ hwdev->port_id);
+
+ cmdqs->cmd_buf_pool = rte_pktmbuf_pool_create(cmdq_pool_name,
+ SPNIC_CMDQ_DEPTH * SPNIC_MAX_CMDQ_TYPES,
+ 0, 0, SPNIC_CMDQ_BUF_SIZE, rte_socket_id());
+ if (!cmdqs->cmd_buf_pool) {
+ PMD_DRV_LOG(ERR, "Create cmdq buffer pool failed");
+ err = -ENOMEM;
+ goto pool_create_err;
+ }
+
+ cmdq_type = SPNIC_CMDQ_SYNC;
+ for (; cmdq_type < SPNIC_MAX_CMDQ_TYPES; cmdq_type++) {
+ err = init_cmdq(&cmdqs->cmdq[cmdq_type], hwdev,
+ &cmdqs->saved_wqs[cmdq_type], cmdq_type);
+ if (err) {
+ PMD_DRV_LOG(ERR, "Initialize cmdq failed");
+ goto init_cmdq_err;
+ }
+ }
+
+ err = spnic_set_cmdq_ctxts(hwdev);
+ if (err)
+ goto init_cmdq_err;
+
+ return 0;
+
+init_cmdq_err:
+ type = SPNIC_CMDQ_SYNC;
+ for (; type < cmdq_type; type++)
+ free_cmdq(hwdev, &cmdqs->cmdq[type]);
+
+ rte_mempool_free(cmdqs->cmd_buf_pool);
+
+pool_create_err:
+ rte_free(cmdqs);
+
+ return err;
+}
+
+void spnic_cmdqs_free(struct spnic_hwdev *hwdev)
+{
+ struct spnic_cmdqs *cmdqs = hwdev->cmdqs;
+ enum spnic_cmdq_type cmdq_type = SPNIC_CMDQ_SYNC;
+
+ cmdqs->status &= ~SPNIC_CMDQ_ENABLE;
+
+ for (; cmdq_type < SPNIC_MAX_CMDQ_TYPES; cmdq_type++)
+ free_cmdq(cmdqs->hwdev, &cmdqs->cmdq[cmdq_type]);
+
+ rte_mempool_free(cmdqs->cmd_buf_pool);
+
+ rte_free(cmdqs->saved_wqs);
+
+ rte_free(cmdqs);
+}
new file mode 100644
@@ -0,0 +1,228 @@
+/* SPDX-License-Identifier: BSD-3-Clause
+ * Copyright(c) 2021 Ramaxel Memory Technology, Ltd
+ */
+
+#ifndef _SPNIC_CMDQ_H_
+#define _SPNIC_CMDQ_H_
+
+#define SPNIC_SCMD_DATA_LEN 16
+
+/* Pmd driver uses 64, kernel l2nic uses 4096 */
+#define SPNIC_CMDQ_DEPTH 64
+
+#define SPNIC_CMDQ_BUF_SIZE 2048U
+#define SPNIC_CMDQ_BUF_HW_RSVD 8
+#define SPNIC_CMDQ_MAX_DATA_SIZE (SPNIC_CMDQ_BUF_SIZE \
+ - SPNIC_CMDQ_BUF_HW_RSVD)
+
+#define SPNIC_CEQ_ID_CMDQ 0
+
+enum cmdq_scmd_type {
+ CMDQ_SET_ARM_CMD = 2,
+};
+
+enum cmdq_wqe_type {
+ WQE_LCMD_TYPE,
+ WQE_SCMD_TYPE
+};
+
+enum ctrl_sect_len {
+ CTRL_SECT_LEN = 1,
+ CTRL_DIRECT_SECT_LEN = 2
+};
+
+enum bufdesc_len {
+ BUFDESC_LCMD_LEN = 2,
+ BUFDESC_SCMD_LEN = 3
+};
+
+enum data_format {
+ DATA_SGE,
+};
+
+enum completion_format {
+ COMPLETE_DIRECT,
+ COMPLETE_SGE
+};
+
+enum completion_request {
+ CEQ_SET = 1,
+};
+
+enum cmdq_cmd_type {
+ SYNC_CMD_DIRECT_RESP,
+ SYNC_CMD_SGE_RESP,
+ ASYNC_CMD
+};
+
+enum spnic_cmdq_type {
+ SPNIC_CMDQ_SYNC,
+ SPNIC_CMDQ_ASYNC,
+ SPNIC_MAX_CMDQ_TYPES
+};
+
+enum spnic_db_src_type {
+ SPNIC_DB_SRC_CMDQ_TYPE,
+ SPNIC_DB_SRC_L2NIC_SQ_TYPE
+};
+
+enum spnic_cmdq_db_type {
+ SPNIC_DB_SQ_RQ_TYPE,
+ SPNIC_DB_CMDQ_TYPE
+};
+
+/* Cmdq ack type */
+enum spnic_ack_type {
+ SPNIC_ACK_TYPE_CMDQ,
+ SPNIC_ACK_TYPE_SHARE_CQN,
+ SPNIC_ACK_TYPE_APP_CQN,
+
+ SPNIC_MOD_ACK_MAX = 15
+};
+
+/* Cmdq wqe ctrls */
+struct spnic_cmdq_header {
+ u32 header_info;
+ u32 saved_data;
+};
+
+struct spnic_scmd_bufdesc {
+ u32 buf_len;
+ u32 rsvd;
+ u8 data[SPNIC_SCMD_DATA_LEN];
+};
+
+struct spnic_lcmd_bufdesc {
+ u32 rsvd1;
+ u64 saved_async_buf;
+ u64 rsvd3;
+};
+
+struct spnic_cmdq_db {
+ u32 db_head;
+ u32 db_info;
+};
+
+struct spnic_status {
+ u32 status_info;
+};
+
+struct spnic_ctrl {
+ u32 ctrl_info;
+};
+
+struct spnic_sge_resp {
+ u32 rsvd;
+};
+
+struct spnic_cmdq_completion {
+ /* HW format */
+ union {
+ struct spnic_sge_resp sge_resp;
+ u64 direct_resp;
+ };
+};
+
+struct spnic_cmdq_wqe_scmd {
+ struct spnic_cmdq_header header;
+ u64 rsvd;
+ struct spnic_status status;
+ struct spnic_ctrl ctrl;
+ struct spnic_cmdq_completion completion;
+ struct spnic_scmd_bufdesc buf_desc;
+};
+
+struct spnic_cmdq_wqe_lcmd {
+ struct spnic_cmdq_header header;
+ struct spnic_status status;
+ struct spnic_ctrl ctrl;
+ struct spnic_cmdq_completion completion;
+ struct spnic_lcmd_bufdesc buf_desc;
+};
+
+struct spnic_cmdq_inline_wqe {
+ struct spnic_cmdq_wqe_scmd wqe_scmd;
+};
+
+struct spnic_cmdq_wqe {
+ /* HW format */
+ union {
+ struct spnic_cmdq_inline_wqe inline_wqe;
+ struct spnic_cmdq_wqe_lcmd wqe_lcmd;
+ };
+};
+
+struct spnic_cmdq_ctxt_info {
+ u64 curr_wqe_page_pfn;
+ u64 wq_block_pfn;
+};
+
+struct spnic_cmd_cmdq_ctxt {
+ u8 status;
+ u8 version;
+ u8 rsvd0[6];
+
+ u16 func_idx;
+ u8 cmdq_id;
+ u8 rsvd1[5];
+
+ struct spnic_cmdq_ctxt_info ctxt_info;
+};
+
+enum spnic_cmdq_status {
+ SPNIC_CMDQ_ENABLE = BIT(0),
+};
+
+enum spnic_cmdq_cmd_type {
+ SPNIC_CMD_TYPE_NONE,
+ SPNIC_CMD_TYPE_SET_ARM,
+ SPNIC_CMD_TYPE_DIRECT_RESP,
+ SPNIC_CMD_TYPE_SGE_RESP
+};
+
+struct spnic_cmdq_cmd_info {
+ enum spnic_cmdq_cmd_type cmd_type;
+};
+
+struct spnic_cmdq {
+ struct spnic_wq *wq;
+
+ enum spnic_cmdq_type cmdq_type;
+ int wrapped;
+
+ int *errcode;
+ u8 *db_base;
+
+ rte_spinlock_t cmdq_lock;
+
+ struct spnic_cmdq_ctxt_info cmdq_ctxt;
+
+ struct spnic_cmdq_cmd_info *cmd_infos;
+};
+
+struct spnic_cmdqs {
+ struct spnic_hwdev *hwdev;
+
+ struct rte_mempool *cmd_buf_pool;
+
+ struct spnic_wq *saved_wqs;
+
+ struct spnic_cmdq cmdq[SPNIC_MAX_CMDQ_TYPES];
+
+ u32 status;
+};
+
+struct spnic_cmd_buf {
+ void *buf;
+ uint64_t dma_addr;
+ struct rte_mbuf *mbuf;
+ u16 size;
+};
+
+int spnic_reinit_cmdq_ctxts(struct spnic_hwdev *hwdev);
+
+int spnic_cmdqs_init(struct spnic_hwdev *hwdev);
+
+void spnic_cmdqs_free(struct spnic_hwdev *hwdev);
+
+#endif /* _SPNIC_CMDQ_H_ */
new file mode 100644
@@ -0,0 +1,222 @@
+/* SPDX-License-Identifier: BSD-3-Clause
+ * Copyright(c) 2021 Ramaxel Memory Technology, Ltd
+ */
+
+#include <ethdev_driver.h>
+#include <rte_bus_pci.h>
+#include <rte_hash.h>
+#include <rte_jhash.h>
+
+#include "spnic_compat.h"
+#include "spnic_csr.h"
+#include "spnic_hwdev.h"
+#include "spnic_hwif.h"
+#include "spnic_mgmt.h"
+#include "spnic_cmdq.h"
+#include "spnic_hw_comm.h"
+#include "spnic_cmd.h"
+
+#define SPNIC_MSIX_CNT_LLI_TIMER_SHIFT 0
+#define SPNIC_MSIX_CNT_LLI_CREDIT_SHIFT 8
+#define SPNIC_MSIX_CNT_COALESC_TIMER_SHIFT 8
+#define SPNIC_MSIX_CNT_PENDING_SHIFT 8
+#define SPNIC_MSIX_CNT_RESEND_TIMER_SHIFT 29
+
+#define SPNIC_MSIX_CNT_LLI_TIMER_MASK 0xFFU
+#define SPNIC_MSIX_CNT_LLI_CREDIT_MASK 0xFFU
+#define SPNIC_MSIX_CNT_COALESC_TIMER_MASK 0xFFU
+#define SPNIC_MSIX_CNT_PENDING_MASK 0x1FU
+#define SPNIC_MSIX_CNT_RESEND_TIMER_MASK 0x7U
+
+int spnic_get_interrupt_cfg(void *dev, struct interrupt_info *info)
+{
+ struct spnic_hwdev *hwdev = dev;
+ struct spnic_cmd_msix_config msix_cfg;
+ u16 out_size = sizeof(msix_cfg);
+ int err;
+
+ if (!hwdev || !info)
+ return -EINVAL;
+
+ memset(&msix_cfg, 0, sizeof(msix_cfg));
+ msix_cfg.func_id = spnic_global_func_id(hwdev);
+ msix_cfg.msix_index = info->msix_index;
+ msix_cfg.opcode = SPNIC_MGMT_CMD_OP_GET;
+
+ err = spnic_msg_to_mgmt_sync(hwdev, SPNIC_MOD_COMM,
+ MGMT_CMD_CFG_MSIX_CTRL_REG,
+ &msix_cfg, sizeof(msix_cfg),
+ &msix_cfg, &out_size, 0);
+ if (err || !out_size || msix_cfg.status) {
+ PMD_DRV_LOG(ERR, "Get interrupt config failed, err: %d, "
+ "status: 0x%x, out size: 0x%x",
+ err, msix_cfg.status, out_size);
+ return -EINVAL;
+ }
+
+ info->lli_credit_limit = msix_cfg.lli_credit_cnt;
+ info->lli_timer_cfg = msix_cfg.lli_tmier_cnt;
+ info->pending_limt = msix_cfg.pending_cnt;
+ info->coalesc_timer_cfg = msix_cfg.coalesct_timer_cnt;
+ info->resend_timer_cfg = msix_cfg.resend_timer_cnt;
+
+ return 0;
+}
+
+/**
+ * Set interrupt cfg
+ *
+ * @param[in] dev
+ * The pointer to the private hardware device object
+ * @param[in] info
+ * Interrupt info
+ *
+ * @retval zero : Success
+ * @retval negative : Failure.
+ */
+int spnic_set_interrupt_cfg(void *dev, struct interrupt_info info)
+{
+ struct spnic_hwdev *hwdev = dev;
+ struct spnic_cmd_msix_config msix_cfg;
+ struct interrupt_info temp_info;
+ u16 out_size = sizeof(msix_cfg);
+ int err;
+
+ if (!hwdev)
+ return -EINVAL;
+
+ temp_info.msix_index = info.msix_index;
+ err = spnic_get_interrupt_cfg(hwdev, &temp_info);
+ if (err)
+ return -EIO;
+
+ memset(&msix_cfg, 0, sizeof(msix_cfg));
+ msix_cfg.func_id = spnic_global_func_id(hwdev);
+ msix_cfg.msix_index = (u16)info.msix_index;
+ msix_cfg.opcode = SPNIC_MGMT_CMD_OP_SET;
+
+ msix_cfg.lli_credit_cnt = temp_info.lli_credit_limit;
+ msix_cfg.lli_tmier_cnt = temp_info.lli_timer_cfg;
+ msix_cfg.pending_cnt = temp_info.pending_limt;
+ msix_cfg.coalesct_timer_cnt = temp_info.coalesc_timer_cfg;
+ msix_cfg.resend_timer_cnt = temp_info.resend_timer_cfg;
+
+ if (info.lli_set) {
+ msix_cfg.lli_credit_cnt = info.lli_credit_limit;
+ msix_cfg.lli_tmier_cnt = info.lli_timer_cfg;
+ }
+
+ if (info.interrupt_coalesc_set) {
+ msix_cfg.pending_cnt = info.pending_limt;
+ msix_cfg.coalesct_timer_cnt = info.coalesc_timer_cfg;
+ msix_cfg.resend_timer_cnt = info.resend_timer_cfg;
+ }
+
+ err = spnic_msg_to_mgmt_sync(hwdev, SPNIC_MOD_COMM,
+ MGMT_CMD_CFG_MSIX_CTRL_REG,
+ &msix_cfg, sizeof(msix_cfg),
+ &msix_cfg, &out_size, 0);
+ if (err || !out_size || msix_cfg.status) {
+ PMD_DRV_LOG(ERR, "Set interrupt config failed, err: %d, "
+ "status: 0x%x, out size: 0x%x",
+ err, msix_cfg.status, out_size);
+ return -EIO;
+ }
+
+ return 0;
+}
+
+int spnic_set_wq_page_size(void *hwdev, u16 func_idx, u32 page_size)
+{
+ struct spnic_cmd_wq_page_size page_size_info;
+ u16 out_size = sizeof(page_size_info);
+ int err;
+
+ memset(&page_size_info, 0, sizeof(page_size_info));
+ page_size_info.func_idx = func_idx;
+ page_size_info.page_size = SPNIC_PAGE_SIZE_HW(page_size);
+ page_size_info.opcode = SPNIC_MGMT_CMD_OP_SET;
+
+ err = spnic_msg_to_mgmt_sync(hwdev, SPNIC_MOD_COMM,
+ MGMT_CMD_CFG_PAGESIZE,
+ &page_size_info, sizeof(page_size_info),
+ &page_size_info, &out_size, 0);
+ if (err || !out_size || page_size_info.status) {
+ PMD_DRV_LOG(ERR, "Set wq page size failed, err: %d, "
+ "status: 0x%x, out_size: 0x%0x",
+ err, page_size_info.status, out_size);
+ return -EFAULT;
+ }
+
+ return 0;
+}
+
+int spnic_set_cmdq_depth(void *hwdev, u16 cmdq_depth)
+{
+ struct spnic_cmd_root_ctxt root_ctxt;
+ u16 out_size = sizeof(root_ctxt);
+ int err;
+
+ memset(&root_ctxt, 0, sizeof(root_ctxt));
+ root_ctxt.func_idx = spnic_global_func_id(hwdev);
+ root_ctxt.set_cmdq_depth = 1;
+ root_ctxt.cmdq_depth = (u8)ilog2(cmdq_depth);
+
+ err = spnic_msg_to_mgmt_sync(hwdev, SPNIC_MOD_COMM, MGMT_CMD_SET_VAT,
+ &root_ctxt, sizeof(root_ctxt),
+ &root_ctxt, &out_size, 0);
+ if (err || !out_size || root_ctxt.status) {
+ PMD_DRV_LOG(ERR, "Set cmdq depth failed, err: %d, status: 0x%x, out_size: 0x%x",
+ err, root_ctxt.status, out_size);
+ return -EFAULT;
+ }
+
+ return 0;
+}
+
+/**
+ * Set the dma attributes for entry
+ *
+ * @param[in] hwdev
+ * The pointer to the private hardware device object
+ * @param[in] entry_idx
+ * The entry index in the dma table
+ * @param[in] st
+ * PCIE TLP steering tag
+ * @param[in] at
+ * PCIE TLP AT field
+ * @param[in] ph
+ * PCIE TLP Processing Hint field
+ * @param[in] no_snooping
+ * PCIE TLP No snooping
+ * @param[in] tph_en
+ * PCIE TLP Processing Hint Enable
+ */
+int spnic_set_dma_attr_tbl(struct spnic_hwdev *hwdev, u32 entry_idx, u8 st,
+ u8 at, u8 ph, u8 no_snooping, u8 tph_en)
+{
+ struct comm_cmd_dma_attr_config dma_attr;
+ u16 out_size = sizeof(dma_attr);
+ int err;
+
+ memset(&dma_attr, 0, sizeof(dma_attr));
+ dma_attr.func_id = spnic_global_func_id(hwdev);
+ dma_attr.entry_idx = entry_idx;
+ dma_attr.st = st;
+ dma_attr.at = at;
+ dma_attr.ph = ph;
+ dma_attr.no_snooping = no_snooping;
+ dma_attr.tph_en = tph_en;
+
+ err = spnic_msg_to_mgmt_sync(hwdev, SPNIC_MOD_COMM,
+ MGMT_CMD_SET_DMA_ATTR,
+ &dma_attr, sizeof(dma_attr),
+ &dma_attr, &out_size, 0);
+ if (err || !out_size || dma_attr.head.status) {
+ PMD_DRV_LOG(ERR, "Failed to set dma attr, err: %d, status: 0x%x, out_size: 0x%x\n",
+ err, dma_attr.head.status, out_size);
+ return -EINVAL;
+ }
+
+ return 0;
+}
new file mode 100644
@@ -0,0 +1,176 @@
+/* SPDX-License-Identifier: BSD-3-Clause
+ * Copyright(c) 2021 Ramaxel Memory Technology, Ltd
+ */
+
+#ifndef _SPNIC_HW_COMM_H_
+#define _SPNIC_HW_COMM_H_
+
+#define SPNIC_MGMT_CMD_OP_GET 0
+#define SPNIC_MGMT_CMD_OP_SET 1
+
+#define SPNIC_MSIX_CNT_LLI_TIMER_SHIFT 0
+#define SPNIC_MSIX_CNT_LLI_CREDIT_SHIFT 8
+#define SPNIC_MSIX_CNT_COALESC_TIMER_SHIFT 8
+#define SPNIC_MSIX_CNT_PENDING_SHIFT 8
+#define SPNIC_MSIX_CNT_RESEND_TIMER_SHIFT 29
+
+#define SPNIC_MSIX_CNT_LLI_TIMER_MASK 0xFFU
+#define SPNIC_MSIX_CNT_LLI_CREDIT_MASK 0xFFU
+#define SPNIC_MSIX_CNT_COALESC_TIMER_MASK 0xFFU
+#define SPNIC_MSIX_CNT_PENDING_MASK 0x1FU
+#define SPNIC_MSIX_CNT_RESEND_TIMER_MASK 0x7U
+
+#define SPNIC_MSIX_CNT_SET(val, member) \
+ (((val) & SPNIC_MSIX_CNT_##member##_MASK) << \
+ SPNIC_MSIX_CNT_##member##_SHIFT)
+
+#define MSG_TO_MGMT_SYNC_RETURN_ERR(err, out_size, status) \
+ ((err) || (status) || !(out_size))
+
+struct spnic_cmd_msix_config {
+ u8 status;
+ u8 version;
+ u8 rsvd0[6];
+
+ u16 func_id;
+ u8 opcode;
+ u8 rsvd1;
+ u16 msix_index;
+ u8 pending_cnt;
+ u8 coalesct_timer_cnt;
+ u8 resend_timer_cnt;
+ u8 lli_tmier_cnt;
+ u8 lli_credit_cnt;
+ u8 rsvd2[5];
+};
+
+#define SPNIC_PAGE_SIZE_HW(pg_size) ((u8)ilog2((u32)((pg_size) >> 12)))
+
+struct spnic_cmd_wq_page_size {
+ u8 status;
+ u8 version;
+ u8 rsvd0[6];
+
+ u16 func_idx;
+ u8 opcode;
+ /*
+ * Real size is 4KB * 2^page_size, range(0~20) must be checked
+ * by driver
+ */
+ u8 page_size;
+
+ u32 rsvd1;
+};
+
+struct spnic_reset {
+ u8 status;
+ u8 version;
+ u8 rsvd0[6];
+
+ u16 func_id;
+ u16 rsvd1[3];
+ u64 reset_flag;
+};
+
+struct spnic_cmd_root_ctxt {
+ u8 status;
+ u8 version;
+ u8 rsvd0[6];
+
+ u16 func_idx;
+ u8 set_cmdq_depth;
+ u8 cmdq_depth;
+ u16 rx_buf_sz;
+ u8 lro_en;
+ u8 rsvd1;
+ u16 sq_depth;
+ u16 rq_depth;
+ u64 rsvd2;
+};
+
+enum spnic_fw_ver_type {
+ SPNIC_FW_VER_TYPE_BOOT,
+ SPNIC_FW_VER_TYPE_MPU,
+ SPNIC_FW_VER_TYPE_NPU,
+ SPNIC_FW_VER_TYPE_SMU,
+ SPNIC_FW_VER_TYPE_CFG,
+};
+
+struct comm_cmd_dma_attr_config {
+ struct mgmt_msg_head head;
+
+ u16 func_id;
+ u8 entry_idx;
+ u8 st;
+ u8 at;
+ u8 ph;
+ u8 no_snooping;
+ u8 tph_en;
+ u32 resv1;
+};
+
+#define SPNIC_FW_VERSION_LEN 16
+#define SPNIC_FW_COMPILE_TIME_LEN 20
+#define SPNIC_MGMT_VERSION_MAX_LEN 32
+struct spnic_cmd_get_fw_version {
+ u8 status;
+ u8 version;
+ u8 rsvd0[6];
+
+ u16 fw_type;
+ u16 rsvd1;
+ u8 ver[SPNIC_FW_VERSION_LEN];
+ u8 time[SPNIC_FW_COMPILE_TIME_LEN];
+};
+
+struct spnic_cmd_clear_doorbell {
+ u8 status;
+ u8 version;
+ u8 rsvd0[6];
+
+ u16 func_idx;
+ u16 rsvd1[3];
+};
+
+struct spnic_cmd_clear_resource {
+ u8 status;
+ u8 version;
+ u8 rsvd0[6];
+
+ u16 func_idx;
+ u16 rsvd1[3];
+};
+
+struct spnic_cmd_board_info {
+ u8 status;
+ u8 version;
+ u8 rsvd0[6];
+
+ struct spnic_board_info info;
+
+ u32 rsvd1[25];
+};
+
+struct interrupt_info {
+ u32 lli_set;
+ u32 interrupt_coalesc_set;
+ u16 msix_index;
+ u8 lli_credit_limit;
+ u8 lli_timer_cfg;
+ u8 pending_limt;
+ u8 coalesc_timer_cfg;
+ u8 resend_timer_cfg;
+};
+
+int spnic_get_interrupt_cfg(void *dev, struct interrupt_info *info);
+
+int spnic_set_interrupt_cfg(void *dev, struct interrupt_info info);
+
+int spnic_set_wq_page_size(void *hwdev, u16 func_idx, u32 page_size);
+
+int spnic_set_cmdq_depth(void *hwdev, u16 cmdq_depth);
+
+int spnic_set_dma_attr_tbl(struct spnic_hwdev *hwdev, u32 entry_idx, u8 st,
+ u8 at, u8 ph, u8 no_snooping, u8 tph_en);
+
+#endif
@@ -9,7 +9,64 @@
#include "spnic_mgmt.h"
#include "spnic_cmd.h"
#include "spnic_mbox.h"
+#include "spnic_cmdq.h"
#include "spnic_hwdev.h"
+#include "spnic_hw_comm.h"
+
+enum spnic_pcie_nosnoop {
+ SPNIC_PCIE_SNOOP = 0,
+ SPNIC_PCIE_NO_SNOOP = 1
+};
+
+enum spnic_pcie_tph {
+ SPNIC_PCIE_TPH_DISABLE = 0,
+ SPNIC_PCIE_TPH_ENABLE = 1
+};
+
+#define SPNIC_DMA_ATTR_INDIR_IDX_SHIFT 0
+
+#define SPNIC_DMA_ATTR_INDIR_IDX_MASK 0x3FF
+
+#define SPNIC_DMA_ATTR_INDIR_IDX_SET(val, member) \
+ (((u32)(val) & SPNIC_DMA_ATTR_INDIR_##member##_MASK) << \
+ SPNIC_DMA_ATTR_INDIR_##member##_SHIFT)
+
+#define SPNIC_DMA_ATTR_INDIR_IDX_CLEAR(val, member) \
+ ((val) & (~(SPNIC_DMA_ATTR_INDIR_##member##_MASK \
+ << SPNIC_DMA_ATTR_INDIR_##member##_SHIFT)))
+
+#define SPNIC_DMA_ATTR_ENTRY_ST_SHIFT 0
+#define SPNIC_DMA_ATTR_ENTRY_AT_SHIFT 8
+#define SPNIC_DMA_ATTR_ENTRY_PH_SHIFT 10
+#define SPNIC_DMA_ATTR_ENTRY_NO_SNOOPING_SHIFT 12
+#define SPNIC_DMA_ATTR_ENTRY_TPH_EN_SHIFT 13
+
+#define SPNIC_DMA_ATTR_ENTRY_ST_MASK 0xFF
+#define SPNIC_DMA_ATTR_ENTRY_AT_MASK 0x3
+#define SPNIC_DMA_ATTR_ENTRY_PH_MASK 0x3
+#define SPNIC_DMA_ATTR_ENTRY_NO_SNOOPING_MASK 0x1
+#define SPNIC_DMA_ATTR_ENTRY_TPH_EN_MASK 0x1
+
+#define SPNIC_DMA_ATTR_ENTRY_SET(val, member) \
+ (((u32)(val) & SPNIC_DMA_ATTR_ENTRY_##member##_MASK) << \
+ SPNIC_DMA_ATTR_ENTRY_##member##_SHIFT)
+
+#define SPNIC_DMA_ATTR_ENTRY_CLEAR(val, member) \
+ ((val) & (~(SPNIC_DMA_ATTR_ENTRY_##member##_MASK \
+ << SPNIC_DMA_ATTR_ENTRY_##member##_SHIFT)))
+
+#define SPNIC_PCIE_ST_DISABLE 0
+#define SPNIC_PCIE_AT_DISABLE 0
+#define SPNIC_PCIE_PH_DISABLE 0
+
+#define PCIE_MSIX_ATTR_ENTRY 0
+
+#define SPNIC_CHIP_PRESENT 1
+#define SPNIC_CHIP_ABSENT 0
+
+#define SPNIC_DEAULT_EQ_MSIX_PENDING_LIMIT 0
+#define SPNIC_DEAULT_EQ_MSIX_COALESC_TIMER_CFG 0xFF
+#define SPNIC_DEAULT_EQ_MSIX_RESEND_TIMER_CFG 7
typedef void (*mgmt_event_cb)(void *handle, void *buf_in, u16 in_size,
void *buf_out, u16 *out_size);
@@ -100,6 +157,78 @@ void pf_handle_mgmt_comm_event(void *handle, __rte_unused void *pri_handle,
PMD_DRV_LOG(WARNING, "Unsupported mgmt cpu event %d to process", cmd);
}
+/**
+ * Initialize the default dma attributes
+ *
+ * @param[in] hwdev
+ * The pointer to the private hardware device object
+ *
+ * @retval zero: Success
+ * @retval non-zero: Failure
+ */
+static int dma_attr_table_init(struct spnic_hwdev *hwdev)
+{
+ u32 addr, val, dst_attr;
+
+ /* Use indirect access should set entry_idx first */
+ addr = SPNIC_CSR_DMA_ATTR_INDIR_IDX_ADDR;
+ val = spnic_hwif_read_reg(hwdev->hwif, addr);
+ val = SPNIC_DMA_ATTR_INDIR_IDX_CLEAR(val, IDX);
+
+ val |= SPNIC_DMA_ATTR_INDIR_IDX_SET(PCIE_MSIX_ATTR_ENTRY, IDX);
+
+ spnic_hwif_write_reg(hwdev->hwif, addr, val);
+
+ rte_wmb(); /* Write index before config */
+
+ addr = SPNIC_CSR_DMA_ATTR_TBL_ADDR;
+ val = spnic_hwif_read_reg(hwdev->hwif, addr);
+
+ dst_attr = SPNIC_DMA_ATTR_ENTRY_SET(SPNIC_PCIE_ST_DISABLE, ST) |
+ SPNIC_DMA_ATTR_ENTRY_SET(SPNIC_PCIE_AT_DISABLE, AT) |
+ SPNIC_DMA_ATTR_ENTRY_SET(SPNIC_PCIE_PH_DISABLE, PH) |
+ SPNIC_DMA_ATTR_ENTRY_SET(SPNIC_PCIE_SNOOP, NO_SNOOPING) |
+ SPNIC_DMA_ATTR_ENTRY_SET(SPNIC_PCIE_TPH_DISABLE, TPH_EN);
+
+ if (val == dst_attr)
+ return 0;
+
+ return spnic_set_dma_attr_tbl(hwdev, PCIE_MSIX_ATTR_ENTRY,
+ SPNIC_PCIE_ST_DISABLE,
+ SPNIC_PCIE_AT_DISABLE,
+ SPNIC_PCIE_PH_DISABLE,
+ SPNIC_PCIE_SNOOP,
+ SPNIC_PCIE_TPH_DISABLE);
+}
+
+static int init_aeqs_msix_attr(struct spnic_hwdev *hwdev)
+{
+ struct spnic_aeqs *aeqs = hwdev->aeqs;
+ struct interrupt_info info = {0};
+ struct spnic_eq *eq = NULL;
+ u16 q_id;
+ int err;
+
+ info.lli_set = 0;
+ info.interrupt_coalesc_set = 1;
+ info.pending_limt = SPNIC_DEAULT_EQ_MSIX_PENDING_LIMIT;
+ info.coalesc_timer_cfg = SPNIC_DEAULT_EQ_MSIX_COALESC_TIMER_CFG;
+ info.resend_timer_cfg = SPNIC_DEAULT_EQ_MSIX_RESEND_TIMER_CFG;
+
+ for (q_id = 0; q_id < aeqs->num_aeqs; q_id++) {
+ eq = &aeqs->aeq[q_id];
+ info.msix_index = eq->eq_irq.msix_entry_idx;
+ err = spnic_set_interrupt_cfg(hwdev, info);
+ if (err) {
+ PMD_DRV_LOG(ERR, "Set msix attr for aeq %d failed",
+ q_id);
+ return -EFAULT;
+ }
+ }
+
+ return 0;
+}
+
static int spnic_comm_pf_to_mgmt_init(struct spnic_hwdev *hwdev)
{
int err;
@@ -124,6 +253,35 @@ static void spnic_comm_pf_to_mgmt_free(struct spnic_hwdev *hwdev)
spnic_pf_to_mgmt_free(hwdev);
}
+static int spnic_comm_cmdqs_init(struct spnic_hwdev *hwdev)
+{
+ int err;
+
+ err = spnic_cmdqs_init(hwdev);
+ if (err) {
+ PMD_DRV_LOG(ERR, "Init cmd queues failed");
+ return err;
+ }
+
+ err = spnic_set_cmdq_depth(hwdev, SPNIC_CMDQ_DEPTH);
+ if (err) {
+ PMD_DRV_LOG(ERR, "Set cmdq depth failed");
+ goto set_cmdq_depth_err;
+ }
+
+ return 0;
+
+set_cmdq_depth_err:
+ spnic_cmdqs_free(hwdev);
+
+ return err;
+}
+
+static void spnic_comm_cmdqs_free(struct spnic_hwdev *hwdev)
+{
+ spnic_cmdqs_free(hwdev);
+}
+
static int init_mgmt_channel(struct spnic_hwdev *hwdev)
{
int err;
@@ -164,6 +322,51 @@ static void free_mgmt_channel(struct spnic_hwdev *hwdev)
spnic_aeqs_free(hwdev);
}
+#define SPNIC_DEFAULT_WQ_PAGE_SIZE 0x100000
+#define SPNIC_HW_WQ_PAGE_SIZE 0x1000
+
+static int init_cmdqs_channel(struct spnic_hwdev *hwdev)
+{
+ int err;
+
+ err = dma_attr_table_init(hwdev);
+ if (err) {
+ PMD_DRV_LOG(ERR, "Init dma attr table failed");
+ goto dma_attr_init_err;
+ }
+
+ err = init_aeqs_msix_attr(hwdev);
+ if (err)
+ goto init_aeqs_msix_err;
+
+ /* Set default wq page_size */
+ hwdev->wq_page_size = SPNIC_DEFAULT_WQ_PAGE_SIZE;
+ err = spnic_set_wq_page_size(hwdev, spnic_global_func_id(hwdev),
+ hwdev->wq_page_size);
+ if (err) {
+ PMD_DRV_LOG(ERR, "Set wq page size failed");
+ goto init_wq_pg_size_err;
+ }
+
+ err = spnic_comm_cmdqs_init(hwdev);
+ if (err) {
+ PMD_DRV_LOG(ERR, "Init cmd queues failed");
+ goto cmdq_init_err;
+ }
+
+ return 0;
+
+cmdq_init_err:
+ if (SPNIC_FUNC_TYPE(hwdev) != TYPE_VF)
+ spnic_set_wq_page_size(hwdev, spnic_global_func_id(hwdev),
+ SPNIC_HW_WQ_PAGE_SIZE);
+init_wq_pg_size_err:
+init_aeqs_msix_err:
+dma_attr_init_err:
+
+ return err;
+}
+
static int spnic_init_comm_ch(struct spnic_hwdev *hwdev)
{
int err;
@@ -174,11 +377,23 @@ static int spnic_init_comm_ch(struct spnic_hwdev *hwdev)
return err;
}
+ err = init_cmdqs_channel(hwdev);
+ if (err) {
+ PMD_DRV_LOG(ERR, "Init cmdq channel failed");
+ goto init_cmdqs_channel_err;
+ }
+
return 0;
+
+init_cmdqs_channel_err:
+ free_mgmt_channel(hwdev);
+
+ return err;
}
static void spnic_uninit_comm_ch(struct spnic_hwdev *hwdev)
{
+ spnic_comm_cmdqs_free(hwdev);
free_mgmt_channel(hwdev);
}
@@ -91,13 +91,17 @@ struct spnic_hwdev {
void *dev_handle; /* Pointer to spnic_nic_dev */
void *pci_dev; /* Pointer to rte_pci_device */
void *eth_dev; /* Pointer to rte_eth_dev */
-
+ struct spnic_hwif *hwif;
uint16_t port_id;
- struct spnic_hwif *hwif;
+ u32 wq_page_size;
+
struct spnic_mbox *func_to_func;
struct cfg_mgmt_info *cfg_mgmt;
+
+ struct spnic_cmdqs *cmdqs;
struct spnic_aeqs *aeqs;
+
struct spnic_msg_pf_to_mgmt *pf_to_mgmt;
u8 *chip_fault_stats;
struct spnic_hw_stats hw_stats;
new file mode 100644
@@ -0,0 +1,57 @@
+/* SPDX-License-Identifier: BSD-3-Clause
+ * Copyright(c) 2021 Ramaxel Memory Technology, Ltd
+ */
+
+#ifndef _SPNIC_WQ_H_
+#define _SPNIC_WQ_H_
+
+/* Use 0-level CLA, page size must be: SQ 16B(wqe) * 64k(max_q_depth) */
+#define SPNIC_DEFAULT_WQ_PAGE_SIZE 0x100000
+#define SPNIC_HW_WQ_PAGE_SIZE 0x1000
+
+#define CMDQ_BLOCKS_PER_PAGE 8
+#define CMDQ_BLOCK_SIZE 512UL
+#define CMDQ_PAGE_SIZE RTE_ALIGN((CMDQ_BLOCKS_PER_PAGE * \
+ CMDQ_BLOCK_SIZE), PAGE_SIZE)
+
+#define CMDQ_BASE_VADDR(cmdq_pages, wq) \
+ ((u64 *)(((u64)((cmdq_pages)->cmdq_page_vaddr)) \
+ + (u64)((wq)->block_idx * CMDQ_BLOCK_SIZE)))
+
+#define CMDQ_BASE_PADDR(cmdq_pages, wq) \
+ (((u64)((cmdq_pages)->cmdq_page_paddr)) \
+ + (u64)(wq)->block_idx * CMDQ_BLOCK_SIZE)
+
+#define CMDQ_BASE_ADDR(cmdq_pages, wq) \
+ ((u64 *)(((u64)((cmdq_pages)->cmdq_shadow_page_vaddr)) \
+ + (u64)((wq)->block_idx * CMDQ_BLOCK_SIZE)))
+
+#define MASKED_WQE_IDX(wq, idx) ((idx) & (wq)->mask)
+
+#define WQ_WQE_ADDR(wq, idx) ((void *)((u64)((wq)->queue_buf_vaddr) + \
+ ((idx) << (wq)->wqebb_shift)))
+
+struct spnic_wq {
+ /* The addresses are 64 bit in the HW */
+ u64 queue_buf_vaddr;
+
+ u16 q_depth;
+ u16 mask;
+ rte_atomic32_t delta;
+
+ u32 cons_idx;
+ u32 prod_idx;
+
+ u64 queue_buf_paddr;
+
+ u32 wqebb_size;
+ u32 wqebb_shift;
+
+ u32 wq_buf_size;
+
+ const struct rte_memzone *wq_mz;
+
+ u32 rsvd[5];
+};
+
+#endif /* _SPNIC_WQ_H_ :*/