[v2,06/32] net/sssnic/base: add message definition and utility

Message ID 20230831095650.219964-7-wanry@3snic.com (mailing list archive)
State Superseded, archived
Delegated to: Thomas Monjalon
Headers
Series Introduce sssnic PMD for 3SNIC's 9x0 serials Ethernet adapters |

Checks

Context Check Description
ci/checkpatch warning coding style issues

Commit Message

Renyong Wan Aug. 31, 2023, 9:56 a.m. UTC
  From: Renyong Wan <wanry@3snic.com>

sssnic message is used to encapsulate sssnic command for transmission
between driver and firmware. sssnic message is sent by driver via mail
box and is received by driver via event queue.

Signed-off-by: Steven Song <steven.song@3snic.com>
Signed-off-by: Renyong Wan <wanry@3snic.com>
---
v2:
* Removed error.h from including files.
---
 drivers/net/sssnic/base/meson.build     |   3 +-
 drivers/net/sssnic/base/sssnic_eventq.c |  29 +++
 drivers/net/sssnic/base/sssnic_hw.c     |  15 +-
 drivers/net/sssnic/base/sssnic_hw.h     |   2 +
 drivers/net/sssnic/base/sssnic_msg.c    | 254 ++++++++++++++++++++++++
 drivers/net/sssnic/base/sssnic_msg.h    | 166 ++++++++++++++++
 6 files changed, 467 insertions(+), 2 deletions(-)
 create mode 100644 drivers/net/sssnic/base/sssnic_msg.c
 create mode 100644 drivers/net/sssnic/base/sssnic_msg.h
  

Patch

diff --git a/drivers/net/sssnic/base/meson.build b/drivers/net/sssnic/base/meson.build
index 7758faa482..dd4dd08fc1 100644
--- a/drivers/net/sssnic/base/meson.build
+++ b/drivers/net/sssnic/base/meson.build
@@ -3,7 +3,8 @@ 
 
 sources = [
         'sssnic_hw.c',
-        'sssnic_eventq.c'
+        'sssnic_eventq.c',
+        'sssnic_msg.c',
 ]
 
 c_args = cflags
diff --git a/drivers/net/sssnic/base/sssnic_eventq.c b/drivers/net/sssnic/base/sssnic_eventq.c
index a479bdff35..f6a343f0e8 100644
--- a/drivers/net/sssnic/base/sssnic_eventq.c
+++ b/drivers/net/sssnic/base/sssnic_eventq.c
@@ -14,6 +14,7 @@ 
 #include "../sssnic_log.h"
 #include "sssnic_hw.h"
 #include "sssnic_reg.h"
+#include "sssnic_msg.h"
 #include "sssnic_eventq.h"
 
 #define SSSNIC_EVENTQ_DEF_DEPTH 64
@@ -184,6 +185,32 @@  sssnic_eventq_ci_update(struct sssnic_eventq *eq, int informed)
 	sssnic_eventq_reg_write(eq, SSSNIC_EVENTQ_CI_CTRL_REG, reg.u32);
 }
 
+static int
+sssnic_event_default_handler_func(struct sssnic_eventq *eq,
+	struct sssnic_event *ev, __rte_unused void *data)
+{
+	struct sssnic_hw *hw;
+	int ret;
+
+	hw = eq->hw;
+	ret = sssnic_msg_rx_handle(hw, (struct sssnic_msg_hdr *)(ev->data));
+	if (ret != SSSNIC_MSG_DONE)
+		return -1;
+
+	return SSSNIC_EVENT_DONE;
+}
+
+static void
+sssnic_eventq_handlers_init(struct sssnic_eventq *eq)
+{
+	int i;
+
+	for (i = SSSNIC_EVENT_CODE_MIN; i <= SSSNIC_EVENT_CODE_MAX; i++) {
+		eq->handlers[i].func = sssnic_event_default_handler_func;
+		eq->handlers[i].data = NULL;
+	}
+}
+
 static int
 sssnic_eventq_init(struct sssnic_hw *hw, struct sssnic_eventq *eq, uint16_t qid)
 {
@@ -230,6 +257,8 @@  sssnic_eventq_init(struct sssnic_hw *hw, struct sssnic_eventq *eq, uint16_t qid)
 		PMD_DRV_LOG(ERR, "Failed to setup eventq pages!");
 		return ret;
 	}
