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 <son...@ramaxel.com>
---
 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

Reply via email to