]> www.infradead.org Git - users/griffoul/linux.git/commitdiff
hinic3: Mailbox framework
authorFan Gong <gongfan1@huawei.com>
Wed, 20 Aug 2025 09:31:23 +0000 (17:31 +0800)
committerJakub Kicinski <kuba@kernel.org>
Sat, 23 Aug 2025 00:05:07 +0000 (17:05 -0700)
Add mailbox framework initialization.
It allows driver to send commands to HW.

Co-developed-by: Xin Guo <guoxin09@huawei.com>
Signed-off-by: Xin Guo <guoxin09@huawei.com>
Co-developed-by: Zhu Yikai <zhuyikai1@h-partners.com>
Signed-off-by: Zhu Yikai <zhuyikai1@h-partners.com>
Signed-off-by: Fan Gong <gongfan1@huawei.com>
Link: https://patch.msgid.link/084f22f0155aaa713fa583205d540cb2bf3c3c2d.1755673097.git.zhuyikai1@h-partners.com
Signed-off-by: Jakub Kicinski <kuba@kernel.org>
drivers/net/ethernet/huawei/hinic3/hinic3_common.c
drivers/net/ethernet/huawei/hinic3/hinic3_common.h
drivers/net/ethernet/huawei/hinic3/hinic3_mbox.c
drivers/net/ethernet/huawei/hinic3/hinic3_mbox.h

index b8d29e26e2da63e080c093ffd553d9d385a9af29..fe4778d152cff2b115f126e41b7b5e168a4c93e3 100644 (file)
@@ -3,6 +3,7 @@
 
 #include <linux/delay.h>
 #include <linux/dma-mapping.h>
+#include <linux/iopoll.h>
 
 #include "hinic3_common.h"
 
@@ -52,6 +53,19 @@ void hinic3_dma_free_coherent_align(struct device *dev,
                          mem_align->ori_vaddr, mem_align->ori_paddr);
 }
 
