From mboxrd@z Thu Jan 1 00:00:00 1970 Received: from out-180.mta0.migadu.com (out-180.mta0.migadu.com [91.218.175.180]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id 796FB1F0E32 for ; Sat, 28 Jun 2025 13:04:13 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=91.218.175.180 ARC-Seal:i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1751115856; cv=none; b=lMcB/wOdqxT5rCRy6iEqEWcjPfgMpt4s63jCNru0oiltpilQhv14UfVLDl3KputtI7n6oIjlYAtZkQYfISe6moQWTc2+P+G5KupiEvKpD61DBwpNbesK03wjdL5yvE61VY49EOe1pC3MiwkGfJg18woLn55F+5L6k/BA3XBggnU= ARC-Message-Signature:i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1751115856; c=relaxed/simple; bh=nFtZVjZ1uyRu6VhuHQUmqdPGK2q6a3vMbXI2JLqwM+U=; h=Message-ID:Date:MIME-Version:Subject:To:Cc:References:From: In-Reply-To:Content-Type; b=fs2hD0LhzPfUy3ra3qOGFawN/Hxq/wOheWqAPj/UiOxsGbbgBukbOXOgscUVMqepxicAx87XSRFg5PVubqkzsiO49D+kshHiGAFLoArCp9VqjXl2xV+FgrWFnppcXIWqCXK+Ycd0IusREUgbL55ggmC4akSURLn+HzRc/RHSMfk= ARC-Authentication-Results:i=1; smtp.subspace.kernel.org; dmarc=pass (p=none dis=none) header.from=linux.dev; spf=pass smtp.mailfrom=linux.dev; dkim=pass (1024-bit key) header.d=linux.dev header.i=@linux.dev header.b=ch03SzPR; arc=none smtp.client-ip=91.218.175.180 Authentication-Results: smtp.subspace.kernel.org; dmarc=pass (p=none dis=none) header.from=linux.dev Authentication-Results: smtp.subspace.kernel.org; spf=pass smtp.mailfrom=linux.dev Authentication-Results: smtp.subspace.kernel.org; dkim=pass (1024-bit key) header.d=linux.dev header.i=@linux.dev header.b="ch03SzPR" Message-ID: <7c2ab3be-3b7b-49a5-82d2-99c8001ef635@linux.dev> DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=linux.dev; s=key1; t=1751115840; h=from:from:reply-to:subject:subject:date:date:message-id:message-id: to:to:cc:cc:mime-version:mime-version:content-type:content-type: content-transfer-encoding:content-transfer-encoding: in-reply-to:in-reply-to:references:references; bh=S7R/Lv9uuyIk9E8ryJEjauqWrBlCNSlAOgw6lFtntjY=; b=ch03SzPR9kwBK2y5yHqJ5ld9aNH/A6wnr+TOvXPTZbj3xD9VyGqfsuaZWFRO6RQrfJBIL3 JsIhboOFU521847/uI5XtEDESlSzmhNaqsPG0f7UtpRh0yGtuy3fxw9Uk5Hc3Bl9Oj9Mgq CcGLRPvGWuTzHpdNleRkKA149rTb9lE= Date: Sat, 28 Jun 2025 14:03:57 +0100 Precedence: bulk X-Mailing-List: netdev@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 Subject: Re: [PATCH net-next v06 6/8] hinic3: Mailbox framework To: Fan Gong , Zhu Yikai Cc: netdev@vger.kernel.org, linux-kernel@vger.kernel.org, "David S. Miller" , Eric Dumazet , Jakub Kicinski , Paolo Abeni , Simon Horman , Andrew Lunn , linux-doc@vger.kernel.org, Jonathan Corbet , Bjorn Helgaas , luosifu , Xin Guo , Shen Chenyang , Zhou Shuai , Wu Like , Shi Jing , Meny Yossefi , Gur Stavi , Lee Trager , Michael Ellerman , Suman Ghosh , Przemek Kitszel , Joe Damato , Christophe JAILLET References: <5ce04bcb15efc1920cc834421627d1f43f66101c.1750937080.git.zhuyikai1@h-partners.com> Content-Language: en-US X-Report-Abuse: Please report any abuse attempt to abuse@migadu.com and include these headers. From: Vadim Fedorenko In-Reply-To: <5ce04bcb15efc1920cc834421627d1f43f66101c.1750937080.git.zhuyikai1@h-partners.com> Content-Type: text/plain; charset=UTF-8; format=flowed Content-Transfer-Encoding: 7bit X-Migadu-Flow: FLOW_OUT On 27/06/2025 07:12, Fan Gong wrote: > Add mailbox framework initialization. > It allows driver to send commands to HW. > > Co-developed-by: Xin Guo > Signed-off-by: Xin Guo > Co-developed-by: Zhu Yikai > Signed-off-by: Zhu Yikai > Signed-off-by: Fan Gong > --- > .../ethernet/huawei/hinic3/hinic3_common.c | 14 + > .../ethernet/huawei/hinic3/hinic3_common.h | 9 + > .../net/ethernet/huawei/hinic3/hinic3_eqs.c | 9 +- > .../net/ethernet/huawei/hinic3/hinic3_mbox.c | 403 ++++++++++++++++++ > .../net/ethernet/huawei/hinic3/hinic3_mbox.h | 105 +++++ > 5 files changed, 537 insertions(+), 3 deletions(-) > > diff --git a/drivers/net/ethernet/huawei/hinic3/hinic3_common.c b/drivers/net/ethernet/huawei/hinic3/hinic3_common.c > index d3a69d67b4c1..016da1911072 100644 > --- a/drivers/net/ethernet/huawei/hinic3/hinic3_common.c > +++ b/drivers/net/ethernet/huawei/hinic3/hinic3_common.c > @@ -3,6 +3,7 @@ > > #include > #include > +#include > > #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. This is a mandatory swap regardless of the > diff --git a/drivers/net/ethernet/huawei/hinic3/hinic3_common.h b/drivers/net/ethernet/huawei/hinic3/hinic3_common.h > index 52d6cb2515c8..50d1fd038b48 100644 > --- a/drivers/net/ethernet/huawei/hinic3/hinic3_common.h > +++ b/drivers/net/ethernet/huawei/hinic3/hinic3_common.h > @@ -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 { > u32 hi_addr; > u32 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 > diff --git a/drivers/net/ethernet/huawei/hinic3/hinic3_eqs.c b/drivers/net/ethernet/huawei/hinic3/hinic3_eqs.c > index 0d1f1b406064..fec82ce42939 100644 > --- a/drivers/net/ethernet/huawei/hinic3/hinic3_eqs.c > +++ b/drivers/net/ethernet/huawei/hinic3/hinic3_eqs.c > @@ -361,10 +361,13 @@ static void ceq_tasklet(ulong ceq_data) > > static irqreturn_t aeq_interrupt(int irq, void *data) > { > - struct hinic3_eq *aeq = data; > - struct hinic3_aeqs *aeqs = aeq_to_aeqs(aeq); > - struct hinic3_hwdev *hwdev = aeq->hwdev; > struct workqueue_struct *workq; > + struct hinic3_eq *aeq = data; > + struct hinic3_hwdev *hwdev; > + struct hinic3_aeqs *aeqs; > + > + aeqs = aeq_to_aeqs(aeq); > + hwdev = aeq->hwdev; > > /* clear resend timer cnt register */ > workq = aeqs->workq; > diff --git a/drivers/net/ethernet/huawei/hinic3/hinic3_mbox.c b/drivers/net/ethernet/huawei/hinic3/hinic3_mbox.c > index e74d1eb09730..2967bc29408f 100644 > --- a/drivers/net/ethernet/huawei/hinic3/hinic3_mbox.c > +++ b/drivers/net/ethernet/huawei/hinic3/hinic3_mbox.c > @@ -4,10 +4,413 @@ > #include > > #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_BODY_FROM_HDR(header) ((u8 *)(header) + MBOX_HEADER_SZ) > +#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 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, > + u64 mbox_header) > +{ > + u8 seq_id, seg_len, msg_id, mod; > + u16 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 = MBOX_MSG_HEADER_GET(mbox_header, CMD); > + src_func_idx = 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, > + u64 *header, struct hinic3_msg_desc *msg_desc) > +{ > + void *mbox_body = MBOX_BODY_FROM_HDR(((void *)header)); > + u64 mbox_header = *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((u8 *)msg_desc->msg + pos, mbox_body, seg_len); > + > + if (!MBOX_MSG_HEADER_GET(mbox_header, LAST)) > + return; > + > + msg_desc->msg_len = 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) > +{ > + u64 mbox_header = *((u64 *)header); The question here is how will it work with different endianess? AFAIU, u8 *header is a buffer filled in by FW with device's endianess, which you directly convert into host's endianess into u64 value. If the endianess doesn't match, this conversion will fail. > + 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, (u64 *)header, msg_desc); > +} I cannot find any code which calls hinic3_mbox_func_aeqe_handler(), neither in this patch, nor further in the patchset. What is the reason to have it in this series? > + > +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); > + mutex_init(&mbox->msg_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"); > + kfree(mbox); > + 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) > + return err; > + > + 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); > + 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) > { > diff --git a/drivers/net/ethernet/huawei/hinic3/hinic3_mbox.h b/drivers/net/ethernet/huawei/hinic3/hinic3_mbox.h > index d7a6c37b7eff..730795b66a86 100644 > --- a/drivers/net/ethernet/huawei/hinic3/hinic3_mbox.h > +++ b/drivers/net/ethernet/huawei/hinic3/hinic3_mbox.h > @@ -9,6 +9,111 @@ > > 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, 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 { > + void *msg; > + u16 msg_len; > + u8 seq_id; > + u8 mod; > + u16 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 { > + u32 xor; > + u32 dma_addr_high; > + u32 dma_addr_low; > + u32 msg_len; > + u64 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; > + /* lock for send mbox message */ > + struct mutex msg_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); >