Thread (32 messages) 32 messages, 2 authors, 2021-12-23
STALE1674d
Revisions (5)
  1. v1 current
  2. v2 [diff vs current]
  3. v3 [diff vs current]
  4. v4 [diff vs current]
  5. v6 [diff vs current]

[PATCH v1 05/25] net/spnic: add mgmt module

From: Yanling Song <hidden>
Date: 2021-12-18 02:52:31
Subsystem: networking drivers, the rest · Maintainers: Andrew Lunn, "David S. Miller", Eric Dumazet, Jakub Kicinski, Paolo Abeni, Linus Torvalds

Mgmt module manage the message gerenated from the hardware.
This patch implements mgmt module initialization, related event
processing and message command definition.

Signed-off-by: Yanling Song <redacted>
---
 drivers/net/spnic/base/meson.build       |   4 +-
 drivers/net/spnic/base/spnic_cmd.h       | 222 ++++++++++++++
 drivers/net/spnic/base/spnic_eqs.c       |  46 ++-
 drivers/net/spnic/base/spnic_hwdev.c     |  91 +++++-
 drivers/net/spnic/base/spnic_hwdev.h     |  66 +++-
 drivers/net/spnic/base/spnic_mbox.c      |  17 ++
 drivers/net/spnic/base/spnic_mgmt.c      | 367 +++++++++++++++++++++++
 drivers/net/spnic/base/spnic_mgmt.h      |  74 +++++
 drivers/net/spnic/base/spnic_nic_event.c | 171 +++++++++++
 drivers/net/spnic/base/spnic_nic_event.h |  34 +++
 10 files changed, 1081 insertions(+), 11 deletions(-)
 create mode 100644 drivers/net/spnic/base/spnic_cmd.h
 create mode 100644 drivers/net/spnic/base/spnic_mgmt.c
 create mode 100644 drivers/net/spnic/base/spnic_nic_event.c
 create mode 100644 drivers/net/spnic/base/spnic_nic_event.h
diff --git a/drivers/net/spnic/base/meson.build b/drivers/net/spnic/base/meson.build
index ce7457f400..3f6a060b37 100644
--- a/drivers/net/spnic/base/meson.build
+++ b/drivers/net/spnic/base/meson.build
@@ -5,7 +5,9 @@ sources = [
 	'spnic_eqs.c',
 	'spnic_hwdev.c',
 	'spnic_hwif.c',
-	'spnic_mbox.c'
+	'spnic_mbox.c',
+	'spnic_mgmt.c',
+	'spnic_nic_event.c'
 ]
 
 extra_flags = []
