mirror of
https://github.com/torvalds/linux.git
synced 2026-05-27 08:33:17 +02:00
hinic3: Mailbox framework
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>
This commit is contained in:
parent
bef7c33c67
commit
2742e06e2d
|
|
@ -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.
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
|
|
|||
|
|
@ -4,10 +4,419 @@
|
|||
#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)
|
||||
{
|
||||
|
|
|
|||
|
|
@ -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);
|
||||
|
||||
|
|
|
|||
Loading…
Reference in New Issue
Block a user