From patchwork Fri Sep 1 09:34:49 2023 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Renyong Wan X-Patchwork-Id: 131053 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 BE8054221E; Fri, 1 Sep 2023 11:36:49 +0200 (CEST) Received: from mails.dpdk.org (localhost [127.0.0.1]) by mails.dpdk.org (Postfix) with ESMTP id 35825402B6; Fri, 1 Sep 2023 11:35:55 +0200 (CEST) Received: from VLXDG1SPAM1.ramaxel.com (email.ramaxel.com [221.4.138.186]) by mails.dpdk.org (Postfix) with ESMTP id CCF56402C4 for ; Fri, 1 Sep 2023 11:35:50 +0200 (CEST) Received: from V12DG1MBS03.ramaxel.local ([172.26.18.33]) by VLXDG1SPAM1.ramaxel.com with ESMTP id 3819ZQwI069823; Fri, 1 Sep 2023 17:35:26 +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; Fri, 1 Sep 2023 17:35:25 +0800 From: To: CC: , Renyong Wan , Steven Song Subject: [PATCH v4 07/32] net/sssnic/base: add mailbox support Date: Fri, 1 Sep 2023 17:34:49 +0800 Message-ID: <20230901093514.224824-8-wanry@3snic.com> X-Mailer: git-send-email 2.25.1 In-Reply-To: <20230901093514.224824-1-wanry@3snic.com> References: <20230901093514.224824-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 3819ZQwI069823 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 Mailbox is a message channel used to communicate between PF and VF as well as driver and hardware functions. Mailbox messages are received by driver through event queue, and sent by driver through registers of mailbox. There are two transfer modes for sending mailbox message, one is DMA mode used to send message to PF, another is inline mode used to send message to VF. Signed-off-by: Steven Song Signed-off-by: Renyong Wan --- v3: * Fixed dereferencing type-punned pointer. --- drivers/net/sssnic/base/meson.build | 1 + drivers/net/sssnic/base/sssnic_hw.c | 10 + drivers/net/sssnic/base/sssnic_hw.h | 4 + drivers/net/sssnic/base/sssnic_mbox.c | 615 ++++++++++++++++++++++++++ drivers/net/sssnic/base/sssnic_mbox.h | 45 ++ drivers/net/sssnic/base/sssnic_misc.h | 11 + drivers/net/sssnic/base/sssnic_reg.h | 47 ++ 7 files changed, 733 insertions(+) create mode 100644 drivers/net/sssnic/base/sssnic_mbox.c create mode 100644 drivers/net/sssnic/base/sssnic_mbox.h create mode 100644 drivers/net/sssnic/base/sssnic_misc.h diff --git a/drivers/net/sssnic/base/meson.build b/drivers/net/sssnic/base/meson.build index dd4dd08fc1..4abd1a0daf 100644 --- a/drivers/net/sssnic/base/meson.build +++ b/drivers/net/sssnic/base/meson.build @@ -5,6 +5,7 @@ sources = [ 'sssnic_hw.c', 'sssnic_eventq.c', 'sssnic_msg.c', + 'sssnic_mbox.c', ] c_args = cflags diff --git a/drivers/net/sssnic/base/sssnic_hw.c b/drivers/net/sssnic/base/sssnic_hw.c index 387c823c7e..ff527b2c7f 100644 --- a/drivers/net/sssnic/base/sssnic_hw.c +++ b/drivers/net/sssnic/base/sssnic_hw.c @@ -11,6 +11,7 @@ #include "sssnic_reg.h" #include "sssnic_eventq.h" #include "sssnic_msg.h" +#include "sssnic_mbox.h" static int wait_for_sssnic_hw_ready(struct sssnic_hw *hw) @@ -210,8 +211,16 @@ sssnic_hw_init(struct sssnic_hw *hw) goto eventq_init_fail; } + ret = sssnic_mbox_init(hw); + if (ret) { + PMD_DRV_LOG(ERR, "Failed to initialize mailbox"); + goto mbox_init_fail; + } + return -EINVAL; +mbox_init_fail: + sssnic_eventq_all_shutdown(hw); eventq_init_fail: sssnic_msg_inbox_shutdown(hw); return ret; @@ -222,6 +231,7 @@ sssnic_hw_shutdown(struct sssnic_hw *hw) { PMD_INIT_FUNC_TRACE(); + 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 38fb9ac1ac..41e65f5880 100644 --- a/drivers/net/sssnic/base/sssnic_hw.h +++ b/drivers/net/sssnic/base/sssnic_hw.h @@ -53,12 +53,16 @@ struct sssnic_hw { struct sssnic_hw_attr attr; struct sssnic_eventq *eventqs; struct sssnic_msg_inbox *msg_inbox; + struct sssnic_mbox *mbox; uint8_t num_eventqs; uint16_t eth_port_id; }; +#define SSSNIC_FUNC_IDX(hw) ((hw)->attr.func_idx) #define SSSNIC_ETH_PORT_ID(hw) ((hw)->eth_port_id) #define SSSNIC_MPU_FUNC_IDX 0x1fff +#define SSSNIC_FUNC_TYPE(hw) ((hw)->attr.func_type) +#define SSSNIC_AF_FUNC_IDX(hw) ((hw)->attr.af_idx) int sssnic_hw_init(struct sssnic_hw *hw); void sssnic_hw_shutdown(struct sssnic_hw *hw); diff --git a/drivers/net/sssnic/base/sssnic_mbox.c b/drivers/net/sssnic/base/sssnic_mbox.c new file mode 100644 index 0000000000..02957137ea --- /dev/null +++ b/drivers/net/sssnic/base/sssnic_mbox.c @@ -0,0 +1,615 @@ +/* SPDX-License-Identifier: BSD-3-Clause + * Copyright(c) 2018-2022 Shenzhen 3SNIC Information Technology Co., Ltd. + */ + +#include +#include +#include +#include +#include +#include +#include +#include + +#include "../sssnic_log.h" +#include "sssnic_hw.h" +#include "sssnic_reg.h" +#include "sssnic_misc.h" +#include "sssnic_eventq.h" +#include "sssnic_mbox.h" + +#define SSSNIC_MBOX_SEND_RESULT_SIZE 16 +#define SSSNIC_MBOX_SEND_BUF_SIZE 2048UL +#define SSSNIC_MBOX_RESP_MSG_EVENTQ 1 +#define SSSNIC_MBOX_SEND_DONE_TIMEOUT 500000 /* uint is 10us */ +#define SSSNIC_MBOX_DEF_REQ_TIMEOUT 4000 /* millisecond */ +#define SSSNIC_MBOX_REQ_ID_MASK 0xf /* request id only 4 bits*/ + +struct sssnic_sendbox { + struct sssnic_mbox *mbox; + /* Send data memory */ + uint8_t *data; + /* Send result DMA memory zone */ + const struct rte_memzone *result_mz; + /* Send result DMA virtual address */ + volatile uint64_t *result_addr; + /* DMA buffer mz */ + const struct rte_memzone *buf_mz; + /* DMA buffer virtual address */ + uint8_t *buf_addr; + pthread_mutex_t lock; +}; + +struct sssnic_mbox_msg_dma_desc { + /* 32bit xor checksum for DMA data */ + uint32_t checksum; + /* dword of high DMA address */ + uint32_t dma_addr_hi; + /* dword of low DMA address */ + uint32_t dma_addr_lo; + /* DMA data length */ + uint32_t len; + uint32_t resvd[2]; +}; +#define SSSNIC_MBOX_MSG_DMA_DESC_SIZE 16 + +struct sssnic_mbox_send_result { + union { + uint16_t u16; + struct { + /* SSSNIC_MBOX_SEND_STATUS_xx */ + uint16_t status : 8; + uint16_t errcode : 8; + }; + }; +}; + +#define SSSNIC_MBOX_SEND_STATUS_DONE 0xff +#define SSSNIC_MBOX_SEND_STATUS_ERR 0xfe +#define SSSNIC_MBOX_SEND_ERR_NONE 0x0 + +static inline uint16_t +sssnic_sendbox_result_get(struct sssnic_sendbox *sendbox) +{ + uint64_t result = rte_be_to_cpu_64(rte_read64(sendbox->result_addr)); + return (uint16_t)(result & 0xffff); +} + +static inline void +sssnic_sendbox_result_clear(struct sssnic_sendbox *sendbox) +{ + rte_write64(0, sendbox->result_addr); +} + +/* Wait send status to done */ +static int +sssnic_sendbox_result_wait(struct sssnic_sendbox *sendbox, uint32_t timeout) +{ + int ret; + struct sssnic_mbox_send_result result; + + do { + result.u16 = sssnic_sendbox_result_get(sendbox); + if (result.status == SSSNIC_MBOX_SEND_STATUS_DONE) { + return 0; + } else if (result.status == SSSNIC_MBOX_SEND_STATUS_ERR) { + PMD_DRV_LOG(ERR, + "Failed to send mbox segment data, error code=%u", + result.errcode); + ret = -EFAULT; + goto err_return; + } + if (timeout == 0) + break; + rte_delay_us(10); + } while (--timeout); + + PMD_DRV_LOG(ERR, "Mbox segment data sent time out"); + ret = -ETIMEDOUT; + +err_return: + PMD_DRV_LOG(ERR, "MBOX_SEND_CTRL0_REG=0x%x, SEND_CTRL1_REG=0x%x", + sssnic_cfg_reg_read(sendbox->mbox->hw, + SSSNIC_MBOX_SEND_CTRL0_REG), + sssnic_cfg_reg_read(sendbox->mbox->hw, + SSSNIC_MBOX_SEND_CTRL1_REG)); + + return ret; +} + +static void +sssnic_mbox_send_ctrl_set(struct sssnic_mbox *mbox, uint16_t func, + uint16_t dst_eq, uint16_t len) +{ + struct sssnic_mbox_send_ctrl0_reg ctrl_0; + struct sssnic_mbox_send_ctrl1_reg ctrl_1; + + ctrl_1.u32 = 0; + ctrl_1.dma_attr = 0; + ctrl_1.ordering = 0; + ctrl_1.dst_eq = dst_eq; + ctrl_1.src_eq = 0; + ctrl_1.tx_size = RTE_ALIGN(len + SSSNIC_MSG_HDR_SIZE, 4) >> 2; + ctrl_1.wb = 1; + sssnic_cfg_reg_write(mbox->hw, SSSNIC_MBOX_SEND_CTRL1_REG, ctrl_1.u32); + rte_wmb(); + + if (SSSNIC_FUNC_TYPE(mbox->hw) == SSSNIC_FUNC_TYPE_VF && + func != SSSNIC_MPU_FUNC_IDX) { + if (func == SSSNIC_AF_FUNC_IDX(mbox->hw)) + func = 1; + else + func = 0; + } + + ctrl_0.u32 = 0; + ctrl_0.func = func; + ctrl_0.src_eq_en = 0; + ctrl_0.tx_status = SSSNIC_REG_MBOX_TX_READY; + sssnic_cfg_reg_write(mbox->hw, SSSNIC_MBOX_SEND_CTRL0_REG, ctrl_0.u32); +} + +static void +sssnic_mbox_state_set(struct sssnic_mbox *mbox, enum sssnic_mbox_state state) +{ + rte_spinlock_lock(&mbox->state_lock); + mbox->state = state; + rte_spinlock_unlock(&mbox->state_lock); +} + +static void +sssnic_sendbox_write(struct sssnic_sendbox *sendbox, uint16_t offset, + uint8_t *data, uint16_t data_len) +{ + uint32_t *send_addr; + uint32_t send_data; + uint32_t remain_data[3] = { 0 }; + uint16_t remain; + uint16_t i; + uint16_t len; + uint16_t num_dw; + + len = data_len; + remain = len & 0x3; + if (remain > 0) { + len = len - remain; + for (i = 0; i < remain; i++) + remain_data[i] = data[len + i]; + } + num_dw = len / sizeof(uint32_t); + send_addr = (uint32_t *)(sendbox->data + offset); + + SSSNIC_DEBUG("data_buf=%p, data_len=%u, aligned_len=%u, remain=%u, " + "num_dw=%u send_addr=%p", + data, data_len, len, remain, num_dw, send_addr); + + for (i = 0; i < num_dw; i++) { + send_data = *(((uint32_t *)data) + i); + rte_write32(rte_cpu_to_be_32(send_data), send_addr + i); + } + if (remain > 0) { + send_data = remain_data[0] << 24; + send_data |= remain_data[1] << 16; + send_data |= remain_data[2] << 8; + rte_write32(send_data, send_addr + i); + } +} + +static inline void +sssnic_mbox_msg_hdr_init(struct sssnic_msg_hdr *msghdr, struct sssnic_msg *msg) +{ + msghdr->u64 = 0; + if (msg == NULL) + return; + if (msg->func == SSSNIC_MPU_FUNC_IDX) { + msghdr->trans_mode = SSSNIC_MSG_TRANS_MODE_DMA; + msghdr->length = SSSNIC_MBOX_MSG_DMA_DESC_SIZE; + msghdr->seg_len = SSSNIC_MBOX_MSG_DMA_DESC_SIZE; + msghdr->last_seg = 1; + } else { + msghdr->trans_mode = SSSNIC_MSG_TRANS_MODE_INLINE; + msghdr->length = msg->data_len; + if (msg->data_len > SSSNIC_MSG_MAX_SEG_SIZE) { + msghdr->seg_len = SSSNIC_MSG_MAX_SEG_SIZE; + msghdr->last_seg = 0; + } else { + msghdr->seg_len = msg->data_len; + msghdr->last_seg = 1; + } + } + msghdr->module = msg->module; + msghdr->no_response = !msg->ack; + msghdr->seg_id = SSSNIC_MSG_MIN_SGE_ID; + msghdr->type = msg->type; + msghdr->command = msg->command; + msghdr->id = msg->id; + msghdr->eventq = SSSNIC_MBOX_RESP_MSG_EVENTQ; + msghdr->channel = SSSNIC_MSG_CHAN_MBOX; + msghdr->status = msg->status; +} + +/* Calculate data checksum with XOR */ +static uint32_t +sssnic_mbox_dma_data_csum(uint32_t *data, uint16_t data_len) +{ + uint32_t xor = 0x5a5a5a5a; + uint16_t dw = data_len / sizeof(uint32_t); + uint16_t i; + + for (i = 0; i < dw; i++) + xor ^= data[i]; + return xor; +} + +static int +sssnic_mbox_dma_send(struct sssnic_mbox *mbox, struct sssnic_msg *msg) +{ + int ret; + struct sssnic_mbox_msg_dma_desc dma_desc = { 0 }; + struct sssnic_msg_hdr msghdr; + struct sssnic_sendbox *sendbox = mbox->sendbox; + + /* Init DMA description */ + dma_desc.checksum = sssnic_mbox_dma_data_csum((uint32_t *)msg->data_buf, + msg->data_len); + dma_desc.dma_addr_hi = (uint32_t)((sendbox->buf_mz->iova >> 16) >> 16); + dma_desc.dma_addr_lo = (uint32_t)(sendbox->buf_mz->iova); + dma_desc.len = msg->data_len; + /* Copy message data to DMA buffer */ + rte_memcpy(sendbox->buf_addr, msg->data_buf, msg->data_len); + /* Init message header */ + sssnic_mbox_msg_hdr_init(&msghdr, msg); + msghdr.function = SSSNIC_FUNC_IDX(mbox->hw); + /* Clear send result */ + sssnic_sendbox_result_clear(sendbox); + /* write mbox message header */ + sssnic_sendbox_write(sendbox, 0, (uint8_t *)&msghdr, + SSSNIC_MSG_HDR_SIZE); + /* write DMA description*/ + sssnic_sendbox_write(sendbox, SSSNIC_MSG_HDR_SIZE, (void *)&dma_desc, + sizeof(struct sssnic_mbox_msg_dma_desc)); + /* mbox send control set */ + sssnic_mbox_send_ctrl_set(mbox, msg->func, + msg->type == SSSNIC_MSG_TYPE_REQ ? 0 : + SSSNIC_MBOX_RESP_MSG_EVENTQ, + SSSNIC_MBOX_MSG_DMA_DESC_SIZE); + + rte_wmb(); + /* Wait for send status becomes done */ + ret = sssnic_sendbox_result_wait(sendbox, + SSSNIC_MBOX_SEND_DONE_TIMEOUT); + if (ret != 0) + PMD_DRV_LOG(ERR, "Failed to send mbox DMA data"); + + return ret; +} + +static int +sssnic_mbox_inline_send(struct sssnic_mbox *mbox, struct sssnic_msg *msg) +{ + int ret; + uint16_t remain; + uint16_t send; + struct sssnic_msg_hdr msghdr; + struct sssnic_sendbox *sendbox = mbox->sendbox; + + /* Init message header */ + sssnic_mbox_msg_hdr_init(&msghdr, msg); + send = 0; + remain = msg->data_len; + do { + /* Clear send result */ + sssnic_sendbox_result_clear(sendbox); + /* write mbox message header */ + sssnic_sendbox_write(sendbox, 0, (uint8_t *)&msghdr, + SSSNIC_MSG_HDR_SIZE); + /* write mbox message data */ + sssnic_sendbox_write(sendbox, SSSNIC_MSG_HDR_SIZE, + msg->data_buf + send, msghdr.seg_len); + /* mbox send control set */ + sssnic_mbox_send_ctrl_set(mbox, msg->func, + msg->type == SSSNIC_MSG_TYPE_REQ ? + 0 : + SSSNIC_MBOX_RESP_MSG_EVENTQ, + msghdr.seg_len); + + rte_wmb(); + /* Wait for send status becomes done */ + ret = sssnic_sendbox_result_wait(sendbox, + SSSNIC_MBOX_SEND_DONE_TIMEOUT); + if (ret != 0) { + PMD_DRV_LOG(ERR, "Failed to send mbox inline data"); + return ret; + } + /*last segment has been sent*/ + if (msghdr.last_seg) + break; + + remain -= SSSNIC_MSG_MAX_SEG_SIZE; + send += SSSNIC_MSG_MAX_SEG_SIZE; + if (remain <= SSSNIC_MSG_MAX_SEG_SIZE) { + msghdr.seg_len = remain; + msghdr.last_seg = 1; + } + msghdr.seg_id++; + } while (remain > 0); + + return 0; +} + +static int +sssnic_sendbox_init(struct sssnic_mbox *mbox) +{ + int ret; + struct sssnic_sendbox *sendbox; + struct sssnic_hw *hw; + char m_name[RTE_MEMZONE_NAMESIZE]; + + PMD_INIT_FUNC_TRACE(); + + hw = mbox->hw; + + sendbox = rte_zmalloc(NULL, sizeof(struct sssnic_sendbox), 1); + if (sendbox == NULL) { + PMD_DRV_LOG(ERR, "Could not alloc memory for sendbox"); + return -ENOMEM; + } + + hw = mbox->hw; + mbox->sendbox = sendbox; + sendbox->mbox = mbox; + + snprintf(m_name, sizeof(m_name), "sssnic%u_mbox_send_result", + SSSNIC_ETH_PORT_ID(hw)); + sendbox->result_mz = rte_memzone_reserve_aligned(m_name, + SSSNIC_MBOX_SEND_RESULT_SIZE, SOCKET_ID_ANY, + RTE_MEMZONE_IOVA_CONTIG, RTE_CACHE_LINE_SIZE); + if (sendbox->result_mz == NULL) { + PMD_DRV_LOG(ERR, "Could not alloc memzone for %s", m_name); + ret = -ENOMEM; + goto alloc_send_result_fail; + } + sssnic_cfg_reg_write(hw, SSSNIC_MBOX_SEND_RESULT_ADDR_H_REG, + SSSNIC_UPPER_32_BITS(sendbox->result_mz->iova)); + sssnic_cfg_reg_write(hw, SSSNIC_MBOX_SEND_RESULT_ADDR_L_REG, + SSSNIC_LOWER_32_BITS(sendbox->result_mz->iova)); + sendbox->result_addr = sendbox->result_mz->addr; + + snprintf(m_name, sizeof(m_name), "sssnic%u_mbox_sendbuf", + SSSNIC_ETH_PORT_ID(hw)); + sendbox->buf_mz = rte_memzone_reserve_aligned(m_name, + SSSNIC_MBOX_SEND_BUF_SIZE, SOCKET_ID_ANY, + RTE_MEMZONE_IOVA_CONTIG, SSSNIC_MBOX_SEND_BUF_SIZE); + if (sendbox->buf_mz == NULL) { + PMD_DRV_LOG(ERR, "Could not alloc memzone for %s", m_name); + ret = -ENOMEM; + goto alloc_send_buf_fail; + }; + sendbox->buf_addr = sendbox->buf_mz->addr; + + sendbox->data = hw->cfg_base_addr + SSSNIC_MBOX_SEND_DATA_BASE_REG; + + pthread_mutex_init(&sendbox->lock, NULL); + + return 0; + +alloc_send_buf_fail: + rte_memzone_free(sendbox->result_mz); +alloc_send_result_fail: + rte_free(sendbox); + return ret; +} + +static void +sssnic_sendbox_shutdown(struct sssnic_mbox *mbox) +{ + struct sssnic_sendbox *sendbox = mbox->sendbox; + + PMD_INIT_FUNC_TRACE(); + + rte_memzone_free(sendbox->buf_mz); + sssnic_cfg_reg_write(mbox->hw, SSSNIC_MBOX_SEND_RESULT_ADDR_H_REG, 0); + sssnic_cfg_reg_write(mbox->hw, SSSNIC_MBOX_SEND_RESULT_ADDR_L_REG, 0); + rte_memzone_free(sendbox->result_mz); + pthread_mutex_destroy(&sendbox->lock); + rte_free(sendbox); +} + +static int +sssnic_mbox_response_handle(struct sssnic_msg *msg, + __rte_unused enum sssnic_msg_chann_id chan_id, void *priv) +{ + int ret; + struct sssnic_mbox *mbox = priv; + ; + + rte_spinlock_lock(&mbox->state_lock); + if (msg->id == mbox->req_id && + mbox->state == SSSNIC_MBOX_STATE_RUNNING) { + mbox->state = SSSNIC_MBOX_STATE_READY; + ret = SSSNIC_MSG_DONE; + } else { + PMD_DRV_LOG(ERR, + "Failed to handle mbox response message, msg_id=%u, " + "req_id=%u, msg_status=%u, mbox_state=%u", + msg->id, mbox->req_id, msg->status, mbox->state); + ret = SSSNIC_MSG_REJECT; + } + rte_spinlock_unlock(&mbox->state_lock); + + return ret; +} + +static int +sssnic_mbox_msg_tx(struct sssnic_mbox *mbox, struct sssnic_msg *msg) +{ + int ret; + + if (mbox == NULL || msg == NULL || msg->data_buf == NULL || + msg->data_len == 0 || + msg->data_len > SSSNIC_MSG_MAX_DATA_SIZE) { + PMD_DRV_LOG(ERR, "Bad parameter for mbox message tx"); + return -EINVAL; + } + + SSSNIC_DEBUG("command=%u, func=%u module=%u, type=%u, ack=%u, seq=%u, " + "status=%u, id=%u data_buf=%p, data_len=%u", + msg->command, msg->func, msg->module, msg->type, msg->ack, + msg->seg, msg->status, msg->id, msg->data_buf, msg->data_len); + + pthread_mutex_lock(&mbox->sendbox->lock); + if (msg->func == SSSNIC_MPU_FUNC_IDX) + ret = sssnic_mbox_dma_send(mbox, msg); + else + ret = sssnic_mbox_inline_send(mbox, msg); + pthread_mutex_unlock(&mbox->sendbox->lock); + + return ret; +} + +static int +sssnic_mbox_send_internal(struct sssnic_mbox *mbox, struct sssnic_msg *msg, + uint8_t *resp_data, uint32_t *resp_data_len, uint32_t timeout_ms) +{ + int ret; + struct sssnic_msg *resp_msg = NULL; + + if (resp_data != NULL) { + /* the function of request message equls to response message */ + resp_msg = SSSNIC_MSG_LOCATE(mbox->hw, SSSNIC_MSG_CHAN_MBOX, + SSSNIC_MSG_TYPE_RESP, SSSNIC_MSG_SRC(msg->func)); + mbox->req_id++; + mbox->req_id &= SSSNIC_MBOX_REQ_ID_MASK; + msg->id = mbox->req_id; + msg->ack = 1; + sssnic_mbox_state_set(mbox, SSSNIC_MBOX_STATE_RUNNING); + } + ret = sssnic_mbox_msg_tx(mbox, msg); + if (ret != 0) { + PMD_DRV_LOG(ERR, "Failed to transmit mbox message, ret=%d", + ret); + if (resp_data != NULL) + sssnic_mbox_state_set(mbox, SSSNIC_MBOX_STATE_FAILED); + return ret; + } + + if (resp_data == NULL) + return 0; + + ret = sssnic_eventq_flush(mbox->hw, SSSNIC_MBOX_RESP_MSG_EVENTQ, + timeout_ms ? timeout_ms : SSSNIC_MBOX_DEF_REQ_TIMEOUT); + if (ret != 0) { + PMD_DRV_LOG(ERR, "No response message, ret=%d", ret); + sssnic_mbox_state_set(mbox, SSSNIC_MBOX_STATE_TIMEOUT); + return ret; + } + if (resp_msg->module != msg->module || + resp_msg->command != msg->command) { + PMD_DRV_LOG(ERR, + "Received invalid response message, module=%x, command=%x, expected message module=%x, command=%x", + resp_msg->module, resp_msg->command, msg->module, + msg->command); + sssnic_mbox_state_set(mbox, SSSNIC_MBOX_STATE_FAILED); + return ret; + } + sssnic_mbox_state_set(mbox, SSSNIC_MBOX_STATE_READY); + + if (resp_msg->status != 0) { + PMD_DRV_LOG(ERR, "Bad response status"); + return -EFAULT; + } + + if (*resp_data_len < resp_msg->data_len) { + PMD_DRV_LOG(ERR, + "Invalid response data size %u, expected less than %u for module %x command %x", + resp_msg->data_len, *resp_data_len, msg->module, + msg->command); + return -EFAULT; + } + + rte_memcpy(resp_data, resp_msg->data_buf, resp_msg->data_len); + *resp_data_len = resp_msg->data_len; + return 0; +} + +int +sssnic_mbox_send(struct sssnic_hw *hw, struct sssnic_msg *msg, + uint8_t *resp_data, uint32_t *resp_data_len, uint32_t timeout_ms) +{ + int ret; + struct sssnic_mbox *mbox; + + if (hw == NULL || msg == NULL || + (resp_data != NULL && resp_data_len == NULL)) { + PMD_DRV_LOG(ERR, "Bad parameter for mbox request"); + return -EINVAL; + } + + mbox = hw->mbox; + + if (resp_data != NULL) { + ret = pthread_mutex_lock(&mbox->req_lock); + if (ret != 0) { + PMD_DRV_LOG(ERR, "Failed to lock mbox request lock"); + return ret; + } + } + ret = sssnic_mbox_send_internal(mbox, msg, resp_data, resp_data_len, + timeout_ms); + + if (resp_data != NULL) + pthread_mutex_unlock(&mbox->req_lock); + + return ret; +} + +int +sssnic_mbox_init(struct sssnic_hw *hw) +{ + int ret; + struct sssnic_mbox *mbox; + + PMD_INIT_FUNC_TRACE(); + + mbox = rte_zmalloc(NULL, sizeof(struct sssnic_mbox), 1); + if (mbox == NULL) { + PMD_DRV_LOG(ERR, "Could not alloc memory for mailbox struct"); + return -ENOMEM; + } + + pthread_mutex_init(&mbox->req_lock, NULL); + rte_spinlock_init(&mbox->state_lock); + + mbox->hw = hw; + hw->mbox = mbox; + ret = sssnic_sendbox_init(mbox); + if (ret != 0) { + PMD_DRV_LOG(ERR, "Failed to initialize sendbox!"); + goto sendbox_init_fail; + } + + sssnic_msg_rx_handler_register(hw, SSSNIC_MSG_CHAN_MBOX, + SSSNIC_MSG_TYPE_RESP, sssnic_mbox_response_handle, mbox); + + return 0; + +sendbox_init_fail: + pthread_mutex_destroy(&mbox->req_lock); + rte_free(mbox); + return ret; +} + +void +sssnic_mbox_shutdown(struct sssnic_hw *hw) +{ + struct sssnic_mbox *mbox = hw->mbox; + + PMD_INIT_FUNC_TRACE(); + + if (mbox == NULL) + return; + + sssnic_sendbox_shutdown(mbox); + pthread_mutex_destroy(&mbox->req_lock); + rte_free(mbox); +} diff --git a/drivers/net/sssnic/base/sssnic_mbox.h b/drivers/net/sssnic/base/sssnic_mbox.h new file mode 100644 index 0000000000..00fa02ea78 --- /dev/null +++ b/drivers/net/sssnic/base/sssnic_mbox.h @@ -0,0 +1,45 @@ +/* SPDX-License-Identifier: BSD-3-Clause + * Copyright(c) 2018-2022 Shenzhen 3SNIC Information Technology Co., Ltd. + */ + +#ifndef _SSSNIC_MBOX_H_ +#define _SSSNIC_MBOX_H_ + +#include + +#include "sssnic_msg.h" + +enum sssnic_mbox_state { + /* Mbox is sending message or waiting for response */ + SSSNIC_MBOX_STATE_RUNNING, + /* Waiting for response timed out*/ + SSSNIC_MBOX_STATE_TIMEOUT, + /* Mbox failed to send message */ + SSSNIC_MBOX_STATE_FAILED, + /* Response is ready */ + SSSNIC_MBOX_STATE_READY, + /* Mbox is idle, it can send message */ + SSSNIC_MBOX_STATE_IDLE, +}; + +struct sssnic_sendbox; + +struct sssnic_mbox { + struct sssnic_hw *hw; + /* just be used for sending request msg*/ + pthread_mutex_t req_lock; + /* request msg id*/ + uint8_t req_id; + struct sssnic_sendbox *sendbox; + /*current state*/ + enum sssnic_mbox_state state; + rte_spinlock_t state_lock; +}; + +int sssnic_mbox_send(struct sssnic_hw *hw, struct sssnic_msg *msg, + uint8_t *resp_data, uint32_t *resp_data_len, uint32_t timeout_ms); + +int sssnic_mbox_init(struct sssnic_hw *hw); +void sssnic_mbox_shutdown(struct sssnic_hw *hw); + +#endif /* _SSSNIC_MBOX_H_ */ diff --git a/drivers/net/sssnic/base/sssnic_misc.h b/drivers/net/sssnic/base/sssnic_misc.h new file mode 100644 index 0000000000..ac1bbd9c73 --- /dev/null +++ b/drivers/net/sssnic/base/sssnic_misc.h @@ -0,0 +1,11 @@ +/* SPDX-License-Identifier: BSD-3-Clause + * Copyright(c) 2018-2022 Shenzhen 3SNIC Information Technology Co., Ltd. + */ + +#ifndef _SSSNIC_MISC_H_ +#define _SSSNIC_MISC_H_ + +#define SSSNIC_LOWER_32_BITS(x) ((uint32_t)(x)) +#define SSSNIC_UPPER_32_BITS(x) ((uint32_t)(((x) >> 16) >> 16)) + +#endif /* _SSSNIC_MISC_H_ */ diff --git a/drivers/net/sssnic/base/sssnic_reg.h b/drivers/net/sssnic/base/sssnic_reg.h index e38d39a691..859654087d 100644 --- a/drivers/net/sssnic/base/sssnic_reg.h +++ b/drivers/net/sssnic/base/sssnic_reg.h @@ -26,6 +26,12 @@ #define SSSNIC_EVENTQ_PROD_IDX_REG 0x20c #define SSSNIC_EVENTQ_PAGE_ADDR_REG 0x240 +#define SSSNIC_MBOX_SEND_DATA_BASE_REG 0x80 +#define SSSNIC_MBOX_SEND_CTRL0_REG 0x100 +#define SSSNIC_MBOX_SEND_CTRL1_REG 0x104 +#define SSSNIC_MBOX_SEND_RESULT_ADDR_H_REG 0x108 +#define SSSNIC_MBOX_SEND_RESULT_ADDR_L_REG 0x10c + /* registers of mgmt */ #define SSSNIC_AF_ELECTION_REG 0x6000 #define SSSNIC_MF_ELECTION_REG 0x6020 @@ -193,6 +199,47 @@ struct sssnic_eventq_ci_ctrl_reg { }; }; +#define SSSNIC_REG_MBOX_TX_DONE 0 /* Mailbox transmission is done */ +#define SSSNIC_REG_MBOX_TX_READY 1 /* Mailbox is ready to transmit */ +struct sssnic_mbox_send_ctrl0_reg { + union { + uint32_t u32; + struct { + /* enable to inform source eventq if tx done */ + uint32_t src_eq_en : 1; + /* mailbox tx result, see SSSNIC_REG_MBOX_TX_XX */ + uint32_t tx_status : 1; + uint32_t resvd0 : 14; + /* destination function where the mbox send to */ + uint32_t func : 13; + uint32_t resvd1 : 3; + }; + }; +}; + +struct sssnic_mbox_send_ctrl1_reg { + union { + uint32_t u32; + struct { + uint32_t resvd0 : 10; + /* Destination eventq in the mgmt cpu */ + uint32_t dst_eq : 2; + /* eventq that will be informed if tx done */ + uint32_t src_eq : 2; + uint32_t dma_attr : 6; + /* mailbox message size include header and body + * must 4byte align and unit is 4byte + */ + uint32_t tx_size : 5; + uint32_t ordering : 2; + uint32_t resvd1 : 1; + /*write result back to DMA address of sending result */ + uint32_t wb : 1; + uint32_t resvd2 : 3; + }; + }; +}; + static inline uint32_t sssnic_cfg_reg_read(struct sssnic_hw *hw, uint32_t reg) {