+
+	sssnic_eventq_handlers_init(eq);
 	sssnic_eventq_ctrl_setup(eq);
 	sssnic_eventq_ci_update(eq, 1);
 	if (qid == 0)
diff --git a/drivers/net/sssnic/base/sssnic_hw.c b/drivers/net/sssnic/base/sssnic_hw.c
index 44e04486a5..387c823c7e 100644
--- a/drivers/net/sssnic/base/sssnic_hw.c
+++ b/drivers/net/sssnic/base/sssnic_hw.c
@@ -10,6 +10,7 @@ 
 #include "sssnic_hw.h"
 #include "sssnic_reg.h"
 #include "sssnic_eventq.h"
+#include "sssnic_msg.h"
 
 static int
 wait_for_sssnic_hw_ready(struct sssnic_hw *hw)
@@ -197,18 +198,30 @@  sssnic_hw_init(struct sssnic_hw *hw)
 		return ret;
 	}
 
+	ret = sssnic_msg_inbox_init(hw);
+	if (ret) {
+		PMD_DRV_LOG(ERR, "Failed to initialize message inbox.");
+		return ret;
+	}
+
 	ret = sssnic_eventq_all_init(hw);
 	if (ret != 0) {
 		PMD_DRV_LOG(ERR, "Failed to initialize event queues");
-		return ret;
+		goto eventq_init_fail;
 	}
 
 	return -EINVAL;