+int hinic3_wait_for_timeout(void *priv_data, wait_cpl_handler handler,
+                           u32 wait_total_ms, u32 wait_once_us)
+{
+       enum hinic3_wait_return ret;
+       int err;
+
+       err = read_poll_timeout(handler, ret, ret == HINIC3_WAIT_PROCESS_CPL,
+                               wait_once_us, wait_total_ms * USEC_PER_MSEC,
+                               false, priv_data);
+
+       return err;
+}
+
 /* Data provided to/by cmdq is arranged in structs with little endian fields but
  * every dword (32bits) should be swapped since HW swaps it again when it
  * copies it from/to host memory.
index dfa5bd882379ad9ad3b363dcfca57611be2710b1..a8fabfae90fb5ddde452799e8eb55986a10b8a78 100644 (file)
@@ -18,6 +18,11 @@ struct hinic3_dma_addr_align {
        dma_addr_t align_paddr;
 };
 
+enum hinic3_wait_return {
+       HINIC3_WAIT_PROCESS_CPL     = 0,
+       HINIC3_WAIT_PROCESS_WAITING = 1,
+};
+
 struct hinic3_sge {
        __le32 hi_addr;
        __le32 lo_addr;
@@ -40,6 +45,10 @@ int hinic3_dma_zalloc_coherent_align(struct device *dev, u32 size, u32 align,
 void hinic3_dma_free_coherent_align(struct device *dev,
                                    struct hinic3_dma_addr_align *mem_align);
 
+typedef enum hinic3_wait_return (*wait_cpl_handler)(void *priv_data);
+int hinic3_wait_for_timeout(void *priv_data, wait_cpl_handler handler,
+                           u32 wait_total_ms, u32 wait_once_us);
+
 void hinic3_cmdq_buf_swab32(void *data, int len);
 
 #endif
index e74d1eb0973010b8f5f88293665f8405dcf3037c..eaa8b8cda7faa5d7fb8b372d1f0ae493c5b8d7bd 100644 (file)
 #include <linux/dma-mapping.h>
 
 #include "hinic3_common.h"
+#include "hinic3_csr.h"
 #include "hinic3_hwdev.h"
 #include "hinic3_hwif.h"
 #include "hinic3_mbox.h"
 
+#define MBOX_MSG_POLLING_TIMEOUT_MS  8000 // send msg seg timeout
+#define MBOX_COMP_POLLING_TIMEOUT_MS 40000 // response
+
+#define MBOX_MAX_BUF_SZ           2048
+#define MBOX_HEADER_SZ            8
+
+/* MBOX size is 64B, 8B for mbox_header, 8B reserved */
+#define MBOX_SEG_LEN              48
+#define MBOX_SEG_LEN_ALIGN        4
+#define MBOX_WB_STATUS_LEN        16
+
+#define MBOX_SEQ_ID_START_VAL     0
+#define MBOX_SEQ_ID_MAX_VAL       42
+#define MBOX_LAST_SEG_MAX_LEN  \
+       (MBOX_MAX_BUF_SZ - MBOX_SEQ_ID_MAX_VAL * MBOX_SEG_LEN)
+
+#define MBOX_DMA_MSG_QUEUE_DEPTH    32
+#define MBOX_AREA(hwif)  \
+       ((hwif)->cfg_regs_base + HINIC3_FUNC_CSR_MAILBOX_DATA_OFF)
+
+#define MBOX_MQ_CI_OFFSET  \
+       (HINIC3_CFG_REGS_FLAG + HINIC3_FUNC_CSR_MAILBOX_DATA_OFF + \
+        MBOX_HEADER_SZ + MBOX_SEG_LEN)
+
+#define MBOX_MQ_SYNC_CI_MASK   GENMASK(7, 0)
+#define MBOX_MQ_ASYNC_CI_MASK  GENMASK(15, 8)
+#define MBOX_MQ_CI_GET(val, field)  \
+       FIELD_GET(MBOX_MQ_##field##_CI_MASK, val)
+
+#define MBOX_MGMT_FUNC_ID         0x1FFF
+#define MBOX_COMM_F_MBOX_SEGMENT  BIT(3)
+
+static u8 *get_mobx_body_from_hdr(u8 *header)
+{
+       return header + MBOX_HEADER_SZ;
+}
+
+static struct hinic3_msg_desc *get_mbox_msg_desc(struct hinic3_mbox *mbox,
+                                                enum mbox_msg_direction_type dir,
+                                                u16 src_func_id)
+{
+       struct hinic3_msg_channel *msg_ch;
+
+       msg_ch = (src_func_id == MBOX_MGMT_FUNC_ID) ?
+               &mbox->mgmt_msg : mbox->func_msg;
+
+       return (dir == MBOX_MSG_SEND) ?
+               &msg_ch->recv_msg : &msg_ch->resp_msg;
+}
+
+static void resp_mbox_handler(struct hinic3_mbox *mbox,
+                             const struct hinic3_msg_desc *msg_desc)
+{
+       spin_lock(&mbox->mbox_lock);
+       if (msg_desc->msg_info.msg_id == mbox->send_msg_id &&
+           mbox->event_flag == MBOX_EVENT_START)
+               mbox->event_flag = MBOX_EVENT_SUCCESS;
+       spin_unlock(&mbox->mbox_lock);
+}
+
+static bool mbox_segment_valid(struct hinic3_mbox *mbox,
+                              struct hinic3_msg_desc *msg_desc,
+                              __le64 mbox_header)
+{
+       u8 seq_id, seg_len, msg_id, mod;
+       __le16 src_func_idx, cmd;
+
+       seq_id = MBOX_MSG_HEADER_GET(mbox_header, SEQID);
+       seg_len = MBOX_MSG_HEADER_GET(mbox_header, SEG_LEN);
+       msg_id = MBOX_MSG_HEADER_GET(mbox_header, MSG_ID);
+       mod = MBOX_MSG_HEADER_GET(mbox_header, MODULE);
+       cmd = cpu_to_le16(MBOX_MSG_HEADER_GET(mbox_header, CMD));
+       src_func_idx = cpu_to_le16(MBOX_MSG_HEADER_GET(mbox_header,
+                                                      SRC_GLB_FUNC_IDX));
+
+       if (seq_id > MBOX_SEQ_ID_MAX_VAL || seg_len > MBOX_SEG_LEN ||
+           (seq_id == MBOX_SEQ_ID_MAX_VAL && seg_len > MBOX_LAST_SEG_MAX_LEN))
+               goto err_seg;
+
+       if (seq_id == 0) {
+               msg_desc->seq_id = seq_id;
+               msg_desc->msg_info.msg_id = msg_id;
+               msg_desc->mod = mod;
+               msg_desc->cmd = cmd;
+       } else {
+               if (seq_id != msg_desc->seq_id + 1 ||
+                   msg_id != msg_desc->msg_info.msg_id ||
+                   mod != msg_desc->mod || cmd != msg_desc->cmd)
+                       goto err_seg;
+
+               msg_desc->seq_id = seq_id;
+       }
+
+       return true;
+
+err_seg:
+       dev_err(mbox->hwdev->dev,
+               "Mailbox segment check failed, src func id: 0x%x, front seg info: seq id: 0x%x, msg id: 0x%x, mod: 0x%x, cmd: 0x%x\n",
+               src_func_idx, msg_desc->seq_id, msg_desc->msg_info.msg_id,
+               msg_desc->mod, msg_desc->cmd);
+       dev_err(mbox->hwdev->dev,
+               "Current seg info: seg len: 0x%x, seq id: 0x%x, msg id: 0x%x, mod: 0x%x, cmd: 0x%x\n",
+               seg_len, seq_id, msg_id, mod, cmd);
+
+       return false;
+}
+
+static void recv_mbox_handler(struct hinic3_mbox *mbox,
+                             u8 *header, struct hinic3_msg_desc *msg_desc)
+{
+       __le64 mbox_header = *((__force __le64 *)header);
+       u8 *mbox_body = get_mobx_body_from_hdr(header);
+       u8 seq_id, seg_len;
+       int pos;
+
+       if (!mbox_segment_valid(mbox, msg_desc, mbox_header)) {
+               msg_desc->seq_id = MBOX_SEQ_ID_MAX_VAL;
+               return;
+       }
+
+       seq_id = MBOX_MSG_HEADER_GET(mbox_header, SEQID);
+       seg_len = MBOX_MSG_HEADER_GET(mbox_header, SEG_LEN);
+
+       pos = seq_id * MBOX_SEG_LEN;
+       memcpy(msg_desc->msg + pos, mbox_body, seg_len);
+
+       if (!MBOX_MSG_HEADER_GET(mbox_header, LAST))
+               return;
+
+       msg_desc->msg_len = cpu_to_le16(MBOX_MSG_HEADER_GET(mbox_header,
+                                                           MSG_LEN));
+       msg_desc->msg_info.status = MBOX_MSG_HEADER_GET(mbox_header, STATUS);
+
+       if (MBOX_MSG_HEADER_GET(mbox_header, DIRECTION) == MBOX_MSG_RESP)
+               resp_mbox_handler(mbox, msg_desc);
+}
+
+void hinic3_mbox_func_aeqe_handler(struct hinic3_hwdev *hwdev, u8 *header,
+                                  u8 size)
+{
+       __le64 mbox_header = *((__force __le64 *)header);
+       enum mbox_msg_direction_type dir;
+       struct hinic3_msg_desc *msg_desc;
+       struct hinic3_mbox *mbox;
+       u16 src_func_id;
+
+       mbox = hwdev->mbox;
+       dir = MBOX_MSG_HEADER_GET(mbox_header, DIRECTION);
+       src_func_id = MBOX_MSG_HEADER_GET(mbox_header, SRC_GLB_FUNC_IDX);
+       msg_desc = get_mbox_msg_desc(mbox, dir, src_func_id);
+       recv_mbox_handler(mbox, header, msg_desc);
+}
+
+static int init_mbox_dma_queue(struct hinic3_hwdev *hwdev,
+                              struct mbox_dma_queue *mq)
+{
+       u32 size;
+
+       mq->depth = MBOX_DMA_MSG_QUEUE_DEPTH;
+       mq->prod_idx = 0;
+       mq->cons_idx = 0;
+
+       size = mq->depth * MBOX_MAX_BUF_SZ;
+       mq->dma_buf_vaddr = dma_alloc_coherent(hwdev->dev, size,
+                                              &mq->dma_buf_paddr,
+                                              GFP_KERNEL);
+       if (!mq->dma_buf_vaddr)
+               return -ENOMEM;
+
+       return 0;
+}
+
+static void uninit_mbox_dma_queue(struct hinic3_hwdev *hwdev,
+                                 struct mbox_dma_queue *mq)
+{
+       dma_free_coherent(hwdev->dev, mq->depth * MBOX_MAX_BUF_SZ,
+                         mq->dma_buf_vaddr, mq->dma_buf_paddr);
+}
+
+static int hinic3_init_mbox_dma_queue(struct hinic3_mbox *mbox)
+{
+       u32 val;
+       int err;
+
+       err = init_mbox_dma_queue(mbox->hwdev, &mbox->sync_msg_queue);
+       if (err)
+               return err;
+
+       err = init_mbox_dma_queue(mbox->hwdev, &mbox->async_msg_queue);
+       if (err) {
+               uninit_mbox_dma_queue(mbox->hwdev, &mbox->sync_msg_queue);
+               return err;
+       }
+
+       val = hinic3_hwif_read_reg(mbox->hwdev->hwif, MBOX_MQ_CI_OFFSET);
+       val &= ~MBOX_MQ_SYNC_CI_MASK;
+       val &= ~MBOX_MQ_ASYNC_CI_MASK;
+       hinic3_hwif_write_reg(mbox->hwdev->hwif, MBOX_MQ_CI_OFFSET, val);
+
+       return 0;
+}
+
+static void hinic3_uninit_mbox_dma_queue(struct hinic3_mbox *mbox)
+{
+       uninit_mbox_dma_queue(mbox->hwdev, &mbox->sync_msg_queue);
+       uninit_mbox_dma_queue(mbox->hwdev, &mbox->async_msg_queue);
+}
+
+static int alloc_mbox_msg_channel(struct hinic3_msg_channel *msg_ch)
+{
+       msg_ch->resp_msg.msg = kzalloc(MBOX_MAX_BUF_SZ, GFP_KERNEL);
+       if (!msg_ch->resp_msg.msg)
+               return -ENOMEM;
+
+       msg_ch->recv_msg.msg = kzalloc(MBOX_MAX_BUF_SZ, GFP_KERNEL);
+       if (!msg_ch->recv_msg.msg) {
+               kfree(msg_ch->resp_msg.msg);
+               return -ENOMEM;
+       }
+
+       msg_ch->resp_msg.seq_id = MBOX_SEQ_ID_MAX_VAL;
+       msg_ch->recv_msg.seq_id = MBOX_SEQ_ID_MAX_VAL;
+
+       return 0;
+}
+
+static void free_mbox_msg_channel(struct hinic3_msg_channel *msg_ch)
+{
+       kfree(msg_ch->recv_msg.msg);
+       kfree(msg_ch->resp_msg.msg);
+}
+
+static int init_mgmt_msg_channel(struct hinic3_mbox *mbox)
+{
+       int err;
+
+       err = alloc_mbox_msg_channel(&mbox->mgmt_msg);
+       if (err) {
+               dev_err(mbox->hwdev->dev, "Failed to alloc mgmt message channel\n");
+               return err;
+       }
+
+       err = hinic3_init_mbox_dma_queue(mbox);
+       if (err) {
+               dev_err(mbox->hwdev->dev, "Failed to init mbox dma queue\n");
+               free_mbox_msg_channel(&mbox->mgmt_msg);
+               return err;
+       }
+
+       return 0;
+}
+
+static void uninit_mgmt_msg_channel(struct hinic3_mbox *mbox)
+{
+       hinic3_uninit_mbox_dma_queue(mbox);
+       free_mbox_msg_channel(&mbox->mgmt_msg);
+}
+
+static int hinic3_init_func_mbox_msg_channel(struct hinic3_hwdev *hwdev)
+{
+       struct hinic3_mbox *mbox;
+       int err;
+
+       mbox = hwdev->mbox;
+       mbox->func_msg = kzalloc(sizeof(*mbox->func_msg), GFP_KERNEL);
+       if (!mbox->func_msg)
+               return -ENOMEM;
+
+       err = alloc_mbox_msg_channel(mbox->func_msg);
+       if (err)
+               goto err_free_func_msg;
+
+       return 0;
+
+err_free_func_msg:
+       kfree(mbox->func_msg);
+       mbox->func_msg = NULL;
+
+       return err;
+}
+
+static void hinic3_uninit_func_mbox_msg_channel(struct hinic3_hwdev *hwdev)
+{
+       struct hinic3_mbox *mbox = hwdev->mbox;
+
+       free_mbox_msg_channel(mbox->func_msg);
+       kfree(mbox->func_msg);
+       mbox->func_msg = NULL;
+}
+
+static void prepare_send_mbox(struct hinic3_mbox *mbox)
+{
+       struct hinic3_send_mbox *send_mbox = &mbox->send_mbox;
+
+       send_mbox->data = MBOX_AREA(mbox->hwdev->hwif);
+}
+
+static int alloc_mbox_wb_status(struct hinic3_mbox *mbox)
+{
+       struct hinic3_send_mbox *send_mbox = &mbox->send_mbox;
+       struct hinic3_hwdev *hwdev = mbox->hwdev;
+       u32 addr_h, addr_l;
+
+       send_mbox->wb_vaddr = dma_alloc_coherent(hwdev->dev,
+                                                MBOX_WB_STATUS_LEN,
+                                                &send_mbox->wb_paddr,
+                                                GFP_KERNEL);
+       if (!send_mbox->wb_vaddr)
+               return -ENOMEM;
+
+       addr_h = upper_32_bits(send_mbox->wb_paddr);
+       addr_l = lower_32_bits(send_mbox->wb_paddr);
+       hinic3_hwif_write_reg(hwdev->hwif, HINIC3_FUNC_CSR_MAILBOX_RESULT_H_OFF,
+                             addr_h);
+       hinic3_hwif_write_reg(hwdev->hwif, HINIC3_FUNC_CSR_MAILBOX_RESULT_L_OFF,
+                             addr_l);
+
+       return 0;
+}
+
+static void free_mbox_wb_status(struct hinic3_mbox *mbox)
+{
+       struct hinic3_send_mbox *send_mbox = &mbox->send_mbox;
+       struct hinic3_hwdev *hwdev = mbox->hwdev;
+
+       hinic3_hwif_write_reg(hwdev->hwif, HINIC3_FUNC_CSR_MAILBOX_RESULT_H_OFF,
+                             0);
+       hinic3_hwif_write_reg(hwdev->hwif, HINIC3_FUNC_CSR_MAILBOX_RESULT_L_OFF,
+                             0);
+
+       dma_free_coherent(hwdev->dev, MBOX_WB_STATUS_LEN,
+                         send_mbox->wb_vaddr, send_mbox->wb_paddr);
+}
+
+static int hinic3_mbox_pre_init(struct hinic3_hwdev *hwdev,
+                               struct hinic3_mbox *mbox)
+{
+       mbox->hwdev = hwdev;
+       mutex_init(&mbox->mbox_send_lock);
+       spin_lock_init(&mbox->mbox_lock);
+
+       mbox->workq = create_singlethread_workqueue(HINIC3_MBOX_WQ_NAME);
+       if (!mbox->workq) {
+               dev_err(hwdev->dev, "Failed to initialize MBOX workqueue\n");
+               return -ENOMEM;
+       }
+       hwdev->mbox = mbox;
+
+       return 0;
+}
+
+int hinic3_init_mbox(struct hinic3_hwdev *hwdev)
+{
+       struct hinic3_mbox *mbox;
+       int err;
+
+       mbox = kzalloc(sizeof(*mbox), GFP_KERNEL);
+       if (!mbox)
+               return -ENOMEM;
+
+       err = hinic3_mbox_pre_init(hwdev, mbox);
+       if (err)
+               goto err_free_mbox;
+
+       err = init_mgmt_msg_channel(mbox);
+       if (err)
+               goto err_destroy_workqueue;
+
+       err = hinic3_init_func_mbox_msg_channel(hwdev);
+       if (err)
+               goto err_uninit_mgmt_msg_ch;
+
+       err = alloc_mbox_wb_status(mbox);
+       if (err) {
+               dev_err(hwdev->dev, "Failed to alloc mbox write back status\n");
+               goto err_uninit_func_mbox_msg_ch;
+       }
+
+       prepare_send_mbox(mbox);
+
+       return 0;
+
+err_uninit_func_mbox_msg_ch:
+       hinic3_uninit_func_mbox_msg_channel(hwdev);
+
+err_uninit_mgmt_msg_ch:
+       uninit_mgmt_msg_channel(mbox);
+
+err_destroy_workqueue:
+       destroy_workqueue(mbox->workq);
+
+err_free_mbox:
+       kfree(mbox);
+
+       return err;
+}
+
+void hinic3_free_mbox(struct hinic3_hwdev *hwdev)
+{
+       struct hinic3_mbox *mbox = hwdev->mbox;
+
+       destroy_workqueue(mbox->workq);
+       free_mbox_wb_status(mbox);
+       hinic3_uninit_func_mbox_msg_channel(hwdev);
+       uninit_mgmt_msg_channel(mbox);
+       kfree(mbox);
+}
+
 int hinic3_send_mbox_to_mgmt(struct hinic3_hwdev *hwdev, u8 mod, u16 cmd,
                             const struct mgmt_msg_params *msg_params)
 {
index d7a6c37b7eff7c32775df21119e3b5f945722e28..410254ab69f3c5ac58f0d99e1edd488eac40749f 100644 (file)
@@ -9,6 +9,109 @@
 
 struct hinic3_hwdev;
 
+#define MBOX_MSG_HEADER_SRC_GLB_FUNC_IDX_MASK  GENMASK_ULL(12, 0)
+#define MBOX_MSG_HEADER_STATUS_MASK            BIT_ULL(13)
+#define MBOX_MSG_HEADER_SOURCE_MASK            BIT_ULL(15)
+#define MBOX_MSG_HEADER_AEQ_ID_MASK            GENMASK_ULL(17, 16)
+#define MBOX_MSG_HEADER_MSG_ID_MASK            GENMASK_ULL(21, 18)
+#define MBOX_MSG_HEADER_CMD_MASK               GENMASK_ULL(31, 22)
+#define MBOX_MSG_HEADER_MSG_LEN_MASK           GENMASK_ULL(42, 32)
+#define MBOX_MSG_HEADER_MODULE_MASK            GENMASK_ULL(47, 43)
+#define MBOX_MSG_HEADER_SEG_LEN_MASK           GENMASK_ULL(53, 48)
+#define MBOX_MSG_HEADER_NO_ACK_MASK            BIT_ULL(54)
+#define MBOX_MSG_HEADER_DATA_TYPE_MASK         BIT_ULL(55)
+#define MBOX_MSG_HEADER_SEQID_MASK             GENMASK_ULL(61, 56)
+#define MBOX_MSG_HEADER_LAST_MASK              BIT_ULL(62)
+#define MBOX_MSG_HEADER_DIRECTION_MASK         BIT_ULL(63)
+
+#define MBOX_MSG_HEADER_SET(val, member) \
+       FIELD_PREP(MBOX_MSG_HEADER_##member##_MASK, val)
+#define MBOX_MSG_HEADER_GET(val, member) \
+       FIELD_GET(MBOX_MSG_HEADER_##member##_MASK, le64_to_cpu(val))
+
+/* identifies if a segment belongs to a message or to a response. A VF is only
+ * expected to send messages and receive responses. PF driver could receive
+ * messages and send responses.
+ */
+enum mbox_msg_direction_type {
+       MBOX_MSG_SEND = 0,
+       MBOX_MSG_RESP = 1,
+};
+
+#define HINIC3_MBOX_WQ_NAME  "hinic3_mbox"
+
+struct mbox_msg_info {
+       u8 msg_id;
+       u8 status;
+};
+
+struct hinic3_msg_desc {
+       u8                   *msg;
+       __le16               msg_len;
+       u8                   seq_id;
+       u8                   mod;
+       __le16               cmd;
+       struct mbox_msg_info msg_info;
+};
+
+struct hinic3_msg_channel {
+       struct   hinic3_msg_desc resp_msg;
+       struct   hinic3_msg_desc recv_msg;
+};
+
+struct hinic3_send_mbox {
+       u8 __iomem *data;
+       void       *wb_vaddr;
+       dma_addr_t wb_paddr;
+};
+
+enum mbox_event_state {
+       MBOX_EVENT_START   = 0,
+       MBOX_EVENT_FAIL    = 1,
+       MBOX_EVENT_SUCCESS = 2,
+       MBOX_EVENT_TIMEOUT = 3,
+       MBOX_EVENT_END     = 4,
+};
+
+struct mbox_dma_msg {
+       __le32 xor;
+       __le32 dma_addr_high;
+       __le32 dma_addr_low;
+       __le32 msg_len;
+       __le64 rsvd;
+};
+
+struct mbox_dma_queue {
+       void       *dma_buf_vaddr;
+       dma_addr_t dma_buf_paddr;
+       u16        depth;
+       u16        prod_idx;
+       u16        cons_idx;
+};
+
+struct hinic3_mbox {
+       struct hinic3_hwdev       *hwdev;
+       /* lock for send mbox message and ack message */
+       struct mutex              mbox_send_lock;
+       struct hinic3_send_mbox   send_mbox;
+       struct mbox_dma_queue     sync_msg_queue;
+       struct mbox_dma_queue     async_msg_queue;
+       struct workqueue_struct   *workq;
+       /* driver and MGMT CPU */
+       struct hinic3_msg_channel mgmt_msg;
+       /* VF to PF */
+       struct hinic3_msg_channel *func_msg;
+       u8                        send_msg_id;
+       enum mbox_event_state     event_flag;
+       /* lock for mbox event flag */
+       spinlock_t                mbox_lock;
+};
+
+void hinic3_mbox_func_aeqe_handler(struct hinic3_hwdev *hwdev, u8 *header,
+                                  u8 size);
+int hinic3_init_mbox(struct hinic3_hwdev *hwdev);
+void hinic3_free_mbox(struct hinic3_hwdev *hwdev);
+
 int hinic3_send_mbox_to_mgmt(struct hinic3_hwdev *hwdev, u8 mod, u16 cmd,
                             const struct mgmt_msg_params *msg_params);