From patchwork Tue Aug 29 07:58:06 2023 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Renyong Wan X-Patchwork-Id: 130794 X-Patchwork-Delegate: thomas@monjalon.net Return-Path: X-Original-To: patchwork@inbox.dpdk.org Delivered-To: patchwork@inbox.dpdk.org Received: from mails.dpdk.org (mails.dpdk.org [217.70.189.124]) by inbox.dpdk.org (Postfix) with ESMTP id 31A5B41F53; Tue, 29 Aug 2023 10:00:06 +0200 (CEST) Received: from mails.dpdk.org (localhost [127.0.0.1]) by mails.dpdk.org (Postfix) with ESMTP id 332FF4029F; Tue, 29 Aug 2023 09:59:40 +0200 (CEST) Received: from VLXDG1SPAM1.ramaxel.com (email.ramaxel.com [221.4.138.186]) by mails.dpdk.org (Postfix) with ESMTP id 24B1A402B1 for ; Tue, 29 Aug 2023 09:59:36 +0200 (CEST) Received: from V12DG1MBS03.ramaxel.local ([172.26.18.33]) by VLXDG1SPAM1.ramaxel.com with ESMTP id 37T7wrM8080563; Tue, 29 Aug 2023 15:58:59 +0800 (GMT-8) (envelope-from wanry@3snic.com) Received: from localhost.localdomain (10.64.136.151) by V12DG1MBS03.ramaxel.local (172.26.18.33) with Microsoft SMTP Server (version=TLS1_2, cipher=TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA256_P256) id 15.1.2375.17; Tue, 29 Aug 2023 15:58:40 +0800 From: To: CC: , Renyong Wan , Steven Song Subject: [PATCH 09/32] net/sssnic/base: add control queue Date: Tue, 29 Aug 2023 15:58:06 +0800 Message-ID: <20230829075829.208413-10-wanry@3snic.com> X-Mailer: git-send-email 2.25.1 In-Reply-To: <20230829075829.208413-1-wanry@3snic.com> References: <20230829075829.208413-1-wanry@3snic.com> MIME-Version: 1.0 X-Originating-IP: [10.64.136.151] X-ClientProxiedBy: V12DG1MBS03.ramaxel.local (172.26.18.33) To V12DG1MBS03.ramaxel.local (172.26.18.33) X-DNSRBL: X-SPAM-SOURCE-CHECK: pass X-MAIL: VLXDG1SPAM1.ramaxel.com 37T7wrM8080563 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 From: Renyong Wan Control queue is used for communication between driver and datapath code of firmware. Signed-off-by: Steven Song Signed-off-by: Renyong Wan --- drivers/net/sssnic/base/meson.build | 2 + drivers/net/sssnic/base/sssnic_api.c | 102 +++++ drivers/net/sssnic/base/sssnic_api.h | 23 ++ drivers/net/sssnic/base/sssnic_cmd.h | 114 ++++++ drivers/net/sssnic/base/sssnic_ctrlq.c | 519 +++++++++++++++++++++++++ drivers/net/sssnic/base/sssnic_ctrlq.h | 58 +++ drivers/net/sssnic/base/sssnic_hw.c | 149 +++++++ drivers/net/sssnic/base/sssnic_hw.h | 8 + 8 files changed, 975 insertions(+) create mode 100644 drivers/net/sssnic/base/sssnic_api.c create mode 100644 drivers/net/sssnic/base/sssnic_api.h create mode 100644 drivers/net/sssnic/base/sssnic_cmd.h create mode 100644 drivers/net/sssnic/base/sssnic_ctrlq.c create mode 100644 drivers/net/sssnic/base/sssnic_ctrlq.h diff --git a/drivers/net/sssnic/base/meson.build b/drivers/net/sssnic/base/meson.build index 7c23a82ff3..e93ca7b24b 100644 --- a/drivers/net/sssnic/base/meson.build +++ b/drivers/net/sssnic/base/meson.build @@ -7,6 +7,8 @@ sources = [ 'sssnic_msg.c', 'sssnic_mbox.c', 'sssnic_workq.c', + 'sssnic_ctrlq.c', + 'sssnic_api.c', ] c_args = cflags diff --git a/drivers/net/sssnic/base/sssnic_api.c b/drivers/net/sssnic/base/sssnic_api.c new file mode 100644 index 0000000000..51a59f0f25 --- /dev/null +++ b/drivers/net/sssnic/base/sssnic_api.c @@ -0,0 +1,102 @@ +/* SPDX-License-Identifier: BSD-3-Clause + * Copyright(c) 2018-2022 Shenzhen 3SNIC Information Technology Co., Ltd. + */ + +#include +#include +#include +#include + +#include "../sssnic_log.h" +#include "sssnic_hw.h" +#include "sssnic_cmd.h" +#include "sssnic_mbox.h" +#include "sssnic_api.h" + +int +sssnic_msix_attr_get(struct sssnic_hw *hw, uint16_t msix_idx, + struct sssnic_msix_attr *attr) +{ + int ret; + struct sssnic_msg msg; + struct sssnic_msix_ctrl_cmd cmd; + uint32_t cmd_len; + + memset(&cmd, 0, sizeof(cmd)); + cmd.func_id = SSSNIC_FUNC_IDX(hw); + cmd.opcode = SSSNIC_CMD_OPCODE_GET; + cmd.idx = msix_idx; + cmd_len = sizeof(cmd); + sssnic_msg_init(&msg, (uint8_t *)&cmd, cmd_len, SSSNIC_MSIX_CTRL_CMD, + SSSNIC_MPU_FUNC_IDX, SSSNIC_COMM_MODULE, SSSNIC_MSG_TYPE_REQ); + ret = sssnic_mbox_send(hw, &msg, (uint8_t *)&cmd, &cmd_len, 0); + if (ret != 0) { + PMD_DRV_LOG(ERR, "Failed to send mbox message, ret=%d", ret); + return ret; + } + if (cmd_len == 0 || cmd.common.status != 0) { + PMD_DRV_LOG(ERR, + "Bad response to MSIX_CTRL_CMD, len=%u, status=%u", + cmd_len, cmd.common.status); + return -EIO; + } + attr->lli_credit = cmd.lli_credit; + attr->lli_timer = cmd.lli_timer; + attr->pending_limit = cmd.pending_count; + attr->coalescing_timer = cmd.coalescing_timer; + attr->resend_timer = cmd.resend_timer; + + return 0; +} + +int +sssnic_msix_attr_set(struct sssnic_hw *hw, uint16_t msix_idx, + struct sssnic_msix_attr *attr) +{ + int ret; + struct sssnic_msg msg; + struct sssnic_msix_ctrl_cmd cmd; + struct sssnic_msix_attr tmp; + uint32_t cmd_len; + + ret = sssnic_msix_attr_get(hw, msix_idx, &tmp); + if (ret != 0) { + PMD_DRV_LOG(ERR, "Failed to get interrupt configuration"); + return ret; + } + + memset(&cmd, 0, sizeof(cmd)); + cmd.func_id = SSSNIC_FUNC_IDX(hw); + cmd.opcode = SSSNIC_CMD_OPCODE_SET; + cmd.idx = msix_idx; + cmd.lli_credit = tmp.lli_credit; + cmd.lli_timer = tmp.lli_timer; + cmd.pending_count = tmp.pending_limit; + cmd.coalescing_timer = tmp.coalescing_timer; + cmd.resend_timer = tmp.resend_timer; + if (attr->lli_set != 0) { + cmd.lli_credit = attr->lli_credit; + cmd.lli_timer = attr->lli_timer; + } + if (attr->coalescing_set != 0) { + cmd.pending_count = attr->pending_limit; + cmd.coalescing_timer = attr->coalescing_timer; + cmd.resend_timer = attr->resend_timer; + } + cmd_len = sizeof(cmd); + sssnic_msg_init(&msg, (uint8_t *)&cmd, cmd_len, SSSNIC_MSIX_CTRL_CMD, + SSSNIC_MPU_FUNC_IDX, SSSNIC_COMM_MODULE, SSSNIC_MSG_TYPE_REQ); + ret = sssnic_mbox_send(hw, &msg, (uint8_t *)&cmd, &cmd_len, 0); + if (ret != 0) { + PMD_DRV_LOG(ERR, "Failed to send mbox message, ret=%d", ret); + return ret; + } + if (cmd_len == 0 || cmd.common.status != 0) { + PMD_DRV_LOG(ERR, + "Bad response to MSIX_CTRL_CMD, len=%u, status=%u", + cmd_len, cmd.common.status); + return -EIO; + } + + return 0; +} diff --git a/drivers/net/sssnic/base/sssnic_api.h b/drivers/net/sssnic/base/sssnic_api.h new file mode 100644 index 0000000000..3d54eb826a --- /dev/null +++ b/drivers/net/sssnic/base/sssnic_api.h @@ -0,0 +1,23 @@ +/* SPDX-License-Identifier: BSD-3-Clause + * Copyright(c) 2018-2022 Shenzhen 3SNIC Information Technology Co., Ltd. + */ + +#ifndef _SSSNIC_API_H_ +#define _SSSNIC_API_H_ + +struct sssnic_msix_attr { + uint32_t lli_set; + uint32_t coalescing_set; + uint8_t lli_credit; + uint8_t lli_timer; + uint8_t pending_limit; + uint8_t coalescing_timer; + uint8_t resend_timer; +}; + +int sssnic_msix_attr_get(struct sssnic_hw *hw, uint16_t msix_idx, + struct sssnic_msix_attr *attr); +int sssnic_msix_attr_set(struct sssnic_hw *hw, uint16_t msix_idx, + struct sssnic_msix_attr *attr); + +#endif /* _SSSNIC_API_H_ */ diff --git a/drivers/net/sssnic/base/sssnic_cmd.h b/drivers/net/sssnic/base/sssnic_cmd.h new file mode 100644 index 0000000000..ee9f536ac2 --- /dev/null +++ b/drivers/net/sssnic/base/sssnic_cmd.h @@ -0,0 +1,114 @@ +/* SPDX-License-Identifier: BSD-3-Clause + * Copyright(c) 2018-2022 Shenzhen 3SNIC Information Technology Co., Ltd. + */ + +#ifndef _SSSNIC_CMD_H_ +#define _SSSNIC_CMD_H_ + +#define SSSNIC_CMD_OPCODE_SET 1 +#define SSSNIC_CMD_OPCODE_GET 0 + +enum sssnic_mgmt_cmd_id { + SSSNIC_RESET_FUNC_CMD = 0, + SSSNIC_SET_CTRLQ_CTX_CMD = 20, + SSSNIC_SET_ROOT_CTX_CMD = 21, + SSSNIC_PAGESIZE_CFG_CMD = 22, + SSSNIC_MSIX_CTRL_CMD = 23, + SSSNIC_SET_DMA_ATTR_CMD = 25, + SSSNIC_GET_FW_VERSION_CMD = 60, +}; + +struct sssnic_cmd_common { + uint8_t status; + uint8_t version; + uint8_t resvd[6]; +}; + +struct sssnic_set_ctrlq_ctx_cmd { + struct sssnic_cmd_common common; + uint16_t func_id; + /* CtrlQ ID, here always is 0 */ + uint8_t qid; + uint8_t resvd[5]; + union { + uint64_t data[2]; + struct { + /* Page frame number*/ + uint64_t pfn : 52; + uint64_t resvd0 : 4; + /* Completion event queue ID*/ + uint64_t eq_id : 5; + /* Interrupt enable indication */ + uint64_t informed : 1; + /* Completion event queue enable indication */ + uint64_t eq_en : 1; + /* Entries wrapped indication */ + uint64_t wrapped : 1; + uint64_t block_pfn : 52; + uint64_t start_ci : 12; + }; + }; +}; + +struct sssnic_dma_attr_set_cmd { + struct sssnic_cmd_common common; + uint16_t func_id; + uint8_t idx; + uint8_t st; + uint8_t at; + uint8_t ph; + uint8_t no_snooping; + uint8_t tph; + uint32_t resvd0; +}; + +struct sssnic_func_reset_cmd { + struct sssnic_cmd_common common; + uint16_t func_id; + uint16_t resvd[3]; + /* Mask of reource to be reset */ + uint64_t res_mask; +}; + +struct sssnic_root_ctx_cmd { + struct sssnic_cmd_common common; + uint16_t func_id; + /* set ctrlq depth enable */ + uint8_t set_ctrlq_depth; + /* real depth is 2^ctrlq_depth */ + uint8_t ctrlq_depth; + uint16_t rx_buf; + uint8_t lro_enable; + uint8_t resvd0; + uint16_t txq_depth; + uint16_t rxq_depth; + uint64_t resvd1; +}; + +struct sssnic_pagesize_cmd { + struct sssnic_cmd_common common; + uint16_t func_id; + /* SSSNIC_CMD_OPCODE_xx */ + uint8_t opcode; + /* real size is (2^pagesz)*4KB */ + uint8_t pagesz; + uint32_t resvd0; +}; + +struct sssnic_msix_ctrl_cmd { + struct sssnic_cmd_common common; + uint16_t func_id; + /* SSSNIC_CMD_OPCODE_xx */ + uint8_t opcode; + uint8_t resvd0; + /* MSIX index */ + uint16_t idx; + uint8_t pending_count; + uint8_t coalescing_timer; + uint8_t resend_timer; + uint8_t lli_timer; + uint8_t lli_credit; + uint8_t resvd1[5]; +}; + +#endif /* _SSSNIC_CMD_H_ */ diff --git a/drivers/net/sssnic/base/sssnic_ctrlq.c b/drivers/net/sssnic/base/sssnic_ctrlq.c new file mode 100644 index 0000000000..75cd25f441 --- /dev/null +++ b/drivers/net/sssnic/base/sssnic_ctrlq.c @@ -0,0 +1,519 @@ +/* SPDX-License-Identifier: BSD-3-Clause + * Copyright(c) 2018-2022 Shenzhen 3SNIC Information Technology Co., Ltd. + */ + +#include +#include +#include +#include +#include + +#include "../sssnic_log.h" +#include "sssnic_hw.h" +#include "sssnic_reg.h" +#include "sssnic_cmd.h" +#include "sssnic_mbox.h" +#include "sssnic_ctrlq.h" + +#define SSSNIC_CTRLQ_DOORBELL_OFFSET 0 +#define SSSNIC_CTRLQ_BUF_SIZE 4096 +#define SSSNIC_CTRLQ_ENTRY_SIZE 64 +#define SSSNIC_CTRLQ_DEPTH 64 + +#define SSSNIC_CTRLQ_RESP_TIMEOUT 5000 /* Default response timeout */ + +enum sssnic_ctrlq_response_fmt { + /* return result and write it back into corresponding field of ctrlq entry */ + SSSNIC_CTRLQ_RESPONSE_RESULT, + /* return data write it into DMA memory that usually is pktmbuf*/ + SSSNIC_CTRLQ_RESPONSE_DATA, +}; + +struct sssnic_ctrlq_entry_desc_section { + union { + uint32_t dword; + struct { + /* buffer section length, always 2*/ + uint32_t buf_sec_len : 8; + uint32_t resvd0 : 7; + /* response fmt, 0:result 1:data */ + uint32_t resp_fmt : 1; + uint32_t resvd1 : 6; + /* buffer data format,always 0 */ + uint32_t buf_fmt : 1; + /* always 1 */ + uint32_t need_resp : 1; + uint32_t resvd2 : 3; + /* response section length, always 3 */ + uint32_t resp_sec_len : 2; + /* control section length, always 1 */ + uint32_t ctrl_sec_len : 2; + /* wrapped bit */ + uint32_t wrapped : 1; + }; + }; +}; + +struct sssnic_ctrlq_entry_status_section { + union { + uint32_t dword; + struct { + /* status value, usually it saves error code */ + uint32_t value : 31; + uint32_t resvd0 : 1; + }; + }; +}; + +struct sssnic_ctrlq_entry_ctrl_section { + union { + uint32_t dword; + struct { + /* producer index*/ + uint32_t pi : 16; + /* command ID */ + uint32_t cmd : 8; + /* hardware module */ + uint32_t module : 5; + uint32_t resvd0 : 2; + /* Indication of command done */ + uint32_t done : 1; + }; + }; +}; + +struct sssnic_ctrlq_entry_response_section { + union { + struct { + uint32_t hi_addr; + uint32_t lo_addr; + uint32_t len; + uint32_t resvd0; + } data; + struct { + uint64_t value; + uint64_t resvd0; + } result; + }; +}; + +struct sssnic_ctrlq_entry_buf_section { + struct { + uint32_t hi_addr; + uint32_t lo_addr; + uint32_t len; + uint32_t resvd0; + } sge; + uint64_t resvd0[2]; +}; + +/* Hardware format of control queue entry */ +struct sssnic_ctrlq_entry { + union { + uint32_t dword[16]; + struct { + struct sssnic_ctrlq_entry_desc_section desc; + uint32_t resvd0; + struct sssnic_ctrlq_entry_status_section status; + struct sssnic_ctrlq_entry_ctrl_section ctrl; + struct sssnic_ctrlq_entry_response_section response; + struct sssnic_ctrlq_entry_buf_section buf; + }; + }; +}; + +/* Hardware format of control queue doorbell */ +struct sssnic_ctrlq_doorbell { + union { + uint64_t u64; + struct { + uint64_t resvd0 : 23; + /* ctrlq type is always 1*/ + uint64_t qtype : 1; + /* cltrq id is always 0*/ + uint64_t qid : 3; + uint64_t resvd1 : 5; + /* most significant byte of pi*/ + uint64_t pi_msb : 8; + uint64_t resvd2 : 24; + }; + }; +}; +static int +sssnic_ctrlq_wait_response(struct sssnic_ctrlq *ctrlq, int *err_code, + uint32_t timeout_ms) +{ + struct sssnic_ctrlq_entry *entry; + struct sssnic_workq *workq; + uint64_t end; + int done = 0; + + workq = ctrlq->workq; + entry = (struct sssnic_ctrlq_entry *)sssnic_workq_peek(workq); + if (entry == NULL) { + PMD_DRV_LOG(ERR, "Not found executing ctrlq command"); + return -EINVAL; + } + if (timeout_ms == 0) + timeout_ms = SSSNIC_CTRLQ_RESP_TIMEOUT; + end = rte_get_timer_cycles() + rte_get_timer_hz() * timeout_ms / 1000; + do { + done = entry->ctrl.done; + if (done) + break; + rte_delay_us(1); + } while (((long)(rte_get_timer_cycles() - end)) < 0); + + if (!done) { + PMD_DRV_LOG(ERR, "Waiting ctrlq response timeout, ci=%u", + workq->ci); + return -ETIMEDOUT; + } + if (err_code) + *err_code = entry->status.value; + sssnic_workq_consume(workq, 1, NULL); + return 0; +} + +static void +sssnic_ctrlq_doorbell_ring(struct sssnic_ctrlq *ctrlq, uint16_t next_pi) +{ + struct sssnic_ctrlq_doorbell db; + + db.u64 = 0; + db.qtype = 1; + db.qid = 0; + db.pi_msb = (next_pi >> 8) & 0xff; + rte_wmb(); + rte_write64(db.u64, ctrlq->doorbell + ((next_pi & 0xff) << 3)); +} + +static void +sssnic_ctrlq_entry_init(struct sssnic_ctrlq_entry *entry, struct rte_mbuf *mbuf, + struct sssnic_ctrlq_cmd *cmd, uint16_t pi, uint16_t wrapped) +{ + struct sssnic_ctrlq_entry tmp_entry; + void *buf_addr; + rte_iova_t buf_iova; + + /* Fill the temporary ctrlq entry */ + memset(&tmp_entry, 0, sizeof(tmp_entry)); + tmp_entry.desc.buf_fmt = 0; + tmp_entry.desc.buf_sec_len = 2; + tmp_entry.desc.need_resp = 1; + tmp_entry.desc.resp_sec_len = 3; + tmp_entry.desc.ctrl_sec_len = 1; + tmp_entry.desc.wrapped = wrapped; + + tmp_entry.status.value = 0; + + tmp_entry.ctrl.cmd = cmd->cmd; + tmp_entry.ctrl.pi = pi; + tmp_entry.ctrl.module = cmd->module; + tmp_entry.ctrl.done = 0; + + buf_iova = rte_mbuf_data_iova(mbuf); + if (cmd->mbuf == NULL && cmd->data != NULL) { + /* cmd data is not allocated in mbuf*/ + buf_addr = rte_pktmbuf_mtod(mbuf, void *); + rte_memcpy(buf_addr, cmd->data, cmd->data_len); + } + tmp_entry.buf.sge.hi_addr = (uint32_t)((buf_iova >> 16) >> 16); + tmp_entry.buf.sge.lo_addr = (uint32_t)buf_iova; + tmp_entry.buf.sge.len = cmd->data_len; + + if (cmd->response_len == 0) { + tmp_entry.desc.resp_fmt = SSSNIC_CTRLQ_RESPONSE_RESULT; + tmp_entry.response.result.value = 0; + } else { + tmp_entry.desc.resp_fmt = SSSNIC_CTRLQ_RESPONSE_DATA; + /* response sge shares cmd mbuf */ + tmp_entry.response.data.hi_addr = + (uint32_t)((buf_iova >> 16) >> 16); + tmp_entry.response.data.lo_addr = (uint32_t)buf_iova; + tmp_entry.response.data.len = SSSNIC_CTRLQ_MBUF_SIZE; + } + + /* write temporary entry to real ctrlq entry + * the first 64bits must be copied last + */ + rte_memcpy(((uint8_t *)entry) + sizeof(uint64_t), + ((uint8_t *)&tmp_entry) + sizeof(uint64_t), + SSSNIC_CTRLQ_ENTRY_SIZE - sizeof(sizeof(uint64_t))); + rte_wmb(); + *((uint64_t *)entry) = *((uint64_t *)&tmp_entry); +} + +static int +sssnic_ctrlq_cmd_exec_internal(struct sssnic_ctrlq *ctrlq, + struct sssnic_ctrlq_cmd *cmd, uint32_t timeout_ms) +{ + struct rte_mbuf *mbuf; + struct sssnic_ctrlq_entry *entry; + struct sssnic_workq *workq; + uint16_t pi; /* current pi */ + uint16_t next_pi; + uint16_t wrapped; + int ret; + int err_code; + + /* Allocate cmd mbuf */ + if (cmd->mbuf == NULL) { + mbuf = rte_pktmbuf_alloc(ctrlq->mbuf_pool); + if (mbuf == NULL) { + PMD_DRV_LOG(ERR, "Could not alloc mbuf for ctrlq cmd"); + return -ENOMEM; + } + } else { + mbuf = cmd->mbuf; + } + + /* allocate ctrlq entry */ + workq = ctrlq->workq; + wrapped = ctrlq->wrapped; + entry = (struct sssnic_ctrlq_entry *)sssnic_workq_produce(workq, 1, + &pi); + if (entry == NULL) { + PMD_DRV_LOG(ERR, "No enough control queue entry"); + ret = -EBUSY; + goto out; + } + /* workq->pi will be the next pi, the next pi could not exceed workq + * depth else must recalculate next pi, and reverse wrapped bit. + */ + if (workq->pi >= workq->num_entries) { + ctrlq->wrapped = !ctrlq->wrapped; + workq->pi -= workq->num_entries; + } + next_pi = workq->pi; + + /* fill ctrlq entry */ + sssnic_ctrlq_entry_init(entry, mbuf, cmd, pi, wrapped); + + /* Ring doorbell */ + sssnic_ctrlq_doorbell_ring(ctrlq, next_pi); + + /* Wait response */ + ret = sssnic_ctrlq_wait_response(ctrlq, &err_code, timeout_ms); + if (ret != 0) + goto out; + + if (err_code) { + PMD_DRV_LOG(ERR, + "Found error while control queue command executing, error code:%x.", + err_code); + ret = err_code; + goto out; + } + + if (cmd->response_len == 0) { + cmd->result = entry->response.result.value; + } else if ((cmd->mbuf != NULL && cmd->response_data != cmd->data) || + cmd->mbuf == NULL) { + /* cmd data may be as same as response data if mbuf is not null */ + rte_memcpy(cmd->response_data, rte_pktmbuf_mtod(mbuf, void *), + cmd->response_len); + } +out: + if (cmd->mbuf == NULL) + rte_pktmbuf_free(mbuf); + return ret; +} + +int +sssnic_ctrlq_cmd_exec(struct sssnic_hw *hw, struct sssnic_ctrlq_cmd *cmd, + uint32_t timeout_ms) +{ + int ret; + struct sssnic_ctrlq *ctrlq; + + if (hw == NULL || hw->ctrlq == NULL || cmd == NULL || + (cmd->response_len != 0 && cmd->response_data == NULL)) { + PMD_DRV_LOG(ERR, "Bad parameter to execute ctrlq command"); + return -EINVAL; + } + + SSSNIC_DEBUG("module=%u, cmd=%u, data=%p, data_len=%u, response_len=%u", + cmd->module, cmd->cmd, cmd->data, cmd->data_len, + cmd->response_len); + + ctrlq = hw->ctrlq; + rte_spinlock_lock(&ctrlq->lock); + ret = sssnic_ctrlq_cmd_exec_internal(ctrlq, cmd, timeout_ms); + rte_spinlock_unlock(&ctrlq->lock); + + return ret; +} + +static int +sssnic_ctrlq_depth_set(struct sssnic_hw *hw, uint32_t depth) +{ + int ret; + struct sssnic_msg msg; + struct sssnic_root_ctx_cmd cmd; + uint32_t cmd_len; + + memset(&cmd, 0, sizeof(cmd)); + cmd.func_id = SSSNIC_FUNC_IDX(hw); + cmd.set_ctrlq_depth = 1; + cmd.ctrlq_depth = (uint8_t)rte_log2_u32(depth); + sssnic_msg_init(&msg, (uint8_t *)&cmd, cmd_len, SSSNIC_SET_ROOT_CTX_CMD, + SSSNIC_MPU_FUNC_IDX, SSSNIC_COMM_MODULE, SSSNIC_MSG_TYPE_REQ); + ret = sssnic_mbox_send(hw, &msg, (uint8_t *)&cmd, &cmd_len, 0); + if (ret != 0) { + PMD_DRV_LOG(ERR, "Failed to send mbox message, ret=%d", ret); + return ret; + } + if (!cmd_len || cmd.common.status) { + PMD_DRV_LOG(ERR, + "Bad response to SET_ROOT_CTX_CMD, len=%u, status=%u", + cmd_len, cmd.common.status); + return -EIO; + } + return 0; +} + +static int +sssnic_ctrlq_ctx_setup(struct sssnic_ctrlq *ctrlq) +{ + int ret; + struct sssnic_msg msg; + struct sssnic_set_ctrlq_ctx_cmd cmd; + uint32_t cmd_len; + struct sssnic_hw *hw = ctrlq->hw; + + memset(&cmd, 0, sizeof(cmd)); + cmd.func_id = SSSNIC_FUNC_IDX(hw); + cmd.qid = 0; + cmd.pfn = ctrlq->workq->buf_phyaddr / RTE_PGSIZE_4K; + cmd.wrapped = !!ctrlq->wrapped; + cmd.start_ci = 0; + cmd.block_pfn = cmd.pfn; + + cmd_len = sizeof(cmd); + sssnic_msg_init(&msg, (uint8_t *)&cmd, cmd_len, + SSSNIC_SET_CTRLQ_CTX_CMD, SSSNIC_MPU_FUNC_IDX, + SSSNIC_COMM_MODULE, SSSNIC_MSG_TYPE_REQ); + ret = sssnic_mbox_send(hw, &msg, (uint8_t *)&cmd, &cmd_len, 0); + if (ret != 0) { + PMD_DRV_LOG(ERR, "Failed to send SSSNIC_SET_CTRLQ_CTX_CMD"); + return ret; + } + return 0; +} + +struct sssnic_ctrlq_cmd * +sssnic_ctrlq_cmd_alloc(struct sssnic_hw *hw) +{ + struct sssnic_ctrlq_cmd *cmd; + + cmd = rte_zmalloc(NULL, sizeof(struct sssnic_ctrlq_cmd), 0); + if (cmd == NULL) { + PMD_DRV_LOG(ERR, "Failed to allocate sssnic_ctrlq_cmd"); + return NULL; + } + + cmd->mbuf = rte_pktmbuf_alloc(hw->ctrlq->mbuf_pool); + if (cmd->mbuf == NULL) { + PMD_DRV_LOG(ERR, "Failed to allocate sssnic_ctrlq_cmd mbuf"); + rte_free(cmd); + return NULL; + } + + cmd->data = rte_pktmbuf_mtod(cmd->mbuf, void *); + cmd->response_data = cmd->data; + + return cmd; +} + +void +sssnic_ctrlq_cmd_destroy(__rte_unused struct sssnic_hw *hw, + struct sssnic_ctrlq_cmd *cmd) +{ + if (cmd != NULL) { + if (cmd->mbuf != NULL) + rte_pktmbuf_free(cmd->mbuf); + + rte_free(cmd); + } +} + +int +sssnic_ctrlq_init(struct sssnic_hw *hw) +{ + int ret; + struct sssnic_ctrlq *ctrlq; + char m_name[RTE_MEMPOOL_NAMESIZE]; + + PMD_INIT_FUNC_TRACE(); + + ctrlq = rte_zmalloc(NULL, sizeof(struct sssnic_ctrlq), 0); + if (ctrlq == NULL) { + PMD_DRV_LOG(ERR, "Could not alloc memory for ctrlq"); + return -ENOMEM; + } + + ctrlq->hw = hw; + rte_spinlock_init(&ctrlq->lock); + ctrlq->doorbell = hw->db_base_addr + SSSNIC_CTRLQ_DOORBELL_OFFSET; + + snprintf(m_name, sizeof(m_name), "sssnic%u_ctrlq_wq", + SSSNIC_ETH_PORT_ID(hw)); + ctrlq->workq = sssnic_workq_new(m_name, rte_socket_id(), + SSSNIC_CTRLQ_ENTRY_SIZE, SSSNIC_CTRLQ_DEPTH); + if (ctrlq->workq == NULL) { + PMD_DRV_LOG(ERR, "Failed to alloc work queue for ctrlq"); + ret = -ENOMEM; + goto new_workq_fail; + } + ctrlq->wrapped = 1; + + snprintf(m_name, sizeof(m_name), "sssnic%u_ctrlq_mbuf", + SSSNIC_ETH_PORT_ID(hw)); + ctrlq->mbuf_pool = rte_pktmbuf_pool_create(m_name, SSSNIC_CTRLQ_DEPTH, + 0, 0, SSSNIC_CTRLQ_MBUF_SIZE, rte_socket_id()); + if (ctrlq->mbuf_pool == NULL) { + PMD_DRV_LOG(ERR, "Failed to alloc mbuf for %s", m_name); + ret = -ENOMEM; + goto alloc_mbuf_fail; + } + + ret = sssnic_ctrlq_ctx_setup(ctrlq); + if (ret != 0) { + PMD_DRV_LOG(ERR, "Failed to setup control queue context"); + goto setup_ctrlq_ctx_fail; + } + + ret = sssnic_ctrlq_depth_set(hw, SSSNIC_CTRLQ_DEPTH); + if (ret != 0) { + PMD_DRV_LOG(ERR, "Failed to initialize control queue depth"); + goto setup_ctrlq_ctx_fail; + } + + hw->ctrlq = ctrlq; + + return 0; + +setup_ctrlq_ctx_fail: + rte_mempool_free(ctrlq->mbuf_pool); +alloc_mbuf_fail: + sssnic_workq_destroy(ctrlq->workq); +new_workq_fail: + rte_free(ctrlq); + return ret; +} + +void +sssnic_ctrlq_shutdown(struct sssnic_hw *hw) +{ + struct sssnic_ctrlq *ctrlq; + + PMD_INIT_FUNC_TRACE(); + + if (hw == NULL || hw->ctrlq == NULL) + return; + ctrlq = hw->ctrlq; + rte_mempool_free(ctrlq->mbuf_pool); + sssnic_workq_destroy(ctrlq->workq); + rte_free(ctrlq); +} diff --git a/drivers/net/sssnic/base/sssnic_ctrlq.h b/drivers/net/sssnic/base/sssnic_ctrlq.h new file mode 100644 index 0000000000..61b182e9f4 --- /dev/null +++ b/drivers/net/sssnic/base/sssnic_ctrlq.h @@ -0,0 +1,58 @@ +/* SPDX-License-Identifier: BSD-3-Clause + * Copyright(c) 2018-2022 Shenzhen 3SNIC Information Technology Co., Ltd. + */ + +#ifndef _SSSNIC_CTRLQ_H_ +#define _SSSNIC_CTRLQ_H_ + +#include "sssnic_workq.h" + +#define SSSNIC_CTRLQ_MBUF_SIZE 2048 +#define SSSNIC_CTRLQ_MAX_CMD_DATA_LEN \ + (SSSNIC_CTRLQ_MBUF_SIZE - RTE_PKTMBUF_HEADROOM) + +struct sssnic_ctrlq_cmd { + uint32_t module; + /* Command ID */ + uint32_t cmd; + /* Command data */ + void *data; + /* mbuf is just used for dynamic allocation of ctrlq cmd, + * cmd data will point to mbuf data to reduce data copying + * as well as response_data. + */ + struct rte_mbuf *mbuf; + union { + /* response data buffer */ + void *response_data; + /* result of command executing */ + uint64_t result; + }; + /* command data length */ + uint32_t data_len; + /* length of response data buffer, return result of command + * if response_len=0, else return response_data + */ + uint32_t response_len; +}; + +struct sssnic_ctrlq { + struct sssnic_hw *hw; + struct sssnic_workq *workq; + struct rte_mempool *mbuf_pool; + uint8_t *doorbell; + uint32_t wrapped; + uint32_t resvd0; + rte_spinlock_t lock; +}; + +struct sssnic_ctrlq_cmd *sssnic_ctrlq_cmd_alloc(struct sssnic_hw *hw); +void sssnic_ctrlq_cmd_destroy(__rte_unused struct sssnic_hw *hw, + struct sssnic_ctrlq_cmd *cmd); + +int sssnic_ctrlq_cmd_exec(struct sssnic_hw *hw, struct sssnic_ctrlq_cmd *cmd, + uint32_t timeout_ms); +int sssnic_ctrlq_init(struct sssnic_hw *hw); +void sssnic_ctrlq_shutdown(struct sssnic_hw *hw); + +#endif /* _SSSNIC_CTRLQ_H_ */ diff --git a/drivers/net/sssnic/base/sssnic_hw.c b/drivers/net/sssnic/base/sssnic_hw.c index ff527b2c7f..4ca75208af 100644 --- a/drivers/net/sssnic/base/sssnic_hw.c +++ b/drivers/net/sssnic/base/sssnic_hw.c @@ -9,9 +9,12 @@ #include "../sssnic_log.h" #include "sssnic_hw.h" #include "sssnic_reg.h" +#include "sssnic_cmd.h" +#include "sssnic_api.h" #include "sssnic_eventq.h" #include "sssnic_msg.h" #include "sssnic_mbox.h" +#include "sssnic_ctrlq.h" static int wait_for_sssnic_hw_ready(struct sssnic_hw *hw) @@ -140,6 +143,116 @@ sssnic_pf_status_set(struct sssnic_hw *hw, enum sssnic_pf_status status) sssnic_cfg_reg_write(hw, SSSNIC_ATTR6_REG, reg.u32); } +static int +sssnic_dma_attr_init(struct sssnic_hw *hw) +{ + int ret; + struct sssnic_msg msg; + struct sssnic_dma_attr_set_cmd cmd; + uint32_t cmd_len; + + memset(&cmd, 0, sizeof(cmd)); + cmd.func_id = SSSNIC_FUNC_IDX(hw); + cmd_len = sizeof(cmd); + sssnic_msg_init(&msg, (uint8_t *)&cmd, cmd_len, SSSNIC_SET_DMA_ATTR_CMD, + SSSNIC_MPU_FUNC_IDX, SSSNIC_COMM_MODULE, SSSNIC_MSG_TYPE_REQ); + ret = sssnic_mbox_send(hw, &msg, (uint8_t *)&cmd, &cmd_len, 0); + if (ret != 0) { + PMD_DRV_LOG(ERR, "Failed to send mbox message, ret=%d", ret); + return ret; + } + if (cmd_len == 0 || cmd.common.status != 0) { + PMD_DRV_LOG(ERR, + "Bad response to SET_DMA_ATTR_CMD, len=%u, status=%u", + cmd_len, cmd.common.status); + return -EIO; + } + + return 0; +} + +static int +sssnic_func_reset(struct sssnic_hw *hw) +{ + int ret; + struct sssnic_msg msg; + struct sssnic_func_reset_cmd cmd; + uint32_t cmd_len; + + memset(&cmd, 0, sizeof(cmd)); + cmd.func_id = SSSNIC_FUNC_IDX(hw); + cmd.res_mask = RTE_BIT64(0) | RTE_BIT64(1) | RTE_BIT64(2) | + RTE_BIT64(10) | RTE_BIT64(12) | RTE_BIT64(13); + cmd_len = sizeof(cmd); + sssnic_msg_init(&msg, (uint8_t *)&cmd, cmd_len, SSSNIC_RESET_FUNC_CMD, + SSSNIC_MPU_FUNC_IDX, SSSNIC_COMM_MODULE, SSSNIC_MSG_TYPE_REQ); + ret = sssnic_mbox_send(hw, &msg, (uint8_t *)&cmd, &cmd_len, 0); + if (ret != 0) { + PMD_DRV_LOG(ERR, "Failed to send mbox message, ret=%d", ret); + return ret; + } + if (cmd_len == 0 || cmd.common.status != 0) { + PMD_DRV_LOG(ERR, + "Bad response to RESET_FUNC_CMD, len=%u, status=%u", + cmd_len, cmd.common.status); + return -EIO; + } + + return 0; +} + +static int +sssnic_pagesize_set(struct sssnic_hw *hw, uint32_t pagesize) +{ + int ret; + struct sssnic_msg msg; + struct sssnic_pagesize_cmd cmd; + uint32_t cmd_len; + + memset(&cmd, 0, sizeof(cmd)); + cmd.func_id = SSSNIC_FUNC_IDX(hw); + cmd.pagesz = (uint8_t)rte_log2_u32(pagesize >> 12); + cmd.opcode = SSSNIC_CMD_OPCODE_SET; + cmd_len = sizeof(cmd); + sssnic_msg_init(&msg, (uint8_t *)&cmd, cmd_len, SSSNIC_PAGESIZE_CFG_CMD, + SSSNIC_MPU_FUNC_IDX, SSSNIC_COMM_MODULE, SSSNIC_MSG_TYPE_REQ); + ret = sssnic_mbox_send(hw, &msg, (uint8_t *)&cmd, &cmd_len, 0); + if (ret != 0) { + PMD_DRV_LOG(ERR, "Failed to send mbox message, ret=%d", ret); + return ret; + } + if (cmd_len == 0 || cmd.common.status != 0) { + PMD_DRV_LOG(ERR, + "Bad response to PAGESIZE_CFG_CMD, len=%u, status=%u", + cmd_len, cmd.common.status); + return -EIO; + } + + return 0; +} + +/* Only initialize msix 0 attributes */ +static int +sssnic_msix_attr_init(struct sssnic_hw *hw) +{ + int ret; + struct sssnic_msix_attr attr; + + attr.lli_set = 0; + attr.coalescing_set = 1; + attr.pending_limit = 0; + attr.coalescing_timer = 0xff; + attr.resend_timer = 0x7; + + ret = sssnic_msix_attr_set(hw, 0, &attr); + if (ret != 0) { + PMD_DRV_LOG(ERR, "Failed to set msix0 attributes."); + return ret; + } + + return 0; +} + static int sssnic_base_init(struct sssnic_hw *hw) { @@ -217,8 +330,42 @@ sssnic_hw_init(struct sssnic_hw *hw) goto mbox_init_fail; } + ret = sssnic_func_reset(hw); + if (ret != 0) { + PMD_DRV_LOG(ERR, "Failed to reset function resources"); + goto mbox_init_fail; + } + + ret = sssnic_dma_attr_init(hw); + if (ret != 0) { + PMD_DRV_LOG(ERR, "Failed to initialize DMA attributes"); + goto mbox_init_fail; + } + + ret = sssnic_msix_attr_init(hw); + if (ret != 0) { + PMD_DRV_LOG(ERR, "Failed to initialize msix attributes"); + goto mbox_init_fail; + } + + ret = sssnic_pagesize_set(hw, 0x100000); + if (ret != 0) { + PMD_DRV_LOG(ERR, "Failed to set page size to 0x100000"); + goto mbox_init_fail; + } + + ret = sssnic_ctrlq_init(hw); + if (ret != 0) { + PMD_DRV_LOG(ERR, "Failed to initialize control queue"); + goto ctrlq_init_fail; + } + + sssnic_pf_status_set(hw, SSSNIC_PF_STATUS_ACTIVE); + return -EINVAL; +ctrlq_init_fail: + sssnic_mbox_shutdown(hw); mbox_init_fail: sssnic_eventq_all_shutdown(hw); eventq_init_fail: @@ -231,6 +378,8 @@ sssnic_hw_shutdown(struct sssnic_hw *hw) { PMD_INIT_FUNC_TRACE(); + sssnic_pf_status_set(hw, SSSNIC_PF_STATUS_INIT); + sssnic_ctrlq_shutdown(hw); sssnic_mbox_shutdown(hw); sssnic_eventq_all_shutdown(hw); sssnic_msg_inbox_shutdown(hw); diff --git a/drivers/net/sssnic/base/sssnic_hw.h b/drivers/net/sssnic/base/sssnic_hw.h index 41e65f5880..c1b9539015 100644 --- a/drivers/net/sssnic/base/sssnic_hw.h +++ b/drivers/net/sssnic/base/sssnic_hw.h @@ -54,6 +54,7 @@ struct sssnic_hw { struct sssnic_eventq *eventqs; struct sssnic_msg_inbox *msg_inbox; struct sssnic_mbox *mbox; + struct sssnic_ctrlq *ctrlq; uint8_t num_eventqs; uint16_t eth_port_id; }; @@ -64,6 +65,13 @@ struct sssnic_hw { #define SSSNIC_FUNC_TYPE(hw) ((hw)->attr.func_type) #define SSSNIC_AF_FUNC_IDX(hw) ((hw)->attr.af_idx) +enum sssnic_module { + SSSNIC_COMM_MODULE = 0, + SSSNIC_LAN_MODULE = 1, + SSSNIC_CFG_MODULE = 7, + SSSNIC_NETIF_MODULE = 14, +}; + int sssnic_hw_init(struct sssnic_hw *hw); void sssnic_hw_shutdown(struct sssnic_hw *hw); void sssnic_msix_state_set(struct sssnic_hw *hw, uint16_t msix_id, int state);