diff --git a/drivers/net/spnic/base/spnic_cmd.h b/drivers/net/spnic/base/spnic_cmd.h
new file mode 100644
index 0000000000..8900489eef
--- /dev/null
+++ b/drivers/net/spnic/base/spnic_cmd.h
@@ -0,0 +1,222 @@
+/* SPDX-License-Identifier: BSD-3-Clause
+ * Copyright(c) 2021 Ramaxel Memory Technology, Ltd
+ */
+
+#ifndef _SPNIC_CMD_H_
+#define _SPNIC_CMD_H_
+
+#define NIC_RSS_TEMP_ID_TO_CTX_LT_IDX(tmp_id)	tmp_id
+/* Begin of one temp tbl */
+#define NIC_RSS_TEMP_ID_TO_INDIR_LT_IDX(tmp_id)	((tmp_id) << 4)
+/* 4 ctx in one entry */
+#define NIC_RSS_CTX_TBL_ENTRY_SIZE		0x10
+/* Entry size = 16B, 16 entry/template */
+#define NIC_RSS_INDIR_TBL_ENTRY_SIZE		0x10
+/* Entry size = 16B, so entry_num = 256B/16B */
+#define NIC_RSS_INDIR_TBL_ENTRY_NUM		0x10
+
+#define NIC_UP_RSS_INVALID_TEMP_ID		0xFF
+#define NIC_UP_RSS_INVALID_FUNC_ID		0xFFFF
+#define NIC_UP_RSS_INVALID			0x00
+#define NIC_UP_RSS_EN				0x01
+#define NIC_UP_RSS_INVALID_GROUP_ID		0x7F
+
+#define NIC_RSS_CMD_TEMP_ALLOC			0x01
+#define NIC_RSS_CMD_TEMP_FREE			0x02
+
+#define SPNIC_RSS_TYPE_VALID_SHIFT		23
+#define SPNIC_RSS_TYPE_TCP_IPV6_EXT_SHIFT	24
+#define SPNIC_RSS_TYPE_IPV6_EXT_SHIFT		25
+#define SPNIC_RSS_TYPE_TCP_IPV6_SHIFT		26
+#define SPNIC_RSS_TYPE_IPV6_SHIFT		27
+#define SPNIC_RSS_TYPE_TCP_IPV4_SHIFT		28
+#define SPNIC_RSS_TYPE_IPV4_SHIFT		29
+#define SPNIC_RSS_TYPE_UDP_IPV6_SHIFT		30
+#define SPNIC_RSS_TYPE_UDP_IPV4_SHIFT		31
+#define SPNIC_RSS_TYPE_SET(val, member)	\
+	(((u32)(val) & 0x1) << SPNIC_RSS_TYPE_##member##_SHIFT)
+
+#define SPNIC_RSS_TYPE_GET(val, member)	\
+	(((u32)(val) >> SPNIC_RSS_TYPE_##member##_SHIFT) & 0x1)
+
+/* NIC CMDQ MODE */
+typedef enum spnic_ucode_cmd {
+	SPNIC_UCODE_CMD_MODIFY_QUEUE_CTX = 0,
+	SPNIC_UCODE_CMD_CLEAN_QUEUE_CONTEXT,
+	SPNIC_UCODE_CMD_ARM_SQ,
+	SPNIC_UCODE_CMD_ARM_RQ,
+	SPNIC_UCODE_CMD_SET_RSS_INDIR_TABLE,
+	SPNIC_UCODE_CMD_SET_RSS_CONTEXT_TABLE,
+	SPNIC_UCODE_CMD_GET_RSS_INDIR_TABLE,
+	SPNIC_UCODE_CMD_GET_RSS_CONTEXT_TABLE,
+	SPNIC_UCODE_CMD_SET_IQ_ENABLE,
+	SPNIC_UCODE_CMD_SET_RQ_FLUSH = 10,
+	SPNIC_UCODE_CMD_MODIFY_VLAN_CTX,
+	SPNIC_UCODE_CMD_DPI_FLOW
+} cmdq_nic_subtype_e;
+
+/*
+ * Commands between NIC and MPU
+ */
+enum spnic_cmd {
+	SPNIC_CMD_VF_REGISTER = 0, /* only for PFD and VFD */
+
+	/* FUNC CFG */
+	SPNIC_CMD_SET_FUNC_TBL = 5,
+	SPNIC_CMD_SET_VPORT_ENABLE,
+	SPNIC_CMD_SET_RX_MODE,
+	SPNIC_CMD_SQ_CI_ATTR_SET,
+	SPNIC_CMD_GET_VPORT_STAT,
+	SPNIC_CMD_CLEAN_VPORT_STAT,
+	SPNIC_CMD_CLEAR_QP_RESOURCE,
+	SPNIC_CMD_CFG_FLEX_QUEUE,
+	/* LRO CFG */
+	SPNIC_CMD_CFG_RX_LRO,
+	SPNIC_CMD_CFG_LRO_TIMER,
+	SPNIC_CMD_FEATURE_NEGO,
+
+	/* MAC & VLAN CFG */
+	SPNIC_CMD_GET_MAC = 20,
+	SPNIC_CMD_SET_MAC,
+	SPNIC_CMD_DEL_MAC,
+	SPNIC_CMD_UPDATE_MAC,
+	SPNIC_CMD_GET_ALL_DEFAULT_MAC,
+
+	SPNIC_CMD_CFG_FUNC_VLAN,
+	SPNIC_CMD_SET_VLAN_FILTER_EN,
+	SPNIC_CMD_SET_RX_VLAN_OFFLOAD,
+
+	/* SR-IOV */
+	SPNIC_CMD_CFG_VF_VLAN = 40,
+	SPNIC_CMD_SET_SPOOPCHK_STATE,
+	/* RATE LIMIT */
+	SPNIC_CMD_SET_MAX_MIN_RATE,
+
+	/* RSS CFG */
+	SPNIC_CMD_RSS_CFG = 60,
+	SPNIC_CMD_RSS_TEMP_MGR,
+	SPNIC_CMD_GET_RSS_CTX_TBL,
+	SPNIC_CMD_CFG_RSS_HASH_KEY,
+	SPNIC_CMD_CFG_RSS_HASH_ENGINE,
+	SPNIC_CMD_GET_INDIR_TBL,
+
+	/* DPI/FDIR */
+	SPNIC_CMD_ADD_TC_FLOW = 80,
+	SPNIC_CMD_DEL_TC_FLOW,
+	SPNIC_CMD_GET_TC_FLOW,
+	SPNIC_CMD_FLUSH_TCAM,
+	SPNIC_CMD_CFG_TCAM_BLOCK,
+	SPNIC_CMD_ENABLE_TCAM,
+	SPNIC_CMD_GET_TCAM_BLOCK,
+
+	/* PORT CFG */
+	SPNIC_CMD_SET_PORT_ENABLE = 100,
+	SPNIC_CMD_CFG_PAUSE_INFO,
+
+	SPNIC_CMD_SET_PORT_CAR,
+	SPNIC_CMD_SET_ER_DROP_PKT,
+
+	SPNIC_CMD_VF_COS,
+	SPNIC_CMD_SETUP_COS_MAPPING,
+	SPNIC_CMD_SET_ETS,
+	SPNIC_CMD_SET_PFC,
+
+	/* MISC */
+	SPNIC_CMD_BIOS_CFG = 120,
+	SPNIC_CMD_SET_FIRMWARE_CUSTOM_PACKETS_MSG,
+
+	/* DFX */
+	SPNIC_CMD_GET_SM_TABLE = 140,
+	SPNIC_CMD_RD_LINE_TBL,
+
+	SPNIC_CMD_MAX = 256
+};
+
+/* COMM commands between driver to MPU */
+enum spnic_mgmt_cmd {
+	MGMT_CMD_FUNC_RESET = 0,
+	MGMT_CMD_FEATURE_NEGO,
+	MGMT_CMD_FLUSH_DOORBELL,
+	MGMT_CMD_START_FLUSH,
+	MGMT_CMD_SET_FUNC_FLR,
+
+	MGMT_CMD_SET_CMDQ_CTXT = 20,
+	MGMT_CMD_SET_VAT,
+	MGMT_CMD_CFG_PAGESIZE,
+	MGMT_CMD_CFG_MSIX_CTRL_REG,
+	MGMT_CMD_SET_CEQ_CTRL_REG,
+	MGMT_CMD_SET_DMA_ATTR,
+
+	MGMT_CMD_GET_MQM_FIX_INFO = 40,
+	MGMT_CMD_SET_MQM_CFG_INFO,
+	MGMT_CMD_SET_MQM_SRCH_GPA,
+	MGMT_CMD_SET_PPF_TMR,
+	MGMT_CMD_SET_PPF_HT_GPA,
+	MGMT_CMD_SET_FUNC_TMR_BITMAT,
+
+	MGMT_CMD_GET_FW_VERSION = 60,
+	MGMT_CMD_GET_BOARD_INFO,
+	MGMT_CMD_SYNC_TIME,
+	MGMT_CMD_GET_HW_PF_INFOS,
+	MGMT_CMD_SEND_BDF_INFO,
+
+	MGMT_CMD_UPDATE_FW = 80,
+	MGMT_CMD_ACTIVE_FW,
+	MGMT_CMD_HOT_ACTIVE_FW,
+	MGMT_CMD_HOT_ACTIVE_DONE_NOTICE,
+	MGMT_CMD_SWITCH_CFG,
+	MGMT_CMD_CHECK_FLASH,
+	MGMT_CMD_CHECK_FLASH_RW,
+	MGMT_CMD_RESOURCE_CFG,
+	MGMT_CMD_UPDATE_BIOS,
+
+	MGMT_CMD_FAULT_REPORT = 100,
+	MGMT_CMD_WATCHDOG_INFO,
+	MGMT_CMD_MGMT_RESET,
+	MGMT_CMD_FFM_SET,
+
+	MGMT_CMD_GET_LOG = 120,
+	MGMT_CMD_TEMP_OP,
+	MGMT_CMD_EN_AUTO_RST_CHIP,
+	MGMT_CMD_CFG_REG,
+	MGMT_CMD_GET_CHIP_ID,
+	MGMT_CMD_SYSINFO_DFX,
+	MGMT_CMD_PCIE_DFX_NTC,
+};
+
+enum mag_cmd {
+	SERDES_CMD_PROCESS = 0,
+
+	MAG_CMD_SET_PORT_CFG      = 1,
+	MAG_CMD_SET_PORT_ADAPT    = 2,
+	MAG_CMD_CFG_LOOPBACK_MODE = 3,
+
+	MAG_CMD_GET_PORT_ENABLE   = 5,
+	MAG_CMD_SET_PORT_ENABLE   = 6,
+	MAG_CMD_GET_LINK_STATUS   = 7,
+	MAG_CMD_SET_LINK_FOLLOW   = 8,
+	MAG_CMD_SET_PMA_ENABLE    = 9,
+	MAG_CMD_CFG_FEC_MODE      = 10,
+
+	/* PHY */
+	MAG_CMD_GET_XSFP_INFO        = 60,
+	MAG_CMD_SET_XSFP_ENABLE      = 61,
+	MAG_CMD_GET_XSFP_PRESENT     = 62,
+	MAG_CMD_SET_XSFP_RW          = 63,
+	MAG_CMD_CFG_XSFP_TEMPERATURE = 64,
+
+	MAG_CMD_WIRE_EVENT        = 100,
+	MAG_CMD_LINK_ERR_EVENT    = 101,
+
+	MAG_CMD_EVENT_PORT_INFO   = 150,
+	MAG_CMD_GET_PORT_STAT     = 151,
+	MAG_CMD_CLR_PORT_STAT     = 152,
+	MAG_CMD_GET_PORT_INFO     = 153,
+	MAG_CMD_GET_PCS_ERR_CNT   = 154,
+	MAG_CMD_GET_MAG_CNT       = 155,
+	MAG_CMD_DUMP_ANTRAIN_INFO = 156,
+
+	MAG_CMD_MAX = 0xFF
+};
+
+#endif /* _SPNIC_CMD_H_ */
diff --git a/drivers/net/spnic/base/spnic_eqs.c b/drivers/net/spnic/base/spnic_eqs.c
index 7953976441..ee52252ecc 100644
--- a/drivers/net/spnic/base/spnic_eqs.c
+++ b/drivers/net/spnic/base/spnic_eqs.c
@@ -12,6 +12,7 @@
 #include "spnic_eqs.h"
 #include "spnic_mgmt.h"
 #include "spnic_mbox.h"
+#include "spnic_nic_event.h"
 
 #define AEQ_CTRL_0_INTR_IDX_SHIFT		0
 #define AEQ_CTRL_0_DMA_ATTR_SHIFT		12
@@ -510,6 +511,39 @@ void spnic_aeqs_free(struct spnic_hwdev *hwdev)
 	rte_free(aeqs);
 }
 
+void spnic_dump_aeq_info(struct spnic_hwdev *hwdev)
+{
+	struct spnic_aeq_elem *aeqe_pos = NULL;
+	struct spnic_eq *eq = NULL;
+	u32 addr, ci, pi, ctrl0, idx;
+	int q_id;
+
+	for (q_id = 0; q_id < hwdev->aeqs->num_aeqs; q_id++) {
+		eq = &hwdev->aeqs->aeq[q_id];
+		/* Indirect access should set q_id first */
+		spnic_hwif_write_reg(eq->hwdev->hwif, SPNIC_AEQ_INDIR_IDX_ADDR,
+				     eq->q_id);
+		rte_wmb(); /* Write index before config */
+
+		addr = SPNIC_CSR_AEQ_CTRL_0_ADDR;
+
+		ctrl0 = spnic_hwif_read_reg(hwdev->hwif, addr);
+
+		idx = spnic_hwif_read_reg(hwdev->hwif,
+					  SPNIC_AEQ_INDIR_IDX_ADDR);
+
+		addr = SPNIC_CSR_AEQ_CONS_IDX_ADDR;
+		ci = spnic_hwif_read_reg(hwdev->hwif, addr);
+		addr = SPNIC_CSR_AEQ_PROD_IDX_ADDR;
+		pi = spnic_hwif_read_reg(hwdev->hwif, addr);
+		aeqe_pos = GET_CURR_AEQ_ELEM(eq);
+		PMD_DRV_LOG(ERR, "Aeq id: %d, idx: %u, ctrl0: 0x%08x, wrap: %d,"
+			    " pi: 0x%x, ci: 0x%08x,  desc: 0x%x", q_id, idx,
+			    ctrl0, eq->wrapped, pi, ci,
+			    be32_to_cpu(aeqe_pos->desc));
+	}
+}
+
 static int aeq_elem_handler(struct spnic_eq *eq, u32 aeqe_desc,
 			    struct spnic_aeq_elem *aeqe_pos, void *param)
 {
@@ -518,12 +552,22 @@ static int aeq_elem_handler(struct spnic_eq *eq, u32 aeqe_desc,
 	u8 size;
 
 	event = EQ_ELEM_DESC_GET(aeqe_desc, TYPE);
+	if (EQ_ELEM_DESC_GET(aeqe_desc, SRC)) {
+		/* SW event uses only the first 8B */
+		memcpy(data, aeqe_pos->aeqe_data, SPNIC_AEQE_DATA_SIZE);
+		spnic_be32_to_cpu(data, SPNIC_AEQE_DATA_SIZE);
+		/* Just support SPNIC_STATELESS_EVENT */
+		return spnic_nic_sw_aeqe_handler(eq->hwdev, event, data);
+	}
 
 	memcpy(data, aeqe_pos->aeqe_data, SPNIC_AEQE_DATA_SIZE);
 	spnic_be32_to_cpu(data, SPNIC_AEQE_DATA_SIZE);
 	size = EQ_ELEM_DESC_GET(aeqe_desc, SIZE);
 
-	if (event == SPNIC_MBX_FROM_FUNC) {
+	if (event == SPNIC_MSG_FROM_MGMT_CPU) {
+		return spnic_mgmt_msg_aeqe_handler(eq->hwdev, data, size,
+						   param);
+	} else if (event == SPNIC_MBX_FROM_FUNC) {
 		return spnic_mbox_func_aeqe_handler(eq->hwdev, data, size,
 						    param);
 	} else {
diff --git a/drivers/net/spnic/base/spnic_hwdev.c b/drivers/net/spnic/base/spnic_hwdev.c
index e45058423c..2b5154f8a4 100644
--- a/drivers/net/spnic/base/spnic_hwdev.c
+++ b/drivers/net/spnic/base/spnic_hwdev.c
@@ -7,6 +7,7 @@
 #include "spnic_hwif.h"
 #include "spnic_eqs.h"
 #include "spnic_mgmt.h"
+#include "spnic_cmd.h"
 #include "spnic_mbox.h"
 #include "spnic_hwdev.h"
 
@@ -18,7 +19,62 @@ struct mgmt_event_handle {
 	mgmt_event_cb proc;
 };
 
+int vf_handle_pf_comm_mbox(void *handle, __rte_unused void *pri_handle,
+			   __rte_unused u16 cmd, __rte_unused void *buf_in,
+			   __rte_unused u16 in_size, __rte_unused void *buf_out,
+			   __rte_unused u16 *out_size)
+{
+	struct spnic_hwdev *hwdev = handle;
+
+	if (!hwdev)
+		return -EINVAL;
+
+	PMD_DRV_LOG(WARNING, "Unsupported pf mbox event %d to process", cmd);
+
+	return 0;
+}
+
+static void fault_event_handler(__rte_unused void *hwdev,
+				__rte_unused void *buf_in,
+				__rte_unused u16 in_size,
+				__rte_unused void *buf_out,
+				__rte_unused u16 *out_size)
+{
+	PMD_DRV_LOG(WARNING, "Unsupported fault event handler");
+}
+
+static void ffm_event_msg_handler(__rte_unused void *hwdev,
+				  void *buf_in, u16 in_size,
+				  __rte_unused void *buf_out, u16 *out_size)
+{
+	struct ffm_intr_info *intr = NULL;
+
+	if (in_size != sizeof(*intr)) {
+		PMD_DRV_LOG(ERR, "Invalid fault event report, length: %d, should be %"PRIu64" ",
+			    in_size, sizeof(*intr));
+		return;
+	}
+
+	intr = buf_in;
+
+	PMD_DRV_LOG(ERR, "node_id: 0x%x, err_type: 0x%x, err_level: %d, "
+		    "err_csr_addr: 0x%08x, err_csr_value: 0x%08x",
+		    intr->node_id, intr->err_type, intr->err_level,
+		    intr->err_csr_addr, intr->err_csr_value);
+
+	*out_size = sizeof(*intr);
+}
+
 const struct mgmt_event_handle mgmt_event_proc[] = {
+	{
+		.cmd	= MGMT_CMD_FAULT_REPORT,
+		.proc	= fault_event_handler,
+	},
+
+	{
+		.cmd	= MGMT_CMD_FFM_SET,
+		.proc	= ffm_event_msg_handler,
+	},
 };
 
 void pf_handle_mgmt_comm_event(void *handle, __rte_unused void *pri_handle,
@@ -44,21 +100,30 @@ 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);
 }
 
-int vf_handle_pf_comm_mbox(void *handle, __rte_unused void *pri_handle,
-			   __rte_unused u16 cmd, __rte_unused void *buf_in,
-			   __rte_unused u16 in_size, __rte_unused void *buf_out,
-			   __rte_unused u16 *out_size)
+static int spnic_comm_pf_to_mgmt_init(struct spnic_hwdev *hwdev)
 {
-	struct spnic_hwdev *hwdev = handle;
+	int err;
 
-	if (!hwdev)
-		return -EINVAL;
+	/* VF does not support send msg to mgmt directly */
+	if (spnic_func_type(hwdev) == TYPE_VF)
+		return 0;
 
-	PMD_DRV_LOG(WARNING, "Unsupported pf mbox event %d to process", cmd);
+	err = spnic_pf_to_mgmt_init(hwdev);
+	if (err)
+		return err;
 
 	return 0;
 }
 
+static void spnic_comm_pf_to_mgmt_free(struct spnic_hwdev *hwdev)
+{
+	/* VF does not support send msg to mgmt directly */
+	if (spnic_func_type(hwdev) == TYPE_VF)
+		return;
+
+	spnic_pf_to_mgmt_free(hwdev);
+}
+
 static int init_mgmt_channel(struct spnic_hwdev *hwdev)
 {
 	int err;
@@ -69,6 +134,12 @@ static int init_mgmt_channel(struct spnic_hwdev *hwdev)
 		return err;
 	}
 
+	err = spnic_comm_pf_to_mgmt_init(hwdev);
+	if (err) {
+		PMD_DRV_LOG(ERR, "Init mgmt channel failed");
+		goto msg_init_err;
+	}
+
 	err = spnic_func_to_func_init(hwdev);
 	if (err) {
 		PMD_DRV_LOG(ERR, "Init mailbox channel failed");
@@ -78,6 +149,9 @@ static int init_mgmt_channel(struct spnic_hwdev *hwdev)
 	return 0;
 
 func_to_func_init_err:
+	spnic_comm_pf_to_mgmt_free(hwdev);
+
+msg_init_err:
 	spnic_aeqs_free(hwdev);
 
 	return err;
@@ -86,6 +160,7 @@ static int init_mgmt_channel(struct spnic_hwdev *hwdev)
 static void free_mgmt_channel(struct spnic_hwdev *hwdev)
 {
 	spnic_func_to_func_free(hwdev);
+	spnic_comm_pf_to_mgmt_free(hwdev);
 	spnic_aeqs_free(hwdev);
 }
 
diff --git a/drivers/net/spnic/base/spnic_hwdev.h b/drivers/net/spnic/base/spnic_hwdev.h
index a0691eed2e..4e77d776ee 100644
--- a/drivers/net/spnic/base/spnic_hwdev.h
+++ b/drivers/net/spnic/base/spnic_hwdev.h
@@ -7,7 +7,6 @@
 
 #include <rte_ether.h>
 
-#define SPNIC_CHIP_FAULT_SIZE		(110 * 1024)
 struct cfg_mgmt_info;
 struct spnic_hwif;
 struct spnic_aeqs;
@@ -24,6 +23,70 @@ struct ffm_intr_info {
 	u32 err_csr_value;
 };
 
+struct link_event_stats {
+	u32 link_down_stats;
+	u32 link_up_stats;
+};
+
+enum spnic_fault_err_level {
+	FAULT_LEVEL_FATAL,
+	FAULT_LEVEL_SERIOUS_RESET,
+	FAULT_LEVEL_SERIOUS_FLR,
+	FAULT_LEVEL_GENERAL,
+	FAULT_LEVEL_SUGGESTION,
+	FAULT_LEVEL_MAX
+};
+
+enum spnic_fault_type {
+	FAULT_TYPE_CHIP,
+	FAULT_TYPE_UCODE,
+	FAULT_TYPE_MEM_RD_TIMEOUT,
+	FAULT_TYPE_MEM_WR_TIMEOUT,
+	FAULT_TYPE_REG_RD_TIMEOUT,
+	FAULT_TYPE_REG_WR_TIMEOUT,
+	FAULT_TYPE_PHY_FAULT,
+	FAULT_TYPE_MAX
+};
+
+struct fault_event_stats {
+	rte_atomic32_t chip_fault_stats[22][FAULT_LEVEL_MAX];
+	rte_atomic32_t fault_type_stat[FAULT_TYPE_MAX];
+	rte_atomic32_t pcie_fault_stats;
+};
+
+struct spnic_hw_stats {
+	rte_atomic32_t heart_lost_stats;
+	struct link_event_stats link_event_stats;
+	struct fault_event_stats fault_event_stats;
+};
+
+#define SPNIC_CHIP_FAULT_SIZE		(110 * 1024)
+#define MAX_DRV_BUF_SIZE		4096
+
+struct nic_cmd_chip_fault_stats {
+	u32 offset;
+	u8 chip_fault_stats[MAX_DRV_BUF_SIZE];
+};
+
+struct spnic_board_info {
+	u8 board_type;
+	u8 port_num;
+	u8 port_speed;
+	u8 pcie_width;
+	u8 host_num;
+	u8 pf_num;
+	u16 vf_total_num;
+	u8 tile_num;
+	u8 qcm_num;
+	u8 core_num;
+	u8 work_mode;
+	u8 service_mode;
+	u8 pcie_mode;
+	u8 boot_sel;
+	u8 board_id;
+	u32 cfg_addr;
+};
+
 struct spnic_hwdev {
 	void *dev_handle; /* Pointer to spnic_nic_dev */
 	void *pci_dev; /* Pointer to rte_pci_device */
@@ -37,6 +100,7 @@ struct spnic_hwdev {
 	struct spnic_aeqs *aeqs;
 	struct spnic_msg_pf_to_mgmt *pf_to_mgmt;
 	u8 *chip_fault_stats;
+	struct spnic_hw_stats hw_stats;
 
 	u16 max_vfs;
 	u16 link_status;
diff --git a/drivers/net/spnic/base/spnic_mbox.c b/drivers/net/spnic/base/spnic_mbox.c
index 1677bd7404..5c39e307be 100644
--- a/drivers/net/spnic/base/spnic_mbox.c
+++ b/drivers/net/spnic/base/spnic_mbox.c
@@ -6,10 +6,12 @@
 #include "spnic_compat.h"
 #include "spnic_hwdev.h"
 #include "spnic_csr.h"
+#include "spnic_cmd.h"
 #include "spnic_mgmt.h"
 #include "spnic_hwif.h"
 #include "spnic_eqs.h"
 #include "spnic_mbox.h"
+#include "spnic_nic_event.h"
 
 #define SPNIC_MBOX_INT_DST_FUNC_SHIFT				0
 #define SPNIC_MBOX_INT_DST_AEQN_SHIFT				10
@@ -148,6 +150,21 @@ static int recv_vf_mbox_handler(struct spnic_mbox *func_to_func,
 					     recv_mbox->mbox_len,
 					     buf_out, out_size);
 		break;
+	case SPNIC_MOD_L2NIC:
+		err = spnic_vf_event_handler(func_to_func->hwdev,
+					     func_to_func->hwdev->cfg_mgmt,
+					     recv_mbox->cmd, recv_mbox->mbox,
+					     recv_mbox->mbox_len,
+					     buf_out, out_size);
+		break;
+	case SPNIC_MOD_HILINK:
+		err = spnic_vf_mag_event_handler(func_to_func->hwdev,
+						 func_to_func->hwdev->cfg_mgmt,
+						 recv_mbox->cmd,
+						 recv_mbox->mbox,
+						 recv_mbox->mbox_len,
+						 buf_out, out_size);
+		break;
 	default:
 		PMD_DRV_LOG(ERR, "No handler, mod: %d", recv_mbox->mod);
 		err = SPNIC_MBOX_VF_CMD_ERROR;
diff --git a/drivers/net/spnic/base/spnic_mgmt.c b/drivers/net/spnic/base/spnic_mgmt.c
new file mode 100644
index 0000000000..e202780411
--- /dev/null
+++ b/drivers/net/spnic/base/spnic_mgmt.c
@@ -0,0 +1,367 @@
+/* SPDX-License-Identifier: BSD-3-Clause
+ * Copyright(c) 2021 Ramaxel Memory Technology, Ltd
+ */
+
+#include <rte_ethdev.h>
+
+#include "spnic_compat.h"
+#include "spnic_hwdev.h"
+#include "spnic_eqs.h"
+#include "spnic_mgmt.h"
+#include "spnic_mbox.h"
+#include "spnic_nic_event.h"
+
+#define SPNIC_MSG_TO_MGMT_MAX_LEN		2016
+
+#define MAX_PF_MGMT_BUF_SIZE			2048UL
+#define SEGMENT_LEN				48
+#define ASYNC_MSG_FLAG				0x20
+#define MGMT_MSG_MAX_SEQ_ID	(RTE_ALIGN(SPNIC_MSG_TO_MGMT_MAX_LEN, \
+					   SEGMENT_LEN) / SEGMENT_LEN)
+
+#define BUF_OUT_DEFAULT_SIZE			1
+
+#define MGMT_MSG_SIZE_MIN			20
+#define MGMT_MSG_SIZE_STEP			16
+#define	MGMT_MSG_RSVD_FOR_DEV			8
+
+#define SYNC_MSG_ID_MASK			0x1F
+#define ASYNC_MSG_ID_MASK			0x1F
+
+#define SYNC_FLAG				0
+#define ASYNC_FLAG				1
+
+#define MSG_NO_RESP				0xFFFF
+
+#define MGMT_MSG_TIMEOUT			300000 /* Millisecond */
+
+int spnic_msg_to_mgmt_sync(void *hwdev, enum spnic_mod_type mod, u16 cmd,
+			   void *buf_in, u16 in_size, void *buf_out,
+			   u16 *out_size, u32 timeout)
+{
+	int err;
+
+	if (!hwdev)
+		return -EINVAL;
+
+	err = spnic_send_mbox_to_mgmt(hwdev, mod, cmd, buf_in, in_size,
+				      buf_out, out_size, timeout);
+	return err;
+}
+
+static void send_mgmt_ack(struct spnic_msg_pf_to_mgmt *pf_to_mgmt,
+			  enum spnic_mod_type mod, u16 cmd, void *buf_in,
+			  u16 in_size, u16 msg_id)
+{
+	u16 buf_size;
+
+	if (!in_size)
+		buf_size = BUF_OUT_DEFAULT_SIZE;
+	else
+		buf_size = in_size;
+
+	spnic_response_mbox_to_mgmt(pf_to_mgmt->hwdev, mod, cmd, buf_in,
+				    buf_size, msg_id);
+}
+
+static bool check_mgmt_seq_id_and_seg_len(struct spnic_recv_msg *recv_msg,
+					  u8 seq_id, u8 seg_len, u16 msg_id)
+{
+	if (seq_id > MGMT_MSG_MAX_SEQ_ID || seg_len > SEGMENT_LEN)
+		return false;
+
+	if (seq_id == 0) {
+		recv_msg->seq_id = seq_id;
+		recv_msg->msg_id = msg_id;
+	} else {
+		if ((seq_id != recv_msg->seq_id + 1) ||
+		    msg_id != recv_msg->msg_id) {
+			recv_msg->seq_id = 0;
+			return false;
+		}
+
+		recv_msg->seq_id = seq_id;
+	}
+
+	return true;
+}
+
+static void spnic_mgmt_recv_msg_handler(struct spnic_msg_pf_to_mgmt *pf_to_mgmt,
+					struct spnic_recv_msg *recv_msg,
+					__rte_unused void *param)
+{
+	void *buf_out = pf_to_mgmt->mgmt_ack_buf;
+	bool ack_first = false;
+	u16 out_size = 0;
+
+	memset(buf_out, 0, MAX_PF_MGMT_BUF_SIZE);
+
+	switch (recv_msg->mod) {
+	case SPNIC_MOD_COMM:
+		pf_handle_mgmt_comm_event(pf_to_mgmt->hwdev, pf_to_mgmt,
+					  recv_msg->cmd, recv_msg->msg,
+					  recv_msg->msg_len,
+					  buf_out, &out_size);
+		break;
+	case SPNIC_MOD_L2NIC:
+		spnic_pf_event_handler(pf_to_mgmt->hwdev, pf_to_mgmt,
+				       recv_msg->cmd, recv_msg->msg,
+				       recv_msg->msg_len, buf_out, &out_size);
+		break;
+	default:
+		PMD_DRV_LOG(ERR, "Not support mod, maybe need to response, mod: %d",
+			    recv_msg->mod);
+		break;
+	}
+
+	if (!ack_first && !recv_msg->async_mgmt_to_pf)
+		/* Mgmt sends async msg, sends the response */
+		send_mgmt_ack(pf_to_mgmt, recv_msg->mod, recv_msg->cmd, buf_out,
+			      out_size, recv_msg->msg_id);
+}
+
+/**
+ * Handler a message from mgmt cpu
+ *
+ * @param[in] pf_to_mgmt
+ *   PF to mgmt channel
+ * @param[in] recv_msg
+ *   Received message details
+ * @param[in] param
+ *   Customized parameter (unused_)
+ *
+ * @retval 0 : When aeqe is response message
+ * @retval -1 : Default result, when wrong message or not last message.
+ */
+static int recv_mgmt_msg_handler(struct spnic_msg_pf_to_mgmt *pf_to_mgmt,
+				 u8 *header, struct spnic_recv_msg *recv_msg,
+				 void *param)
+{
+	u64 mbox_header = *((u64 *)header);
+	void *msg_body = header + sizeof(mbox_header);
+	u8 seq_id, seq_len;
+	u32 offset;
+	u8 front_id;
+	u16 msg_id;
+
+	/* Don't need to get anything from hw when cmd is async */
+	if (SPNIC_MSG_HEADER_GET(mbox_header, DIRECTION) == SPNIC_MSG_RESPONSE)
+		return 0;
+
+	seq_len = SPNIC_MSG_HEADER_GET(mbox_header, SEG_LEN);
+	seq_id  = SPNIC_MSG_HEADER_GET(mbox_header, SEQID);
+	msg_id = SPNIC_MSG_HEADER_GET(mbox_header, MSG_ID);
+	front_id = recv_msg->seq_id;
+
+	if (!check_mgmt_seq_id_and_seg_len(recv_msg, seq_id, seq_len, msg_id)) {
+		PMD_DRV_LOG(ERR, "Mgmt msg sequence id and segment length check failed, "
+			    "front seq_id: 0x%x, current seq_id: 0x%x, seg len: 0x%x "
+			    "front msg_id: %d, cur msg_id: %d",
+			    front_id, seq_id, seq_len,
+			    recv_msg->msg_id, msg_id);
+		/* Set seq_id to invalid seq_id */
+		recv_msg->seq_id = MGMT_MSG_MAX_SEQ_ID;
+		return SPNIC_MSG_HANDLER_RES;
+	}
+
+	offset  = seq_id * SEGMENT_LEN;
+	memcpy((u8 *)recv_msg->msg + offset, msg_body, seq_len);
+
+	if (!SPNIC_MSG_HEADER_GET(mbox_header, LAST))
+		return SPNIC_MSG_HANDLER_RES;
+
+	recv_msg->cmd = SPNIC_MSG_HEADER_GET(mbox_header, CMD);
+	recv_msg->mod = SPNIC_MSG_HEADER_GET(mbox_header, MODULE);
+	recv_msg->async_mgmt_to_pf = SPNIC_MSG_HEADER_GET(mbox_header, NO_ACK);
+	recv_msg->msg_len = SPNIC_MSG_HEADER_GET(mbox_header, MSG_LEN);
+	recv_msg->msg_id = SPNIC_MSG_HEADER_GET(mbox_header, MSG_ID);
+	recv_msg->seq_id = MGMT_MSG_MAX_SEQ_ID;
+
+	spnic_mgmt_recv_msg_handler(pf_to_mgmt, recv_msg, param);
+
+	return SPNIC_MSG_HANDLER_RES;
+}
+
+/**
+ * Handler for a mgmt message event
+ *
+ * @param[in] hwdev
+ *   The pointer to the private hardware device object
+ * @param[in] header
+ *   The header of the message
+ * @param[in] size
+ *   Size (unused_)
+ * @param[in] param
+ *   Customized parameter
+ *
+ * @retval zero : When aeqe is response message
+ * @retval negative : When wrong message or not last message.
+ */
+int spnic_mgmt_msg_aeqe_handler(void *hwdev, u8 *header, u8 size, void *param)
+{
+	struct spnic_hwdev *dev = (struct spnic_hwdev *)hwdev;
+	struct spnic_msg_pf_to_mgmt *pf_to_mgmt = NULL;
+	struct spnic_recv_msg *recv_msg = NULL;
+	bool is_send_dir = false;
+
+	if ((SPNIC_MSG_HEADER_GET(*(u64 *)header, SOURCE) ==
+	     SPNIC_MSG_FROM_MBOX)) {
+		return spnic_mbox_func_aeqe_handler(hwdev, header, size, param);
+	}
+
+	pf_to_mgmt = dev->pf_to_mgmt;
+
+	is_send_dir = (SPNIC_MSG_HEADER_GET(*(u64 *)header, DIRECTION) ==
+		       SPNIC_MSG_DIRECT_SEND) ? true : false;
+
+	recv_msg = is_send_dir ? &pf_to_mgmt->recv_msg_from_mgmt :
+		   &pf_to_mgmt->recv_resp_msg_from_mgmt;
+
+	return recv_mgmt_msg_handler(pf_to_mgmt, header, recv_msg, param);
+}
+
+/**
+ * Allocate received message memory
+ *
+ * @param[in] recv_msg
+ *   Pointer that will hold the allocated data
+ *
+ * @retval zero : Success
+ * @retval negative : Failure.
+ */
+static int alloc_recv_msg(struct spnic_recv_msg *recv_msg)
+{
+	recv_msg->seq_id = MGMT_MSG_MAX_SEQ_ID;
+
+	recv_msg->msg = rte_zmalloc("recv_msg", MAX_PF_MGMT_BUF_SIZE,
+				    SPNIC_MEM_ALLOC_ALIGN_MIN);
+	if (!recv_msg->msg)
+		return -ENOMEM;
+
+	return 0;
+}
+
+/**
+ * Free received message memory
+ *
+ * @param[in] recv_msg
+ *   Pointer that will hold the allocated data
+ */
+static void free_recv_msg(struct spnic_recv_msg *recv_msg)
+{
+	rte_free(recv_msg->msg);
+}
+
+/**
+ * Allocate all the message buffers of PF to mgmt channel
+ *
+ * @param[in] pf_to_mgmt
+ *   PF to mgmt channel
+ *
+ * @retval zero : Success
+ * @retval negative : Failure.
+ */
+static int alloc_msg_buf(struct spnic_msg_pf_to_mgmt *pf_to_mgmt)
+{
+	int err;
+
+	err = alloc_recv_msg(&pf_to_mgmt->recv_msg_from_mgmt);
+	if (err) {
+		PMD_DRV_LOG(ERR, "Allocate recv msg failed");
+		return err;
+	}
+
+	err = alloc_recv_msg(&pf_to_mgmt->recv_resp_msg_from_mgmt);
+	if (err) {
+		PMD_DRV_LOG(ERR, "Allocate resp recv msg failed");
+		goto alloc_msg_for_resp_err;
+	}
+
+	pf_to_mgmt->mgmt_ack_buf = rte_zmalloc("mgmt_ack_buf",
+					       MAX_PF_MGMT_BUF_SIZE,
+					       SPNIC_MEM_ALLOC_ALIGN_MIN);
+	if (!pf_to_mgmt->mgmt_ack_buf) {
+		err = -ENOMEM;
+		goto ack_msg_buf_err;
+	}
+
+	return 0;
+
+ack_msg_buf_err:
+	free_recv_msg(&pf_to_mgmt->recv_resp_msg_from_mgmt);
+
+alloc_msg_for_resp_err:
+	free_recv_msg(&pf_to_mgmt->recv_msg_from_mgmt);
+	return err;
+}
+
+/**
+ * Free all the message buffers of PF to mgmt channel
+ *
+ * @param[in] pf_to_mgmt
+ *   PF to mgmt channel
+ */
+static void free_msg_buf(struct spnic_msg_pf_to_mgmt *pf_to_mgmt)
+{
+	rte_free(pf_to_mgmt->mgmt_ack_buf);
+	free_recv_msg(&pf_to_mgmt->recv_resp_msg_from_mgmt);
+	free_recv_msg(&pf_to_mgmt->recv_msg_from_mgmt);
+}
+
+/**
+ * Initialize PF to mgmt channel
+ *
+ * @param[in] hwdev
+ *   The pointer to the private hardware device object
+ *
+ * @retval zero : Success
+ * @retval negative : Failure.
+ */
+int spnic_pf_to_mgmt_init(struct spnic_hwdev *hwdev)
+{
+	struct spnic_msg_pf_to_mgmt *pf_to_mgmt;
+	int err;
+
+	pf_to_mgmt = rte_zmalloc("pf_to_mgmt", sizeof(*pf_to_mgmt),
+				 SPNIC_MEM_ALLOC_ALIGN_MIN);
+	if (!pf_to_mgmt)
+		return -ENOMEM;
+
+	hwdev->pf_to_mgmt = pf_to_mgmt;
+	pf_to_mgmt->hwdev = hwdev;
+
+	err = spnic_mutex_init(&pf_to_mgmt->sync_msg_mutex, NULL);
+	if (err)
+		goto mutex_init_err;
+
+	err = alloc_msg_buf(pf_to_mgmt);
+	if (err) {
+		PMD_DRV_LOG(ERR, "Allocate msg buffers failed");
+		goto alloc_msg_buf_err;
+	}
+
+	return 0;
+
+alloc_msg_buf_err:
+	spnic_mutex_destroy(&pf_to_mgmt->sync_msg_mutex);
+
+mutex_init_err:
+	rte_free(pf_to_mgmt);
+
+	return err;
+}
+
+/**
+ * Free PF to mgmt channel
+ *
+ * @param[in] hwdev
+ *   The pointer to the private hardware device object
+ */
+void spnic_pf_to_mgmt_free(struct spnic_hwdev *hwdev)
+{
+	struct spnic_msg_pf_to_mgmt *pf_to_mgmt = hwdev->pf_to_mgmt;
+
+	free_msg_buf(pf_to_mgmt);
+	spnic_mutex_destroy(&pf_to_mgmt->sync_msg_mutex);
+	rte_free(pf_to_mgmt);
+}
diff --git a/drivers/net/spnic/base/spnic_mgmt.h b/drivers/net/spnic/base/spnic_mgmt.h
index 37d0410473..ca820828d2 100644
--- a/drivers/net/spnic/base/spnic_mgmt.h
+++ b/drivers/net/spnic/base/spnic_mgmt.h
@@ -7,6 +7,13 @@
 
 #define SPNIC_MSG_HANDLER_RES	(-1)
 
+/* Structures for l2nic and mag msg to mgmt sync interface */
+struct mgmt_msg_head {
+	u8 status;
+	u8 version;
+	u8 rsvd0[6];
+};
+
 /* Cmdq module type */
 enum spnic_mod_type {
 	SPNIC_MOD_COMM = 0, /* HW communication module */
@@ -33,4 +40,71 @@ enum spnic_mod_type {
 	SPNIC_MOD_MAX
 };
 
+typedef enum {
+	RES_TYPE_FLUSH_BIT = 0,
+	RES_TYPE_MQM,
+	RES_TYPE_SMF,
+
+	RES_TYPE_COMM = 10,
+	/* clear mbox and aeq, The RES_TYPE_COMM bit must be set */
+	RES_TYPE_COMM_MGMT_CH,
+	/* clear cmdq, The RES_TYPE_COMM bit must be set */
+	RES_TYPE_COMM_CMD_CH,
+	RES_TYPE_NIC,
+	RES_TYPE_OVS,
+	RES_TYPE_MAX = 20,
+} func_reset_flag_e;
+
+#define SPNIC_COMM_RES		((1 << RES_TYPE_COMM) | \
+				(1 << RES_TYPE_FLUSH_BIT) | \
+				(1 << RES_TYPE_MQM) | \
+				(1 << RES_TYPE_SMF) | \
+				(1 << RES_TYPE_COMM_CMD_CH))
+#define SPNIC_NIC_RES		(1 << RES_TYPE_NIC)
+#define SPNIC_OVS_RES		(1 << RES_TYPE_OVS)
+
+struct spnic_recv_msg {
+	void *msg;
+
+	u16 msg_len;
+	enum spnic_mod_type mod;
+	u16 cmd;
+	u8 seq_id;
+	u16 msg_id;
+	int async_mgmt_to_pf;
+};
+
+enum comm_pf_to_mgmt_event_state {
+	SEND_EVENT_UNINIT = 0,
+	SEND_EVENT_START,
+	SEND_EVENT_SUCCESS,
+	SEND_EVENT_FAIL,
+	SEND_EVENT_TIMEOUT,
+	SEND_EVENT_END
+};
+
+struct spnic_msg_pf_to_mgmt {
+	struct spnic_hwdev *hwdev;
+
+	/* Mutex for sync message */
+	pthread_mutex_t sync_msg_mutex;
+
+	void *mgmt_ack_buf;
+
+	struct spnic_recv_msg recv_msg_from_mgmt;
+	struct spnic_recv_msg recv_resp_msg_from_mgmt;
+
+	u16 sync_msg_id;
+};
+
+int spnic_mgmt_msg_aeqe_handler(void *hwdev, u8 *header, u8 size, void *param);
+
+int spnic_pf_to_mgmt_init(struct spnic_hwdev *hwdev);
+
+void spnic_pf_to_mgmt_free(struct spnic_hwdev *hwdev);
+
+int spnic_msg_to_mgmt_sync(void *hwdev, enum spnic_mod_type mod, u16 cmd,
+			   void *buf_in, u16 in_size, void *buf_out,
+			   u16 *out_size, u32 timeout);
+
 #endif /* _SPNIC_MGMT_H_ */
diff --git a/drivers/net/spnic/base/spnic_nic_event.c b/drivers/net/spnic/base/spnic_nic_event.c
new file mode 100644
index 0000000000..07ea036d84
--- /dev/null
+++ b/drivers/net/spnic/base/spnic_nic_event.c
@@ -0,0 +1,171 @@
+/* SPDX-License-Identifier: BSD-3-Clause
+ * Copyright(c) 2021 Ramaxel Memory Technology, Ltd
+ */
+
+#include <ethdev_driver.h>
+
+#include "spnic_compat.h"
+#include "spnic_cmd.h"
+#include "spnic_hwif.h"
+#include "spnic_hwdev.h"
+#include "spnic_mgmt.h"
+#include "spnic_hwdev.h"
+#include "spnic_nic_event.h"
+
+static void get_port_info(u8 link_state, struct rte_eth_link *link)
+{
+	if (!link_state) {
+		link->link_status = ETH_LINK_DOWN;
+		link->link_speed = ETH_SPEED_NUM_NONE;
+		link->link_duplex = ETH_LINK_HALF_DUPLEX;
+		link->link_autoneg = ETH_LINK_FIXED;
+	}
+}
+
+static void spnic_link_event_stats(void *dev, u8 link)
+{
+	struct spnic_hwdev *hwdev = dev;
+	struct link_event_stats *stats = &hwdev->hw_stats.link_event_stats;
+
+	if (link)
+		__atomic_fetch_add(&stats->link_up_stats, 1, __ATOMIC_RELAXED);
+	else
+		__atomic_fetch_add(&stats->link_down_stats, 1, __ATOMIC_RELAXED);
+}
+
+static void link_status_event_handler(void *hwdev, void *buf_in,
+				      __rte_unused u16 in_size,
+				      __rte_unused void *buf_out,
+				      __rte_unused u16 *out_size)
+{
+	struct spnic_cmd_link_state *link_status = NULL;
+	struct rte_eth_link link;
+	struct spnic_hwdev *dev = hwdev;
+	int err;
+
+	link_status = buf_in;
+	PMD_DRV_LOG(INFO, "Link status report received, func_id: %d, status: %d(%s)",
+		    spnic_global_func_id(hwdev), link_status->state,
+		    link_status->state ? "UP" : "DOWN");
+
+	spnic_link_event_stats(hwdev, link_status->state);
+
+	/* Link event reported only after set vport enable */
+	get_port_info(link_status->state, &link);
+	err = rte_eth_linkstatus_set((struct rte_eth_dev *)(dev->eth_dev),
+				     &link);
+	if (!err)
+		rte_eth_dev_callback_process(dev->eth_dev,
+					      RTE_ETH_EVENT_INTR_LSC, NULL);
+}
+
+struct nic_event_handler {
+	u16 cmd;
+	void (*handler)(void *hwdev, void *buf_in, u16 in_size,
+			void *buf_out, u16 *out_size);
+};
+
+struct nic_event_handler nic_cmd_handler[] = {
+};
+
+static void nic_event_handler(void *hwdev, u16 cmd, void *buf_in, u16 in_size,
+			      void *buf_out, u16 *out_size)
+{
+	u32 i, size = ARRAY_LEN(nic_cmd_handler);
+
+	if (!hwdev)
+		return;
+
+	*out_size = 0;
+
+	for (i = 0; i < size; i++) {
+		if (cmd == nic_cmd_handler[i].cmd) {
+			nic_cmd_handler[i].handler(hwdev, buf_in, in_size,
+						   buf_out, out_size);
+			break;
+		}
+	}
+
+	if (i == size)
+		PMD_DRV_LOG(WARNING,
+			    "Unsupported nic event cmd(%d) to process", cmd);
+}
+
+/*
+ * VF handler mbox msg from ppf/pf
+ * VF link change event
+ * VF fault report event
+ */
+int spnic_vf_event_handler(void *hwdev, __rte_unused void *pri_handle,
+			   u16 cmd, void *buf_in, u16 in_size,
+			   void *buf_out, u16 *out_size)
+{
+	nic_event_handler(hwdev, cmd, buf_in, in_size, buf_out, out_size);
+	return 0;
+}
+
+/*  NIC event of PF/PPF handler reported by mgmt cpu */
+void spnic_pf_event_handler(void *hwdev, __rte_unused void *pri_handle,
+			    u16 cmd, void *buf_in, u16 in_size,
+			    void *buf_out, u16 *out_size)
+{
+	nic_event_handler(hwdev, cmd, buf_in, in_size, buf_out, out_size);
+}
+
+static struct nic_event_handler mag_cmd_handler[] = {
+	{
+		.cmd = MAG_CMD_GET_LINK_STATUS,
+		.handler = link_status_event_handler,
+	},
+};
+
+static int spnic_mag_event_handler(void *hwdev, u16 cmd, void *buf_in,
+				   u16 in_size, void *buf_out,
+				   u16 *out_size)
+{
+	u32 size = ARRAY_LEN(mag_cmd_handler);
+	u32 i;
+
+	if (!hwdev)
+		return -EINVAL;
+
+	*out_size = 0;
+	for (i = 0; i < size; i++) {
+		if (cmd == mag_cmd_handler[i].cmd) {
+			mag_cmd_handler[i].handler(hwdev, buf_in, in_size,
+						   buf_out, out_size);
+			break;
+		}
+	}
+
+	/* can't find this event cmd */
+	if (i == size)
+		PMD_DRV_LOG(ERR, "Unsupported mag event, cmd: %u\n", cmd);
+
+	return 0;
+}
+
+int spnic_vf_mag_event_handler(void *hwdev, void *pri_handle, u16 cmd,
+			       void *buf_in, u16 in_size, void *buf_out,
+			       u16 *out_size)
+{
+	return spnic_mag_event_handler(hwdev, cmd, buf_in, in_size, buf_out,
+				       out_size);
+}
+
+/* pf/ppf handler mgmt cpu report hilink event*/
+void spnic_pf_mag_event_handler(void *hwdev, void *pri_handle, u16 cmd,
+				void *buf_in, u16 in_size, void *buf_out,
+				u16 *out_size)
+{
+	spnic_mag_event_handler(hwdev, cmd, buf_in, in_size, buf_out, out_size);
+}
+
+u8 spnic_nic_sw_aeqe_handler(__rte_unused void *hwdev, u8 event, u8 *data)
+{
+	PMD_DRV_LOG(ERR,
+		    "Received nic ucode aeq event type: 0x%x, data: %"PRIu64"",
+		    event, *((u64 *)data));
+
+	return 0;
+}
diff --git a/drivers/net/spnic/base/spnic_nic_event.h b/drivers/net/spnic/base/spnic_nic_event.h
new file mode 100644
index 0000000000..eb41d76a7d
--- /dev/null
+++ b/drivers/net/spnic/base/spnic_nic_event.h
@@ -0,0 +1,34 @@
+/* SPDX-License-Identifier: BSD-3-Clause
+ * Copyright(c) 2021 Ramaxel Memory Technology, Ltd
+ */
+
+#ifndef _SPNIC_NIC_EVENT_H_
+#define _SPNIC_NIC_EVENT_H_
+
+struct spnic_cmd_link_state {
+	struct mgmt_msg_head msg_head;
+
+	u8 port_id;
+	u8 state;
+	u16 rsvd1;
+};
+
+void spnic_pf_event_handler(void *hwdev, __rte_unused void *pri_handle,
+			    u16 cmd, void *buf_in, u16 in_size,
+			    void *buf_out, u16 *out_size);
+
+int spnic_vf_event_handler(void *hwdev, __rte_unused void *pri_handle,
+			   u16 cmd, void *buf_in, u16 in_size,
+			   void *buf_out, u16 *out_size);
+
+void spnic_pf_mag_event_handler(void *hwdev, void *pri_handle, u16 cmd,
+				void *buf_in, u16 in_size, void *buf_out,
+				u16 *out_size);
+
+int spnic_vf_mag_event_handler(void *hwdev, void *pri_handle, u16 cmd,
+			       void *buf_in, u16 in_size, void *buf_out,
+			       u16 *out_size);
+
+u8 spnic_nic_sw_aeqe_handler(__rte_unused void *hwdev, u8 event, u8 *data);
+
+#endif /* _SPNIC_NIC_EVENT_H_ */
-- 
2.27.0
Keyboard shortcuts
hback out one level
jnext message in thread
kprevious message in thread
ldrill in
Escclose help / fold thread tree
?toggle this help