+
+eventq_init_fail:
+	sssnic_msg_inbox_shutdown(hw);
+	return ret;
 }
 
 void
 sssnic_hw_shutdown(struct sssnic_hw *hw)
 {
 	PMD_INIT_FUNC_TRACE();
+
 	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 6caf3a6d66..38fb9ac1ac 100644
--- a/drivers/net/sssnic/base/sssnic_hw.h
+++ b/drivers/net/sssnic/base/sssnic_hw.h
@@ -52,11 +52,13 @@  struct sssnic_hw {
 	uint8_t *db_mem_len;
 	struct sssnic_hw_attr attr;
 	struct sssnic_eventq *eventqs;
+	struct sssnic_msg_inbox *msg_inbox;
 	uint8_t num_eventqs;
 	uint16_t eth_port_id;
 };
 
 #define SSSNIC_ETH_PORT_ID(hw) ((hw)->eth_port_id)
+#define SSSNIC_MPU_FUNC_IDX 0x1fff
 
 int sssnic_hw_init(struct sssnic_hw *hw);
 void sssnic_hw_shutdown(struct sssnic_hw *hw);
diff --git a/drivers/net/sssnic/base/sssnic_msg.c b/drivers/net/sssnic/base/sssnic_msg.c
new file mode 100644
index 0000000000..4b98fee75b
--- /dev/null
+++ b/drivers/net/sssnic/base/sssnic_msg.c
@@ -0,0 +1,254 @@ 
+/* SPDX-License-Identifier: BSD-3-Clause
+ * Copyright(c) 2018-2022 Shenzhen 3SNIC Information Technology Co., Ltd.
+ */
+
+#include <rte_common.h>
+#include <rte_malloc.h>
+#include <rte_mempool.h>
+#include <rte_memcpy.h>
+
+#include "../sssnic_log.h"
+#include "sssnic_hw.h"
+#include "sssnic_msg.h"
+
+/* Receive message segment based on message header
+ * @param msghdr
+ *	message header
+ * @param msg
+ *	message where segment store
+ * @return
+ *	SSSNIC_MSG_REJECT - Message segment was not received because of bad
+ *                          parameter of message header.
+ *	SSSNIC_MSG_ACCEPT - Message segment was received.
+ *	SSSNIC_MSG_DONE   - The last message segment was received.
+ */
+static int
+sssnic_msg_rx_seg(struct sssnic_msg_hdr *msghdr, struct sssnic_msg *msg)
+{
+	if (msghdr->seg_id > SSSNIC_MSG_MAX_SEG_ID ||
+		msghdr->seg_len > SSSNIC_MSG_MAX_SEG_SIZE) {
+		PMD_DRV_LOG(ERR,
+			"Bad segment id or segment size of message header");
+		return SSSNIC_MSG_REJECT;
+	}
+
+	if (msghdr->seg_id == 0) {
+		msg->command = msghdr->command;
+		msg->type = msghdr->type;
+		msg->module = msghdr->module;
+		msg->id = msghdr->id;
+	} else {
+		if (msghdr->seg_id != (msg->seg + 1) || msghdr->id != msg->id ||
+			msghdr->module != msg->module ||
+			msghdr->command != msg->command) {
+			PMD_DRV_LOG(ERR, "Bad parameters of message header");
+			return SSSNIC_MSG_REJECT;
+		}
+	}
+	rte_memcpy(msg->data_buf + (SSSNIC_MSG_MAX_SEG_SIZE * msghdr->seg_id),
+		SSSNIC_MSG_DATA(msghdr), msghdr->seg_len);
+
+	if (!msghdr->last_seg) {
+		msg->seg = msghdr->seg_id;
+		return SSSNIC_MSG_ACCEPT;
+	}
+
+	msg->ack = !msghdr->no_response;
+	msg->status = msghdr->status;
+	msg->data_len = msghdr->length;
+	msg->func = msghdr->function;
+	msg->seg = SSSNIC_MSG_MAX_SEG_ID;
+
+	return SSSNIC_MSG_DONE;
+}
+
+static int
+sssnic_msg_buf_alloc(struct sssnic_msg *msg, size_t size)
+{
+	msg->data_buf = rte_zmalloc("sssnic_msg_data", size, 1);
+	if (msg->data_buf == NULL) {
+		PMD_DRV_LOG(ERR, "Could not all message data buffer!");
+		return -ENOMEM;
+	}
+
+	return 0;
+}
+
+static void
+sssnic_msg_buf_free(struct sssnic_msg *msg)
+{
+	rte_free(msg->data_buf);
+}
+
+int
+sssnic_msg_rx_handle(struct sssnic_hw *hw, struct sssnic_msg_hdr *msghdr)
+{
+	struct sssnic_msg *msg;
+	struct sssnic_msg_handler *msg_handler;
+	int msg_src;
+	int msg_chan;
+	int msg_type;
+	int ret;
+
+	msg_src = SSSNIC_MSG_SRC(msghdr->function);
+	msg_chan = msghdr->channel;
+	msg_type = msghdr->type;
+	msg = SSSNIC_MSG_LOCATE(hw, msg_chan, msg_type, msg_src);
+
+	ret = sssnic_msg_rx_seg(msghdr, msg);
+	if (ret != SSSNIC_MSG_DONE)
+		return ret;
+
+	msg_handler = SSSNIC_MSG_HANDLER(hw, msg_chan, msg_type);
+	if (msg_handler->func == NULL) {
+		PMD_DRV_LOG(NOTICE,
+			"No message handler, message channel:%d, type:%d.",
+			msg_chan, msg_type);
+		return SSSNIC_MSG_REJECT;
+	}
+	ret = msg_handler->func(msg, msg_chan, msg_handler->priv);
+
+	return ret;
+}
+
+int
+sssnic_msg_rx_handler_register(struct sssnic_hw *hw,
+	enum sssnic_msg_chann_id chann_id, enum sssnic_msg_type msg_type,
+	sssnic_msg_handler_func_t *func, void *priv)
+{
+	struct sssnic_msg_handler *msg_handler;
+
+	if (chann_id >= SSSNIC_MSG_CHAN_COUNT ||
+		msg_type >= SSSNIC_MSG_TYPE_CONUT || func == NULL) {
+		PMD_DRV_LOG(ERR,
+			"Bad parameters for register rx message handler.");
+		return -EINVAL;
+	}
+
+	msg_handler = SSSNIC_MSG_HANDLER(hw, chann_id, msg_type);
+	if (msg_handler->func != NULL)
+		PMD_DRV_LOG(WARNING,
+			"RX message handler has existed, chann_id:%u, msg_type:%u",
+			chann_id, msg_type);
+
+	msg_handler->func = func;
+	msg_handler->priv = priv;
+
+	return 0;
+}
+
+static int
+sssnic_msg_channel_init(struct sssnic_hw *hw, struct sssnic_msg_channel *chan)
+{
+	struct sssnic_msg *msg;
+	int i;
+	int ret;
+
+	PMD_INIT_FUNC_TRACE();
+
+	for (i = 0; i < SSSNIC_MSG_TYPE_CONUT; i++) {
+		msg = &chan->msg[i][SSSNIC_MSG_SRC_MPU];
+		ret = sssnic_msg_buf_alloc(msg, SSSNIC_MSG_BUF_SIZE);
+		if (ret) {
+			PMD_DRV_LOG(ERR,
+				"Could not alloc MPU message buf for message inbox channel %d of sssnic%u.",
+				SSSNIC_ETH_PORT_ID(hw), chan->id);
+			goto msg_buf_alloc_fail;
+		}
+		msg = &chan->msg[i][SSSNIC_MSG_SRC_PF];
+		ret = sssnic_msg_buf_alloc(msg, SSSNIC_MSG_BUF_SIZE);
+		if (ret) {
+			PMD_DRV_LOG(ERR,
+				"Could not alloc PF message buf for message inbox channel %d of sssnic%u.",
+				SSSNIC_ETH_PORT_ID(hw), chan->id);
+			msg = &chan->msg[i][SSSNIC_MSG_SRC_MPU];
+			sssnic_msg_buf_free(msg);
+			goto msg_buf_alloc_fail;
+		}
+	}
+
+	return 0;
+
+msg_buf_alloc_fail:
+	while (i--) {
+		msg = &chan->msg[i][SSSNIC_MSG_SRC_MPU];
+		sssnic_msg_buf_free(msg);
+		msg = &chan->msg[i][SSSNIC_MSG_SRC_PF];
+		sssnic_msg_buf_free(msg);
+	}
+	return ret;
+}
+
+static void
+sssnic_msg_channel_shutdown(__rte_unused struct sssnic_hw *hw,
+	struct sssnic_msg_channel *chan)
+{
+	struct sssnic_msg *msg;
+	int i;
+
+	PMD_INIT_FUNC_TRACE();
+
+	for (i = 0; i < SSSNIC_MSG_TYPE_CONUT; i++) {
+		msg = &chan->msg[i][SSSNIC_MSG_SRC_MPU];
+		sssnic_msg_buf_free(msg);
+		msg = &chan->msg[i][SSSNIC_MSG_SRC_PF];
+		sssnic_msg_buf_free(msg);
+	}
+}
+
+int
+sssnic_msg_inbox_init(struct sssnic_hw *hw)
+{
+	struct sssnic_msg_inbox *inbox;
+	struct sssnic_msg_channel *chan;
+	int i;
+	int ret;
+
+	PMD_INIT_FUNC_TRACE();
+
+	inbox = rte_zmalloc(NULL, sizeof(struct sssnic_msg_inbox), 1);
+	if (inbox == NULL) {
+		PMD_DRV_LOG(ERR, "Could not alloc memory for message inbox");
+		return -ENOMEM;
+	}
+
+	inbox->hw = hw;
+	hw->msg_inbox = inbox;
+
+	for (i = 0; i < SSSNIC_MSG_CHAN_COUNT; i++) {
+		chan = &inbox->channel[i];
+		ret = sssnic_msg_channel_init(hw, chan);
+		if (ret) {
+			PMD_DRV_LOG(ERR,
+				"Failed to initialize channel%u of message inbox",
+				i);
+			goto init_msg_channel_fail;
+		}
+		chan->id = i;
+	}
+
+	return 0;
+
+init_msg_channel_fail:
+	while (i--) {
+		chan = &inbox->channel[i];
+		sssnic_msg_channel_shutdown(hw, chan);
+	}
+	rte_free(inbox);
+	return ret;
+}
+
+void
+sssnic_msg_inbox_shutdown(struct sssnic_hw *hw)
+{
+	struct sssnic_msg_channel *chan;
+	int i;
+
+	PMD_INIT_FUNC_TRACE();
+
+	for (i = 0; i < SSSNIC_MSG_CHAN_COUNT; i++) {
+		chan = &hw->msg_inbox->channel[i];
+		sssnic_msg_channel_shutdown(hw, chan);
+	}
+	rte_free(hw->msg_inbox);
+}
diff --git a/drivers/net/sssnic/base/sssnic_msg.h b/drivers/net/sssnic/base/sssnic_msg.h
new file mode 100644
index 0000000000..6580f4bb37
--- /dev/null
+++ b/drivers/net/sssnic/base/sssnic_msg.h
@@ -0,0 +1,166 @@ 
+/* SPDX-License-Identifier: BSD-3-Clause
+ * Copyright(c) 2018-2022 Shenzhen 3SNIC Information Technology Co., Ltd.
+ */
+
+#ifndef _SSSNIC_MSG_H_
+#define _SSSNIC_MSG_H_
+
+#include <string.h>
+
+enum sssnic_msg_chann_id {
+	SSSNIC_MSG_CHAN_MPU = 0, /* Message comes from MPU directly */
+	SSSNIC_MSG_CHAN_MBOX = 1, /* Message comes from MBOX */
+	SSSNIC_MSG_CHAN_COUNT = 2,
+};
+
+enum sssnic_msg_src {
+	SSSNIC_MSG_SRC_MPU, /* mbox message from MPU */
+	SSSNIC_MSG_SRC_PF, /* mbox message from PF */
+	SSSNIC_MSG_SRC_COUNT,
+};
+
+#define SSSNIC_MSG_SRC(func_id)                                                \
+	(((func_id) == SSSNIC_MPU_FUNC_IDX) ? SSSNIC_MSG_SRC_MPU :             \
+						    SSSNIC_MSG_SRC_PF)
+
+enum sssnic_msg_type {
+	SSSNIC_MSG_TYPE_REQ, /* Request message*/
+	SSSNIC_MSG_TYPE_RESP, /* Response message */
+	SSSNIC_MSG_TYPE_CONUT,
+};
+
+#define SSSNIC_MSG_TRANS_MODE_DMA 1
+#define SSSNIC_MSG_TRANS_MODE_INLINE 0
+
+/* hardware format of sssnic message header */
+struct sssnic_msg_hdr {
+	union {
+		uint64_t u64;
+		struct {
+			uint32_t dw0;
+			uint32_t dw1;
+		};
+		struct {
+			/* Id of the function the message comes from or send to */
+			uint64_t function : 13;
+			/* indicate the result of command */
+			uint64_t status : 2;
+			/* Mbox channel that message receive from or send to */
+			uint64_t channel : 1;
+			/* ID of the EventQ that response message is informed by */
+			uint64_t eventq : 2;
+			/* Message ID */
+			uint64_t id : 4;
+			/* Command ID of the message */
+			uint64_t command : 10;
+			/* total length of message data */
+			uint64_t length : 11;
+			/* Module of message comes from or send to */
+			uint64_t module : 5;
+			/* Length of this data segment */
+			uint64_t seg_len : 6;
+			/* needless response indication */
+			uint64_t no_response : 1;
+			/* Message data transmission mode, 0: inline 1:dma */
+			uint64_t trans_mode : 1;
+			/* Segment sequence of message data */
+			uint64_t seg_id : 6;
+			/* Last data segment indication, 1: Last segment */
+			uint64_t last_seg : 1;
+			/* Message type, see sssnic_mbox_msg_type */
+			uint64_t type : 1;
+		};
+	};
+};
+#define SSSNIC_MSG_HDR_SIZE sizeof(struct sssnic_msg_hdr)
+#define SSSNIC_MSG_DATA(hdr) (((uint8_t *)hdr) + SSSNIC_MSG_HDR_SIZE)
+
+#define SSSNIC_MSG_BUF_SIZE 2048UL
+#define SSSNIC_MSG_MAX_SEG_SIZE 48
+#define SSSNIC_MSG_MIN_SGE_ID 0
+#define SSSNIC_MSG_MAX_SEG_ID 42
+#define SSSNIC_MSG_MAX_DATA_SIZE (SSSNIC_MSG_BUF_SIZE - SSSNIC_MSG_HDR_SIZE)
+
+struct sssnic_msg {
+	/* message command ID */
+	uint16_t command;
+	/* function id of that message send to or receive from */
+	uint16_t func;
+	/* module id of that message send to or receive from */
+	uint32_t module;
+	/* message is request or response*/
+	enum sssnic_msg_type type;
+	/* message data */
+	uint8_t *data_buf;
+	/* data length */
+	uint32_t data_len;
+	/* need response indication */
+	uint8_t ack;
+	/* the id of last received segment*/
+	uint8_t seg;
+	/* indicate the result of request in response message, request failed if not 0 */
+	uint8_t status;
+	/* generated by sender if dir == SSSNIC_MSG_TYPE_REQ */
+	uint8_t id;
+};
+
+#define SSSNIC_MSG_REJECT -1
+#define SSSNIC_MSG_ACCEPT 0
+#define SSSNIC_MSG_DONE 1
+
+/* sssnic message handler function
+ * @return
+ *   SSSNIC_MSG_REJECT - Message failed to handle
+ *   SSSNIC_MSG_DONE   - Message succeed to handle
+ */
+typedef int sssnic_msg_handler_func_t(struct sssnic_msg *msg,
+	enum sssnic_msg_chann_id chan_id, void *priv);
+
+struct sssnic_msg_handler {
+	sssnic_msg_handler_func_t *func;
+	void *priv;
+};
+
+struct sssnic_msg_channel {
+	enum sssnic_msg_chann_id id;
+	struct sssnic_msg msg[SSSNIC_MSG_TYPE_CONUT][SSSNIC_MSG_SRC_COUNT];
+	struct sssnic_msg_handler handler[SSSNIC_MSG_TYPE_CONUT];
+};
+
+struct sssnic_msg_inbox {
+	struct sssnic_hw *hw;
+	struct sssnic_msg_channel channel[SSSNIC_MSG_CHAN_COUNT];
+};
+
+#define SSSNIC_MSG_INBOX(hw) ((hw)->msg_inbox)
+#define SSSNIC_MSG_CHANNEL(hw, chann_id)                                       \
+	(&(SSSNIC_MSG_INBOX(hw)->channel[chann_id]))
+#define SSSNIC_MSG_LOCATE(hw, chann_id, type, src)                             \
+	(&SSSNIC_MSG_CHANNEL(hw, chann_id)->msg[type][src])
+#define SSSNIC_MSG_HANDLER(hw, chann_id, type)                                 \
+	(&SSSNIC_MSG_CHANNEL(hw, chann_id)->handler[type])
+
+static inline void
+sssnic_msg_init(struct sssnic_msg *msg, uint8_t *data, uint32_t data_len,
+	uint16_t command, uint16_t func, uint32_t module,
+	enum sssnic_msg_type type)
+{
+	memset(msg, 0, sizeof(struct sssnic_msg));
+	msg->data_buf = data;
+	msg->data_len = data_len;
+	msg->command = command;
+	msg->module = module;
+	msg->func = func;
+	msg->type = type;
+}
+
+int sssnic_msg_rx_handler_register(struct sssnic_hw *hw,
+	enum sssnic_msg_chann_id chann_id, enum sssnic_msg_type msg_type,
+	sssnic_msg_handler_func_t *func, void *priv);
+int sssnic_msg_rx_handle(struct sssnic_hw *hw, struct sssnic_msg_hdr *msghdr);
+int sssnic_msg_inbox_init(struct sssnic_hw *hw);
+void sssnic_msg_inbox_shutdown(struct sssnic_hw *hw);
+int sssnic_msg_rx(struct sssnic_msg_hdr *msghdr, uint16_t max_seg_len,
+	uint16_t max_seg_id, struct sssnic_msg *msg);
+
+#endif /* _SSSNIC_MSG_H_ */