From mboxrd@z Thu Jan 1 00:00:00 1970 Return-Path: Received: from mails.dpdk.org (mails.dpdk.org [217.70.189.124]) by inbox.dpdk.org (Postfix) with ESMTP id EE822A00C5; Fri, 24 Dec 2021 09:33:31 +0100 (CET) Received: from [217.70.189.124] (localhost [127.0.0.1]) by mails.dpdk.org (Postfix) with ESMTP id 4A40E4115B; Fri, 24 Dec 2021 09:33:12 +0100 (CET) Received: from VLXDG1SPAM1.ramaxel.com (email.ramaxel.com [221.4.138.186]) by mails.dpdk.org (Postfix) with ESMTP id 37F4341156 for ; Fri, 24 Dec 2021 09:33:10 +0100 (CET) Received: from V12DG1MBS01.ramaxel.local (v12dg1mbs01.ramaxel.local [172.26.18.31]) by VLXDG1SPAM1.ramaxel.com with ESMTPS id 1BO8Wocc043401 (version=TLSv1.2 cipher=AES256-GCM-SHA384 bits=256 verify=FAIL); Fri, 24 Dec 2021 16:32:50 +0800 (GMT-8) (envelope-from songyl@ramaxel.com) Received: from localhost.localdomain (10.64.9.47) by V12DG1MBS01.ramaxel.local (172.26.18.31) with Microsoft SMTP Server (version=TLS1_2, cipher=TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA256_P256) id 15.1.2308.14; Fri, 24 Dec 2021 16:32:50 +0800 From: Yanling Song To: CC: , , , , Subject: [PATCH v3 06/25] net/spnic: add cmdq and work queue Date: Fri, 24 Dec 2021 16:32:24 +0800 Message-ID: <698dfe2c1a1f27bdd3069fa50850e7de62802073.1640332922.git.songyl@ramaxel.com> X-Mailer: git-send-email 2.17.1 In-Reply-To: References: MIME-Version: 1.0 Content-Type: text/plain X-Originating-IP: [10.64.9.47] X-ClientProxiedBy: V12DG1MBS03.ramaxel.local (172.26.18.33) To V12DG1MBS01.ramaxel.local (172.26.18.31) X-DNSRBL: X-MAIL: VLXDG1SPAM1.ramaxel.com 1BO8Wocc043401 X-BeenThere: dev@dpdk.org X-Mailman-Version: 2.1.29 Precedence: list List-Id: DPDK patches and discussions List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Errors-To: dev-bounces@dpdk.org This commit introduce cmdq and work queue which can be used to send bulk message data(up to 2KB) to hardware. cmdq provides a mechanism to encapsulate the message to be sent and handle the response data or status. work queue is used to manager the wqe in which includes message data buffer description, ctrl info, header info and response message data buffer. This patch implements the initialization and data structure. Signed-off-by: Yanling Song --- drivers/net/spnic/base/meson.build | 4 +- drivers/net/spnic/base/spnic_cmdq.c | 202 ++++++++++++++++++++++ drivers/net/spnic/base/spnic_cmdq.h | 228 +++++++++++++++++++++++++ drivers/net/spnic/base/spnic_hw_comm.c | 222 ++++++++++++++++++++++++ drivers/net/spnic/base/spnic_hw_comm.h | 176 +++++++++++++++++++ drivers/net/spnic/base/spnic_hwdev.c | 215 +++++++++++++++++++++++ drivers/net/spnic/base/spnic_hwdev.h | 8 +- drivers/net/spnic/base/spnic_wq.h | 57 +++++++ 8 files changed, 1109 insertions(+), 3 deletions(-) create mode 100644 drivers/net/spnic/base/spnic_cmdq.c create mode 100644 drivers/net/spnic/base/spnic_cmdq.h create mode 100644 drivers/net/spnic/base/spnic_hw_comm.c create mode 100644 drivers/net/spnic/base/spnic_hw_comm.h create mode 100644 drivers/net/spnic/base/spnic_wq.h diff --git a/drivers/net/spnic/base/meson.build b/drivers/net/spnic/base/meson.build index 3f6a060b37..5e4efac7be 100644 --- a/drivers/net/spnic/base/meson.build +++ b/drivers/net/spnic/base/meson.build @@ -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 = [] diff --git a/drivers/net/spnic/base/spnic_cmdq.c b/drivers/net/spnic/base/spnic_cmdq.c new file mode 100644 index 0000000000..ccfcf739a0 --- /dev/null +++ b/drivers/net/spnic/base/spnic_cmdq.c @@ -0,0 +1,202 @@ +/* SPDX-License-Identifier: BSD-3-Clause + * Copyright(c) 2021 Ramaxel Memory Technology, Ltd + */ + +#include + +#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); +} diff --git a/drivers/net/spnic/base/spnic_cmdq.h b/drivers/net/spnic/base/spnic_cmdq.h new file mode 100644 index 0000000000..49fc1b1684 --- /dev/null +++ b/drivers/net/spnic/base/spnic_cmdq.h @@ -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_ */ diff --git a/drivers/net/spnic/base/spnic_hw_comm.c b/drivers/net/spnic/base/spnic_hw_comm.c new file mode 100644 index 0000000000..7c58989c14 --- /dev/null +++ b/drivers/net/spnic/base/spnic_hw_comm.c @@ -0,0 +1,222 @@ +/* SPDX-License-Identifier: BSD-3-Clause + * Copyright(c) 2021 Ramaxel Memory Technology, Ltd + */ + +#include +#include +#include +#include + +#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; +} diff --git a/drivers/net/spnic/base/spnic_hw_comm.h b/drivers/net/spnic/base/spnic_hw_comm.h new file mode 100644 index 0000000000..3b2373e027 --- /dev/null +++ b/drivers/net/spnic/base/spnic_hw_comm.h @@ -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 diff --git a/drivers/net/spnic/base/spnic_hwdev.c b/drivers/net/spnic/base/spnic_hwdev.c index 9059276cdc..6d42d20da2 100644 --- a/drivers/net/spnic/base/spnic_hwdev.c +++ b/drivers/net/spnic/base/spnic_hwdev.c @@ -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); } diff --git a/drivers/net/spnic/base/spnic_hwdev.h b/drivers/net/spnic/base/spnic_hwdev.h index 766d820683..78c5387578 100644 --- a/drivers/net/spnic/base/spnic_hwdev.h +++ b/drivers/net/spnic/base/spnic_hwdev.h @@ -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; diff --git a/drivers/net/spnic/base/spnic_wq.h b/drivers/net/spnic/base/spnic_wq.h new file mode 100644 index 0000000000..032d45e79e --- /dev/null +++ b/drivers/net/spnic/base/spnic_wq.h @@ -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_ :*/ -- 2.32.0