/* SPDX-License-Identifier: GPL-2.0 */ /* Copyright (c) Huawei Technologies Co., Ltd. 2025. All rights reserved. */ #ifndef _HINIC3_CMDQ_H_ #define _HINIC3_CMDQ_H_ #include #include "hinic3_hw_intf.h" #include "hinic3_wq.h" #define CMDQ_DEPTH 4096 struct cmdq_db { __le32 db_head; __le32 db_info; }; /* hw defined cmdq wqe header */ struct cmdq_header { __le32 header_info; __le32 saved_data; }; struct cmdq_lcmd_bufdesc { struct hinic3_sge sge; __le64 rsvd2; __le64 rsvd3; }; struct cmdq_status { __le32 status_info; }; struct cmdq_ctrl { __le32 ctrl_info; }; struct cmdq_direct_resp { __le64 val; __le64 rsvd; }; struct cmdq_completion { union { struct hinic3_sge sge; struct cmdq_direct_resp direct; } resp; }; struct cmdq_wqe_scmd { struct cmdq_header header; __le64 rsvd3; struct cmdq_status status; struct cmdq_ctrl ctrl; struct cmdq_completion completion; __le32 rsvd10[6]; }; struct cmdq_wqe_lcmd { struct cmdq_header header; struct cmdq_status status; struct cmdq_ctrl ctrl; struct cmdq_completion completion; struct cmdq_lcmd_bufdesc buf_desc; }; struct cmdq_wqe { union { struct cmdq_wqe_scmd wqe_scmd; struct cmdq_wqe_lcmd wqe_lcmd; }; }; static_assert(sizeof(struct cmdq_wqe) == 64); enum hinic3_cmdq_type { HINIC3_CMDQ_SYNC = 0, HINIC3_MAX_CMDQ_TYPES = 4 }; enum hinic3_cmdq_status { HINIC3_CMDQ_ENABLE = BIT(0), }; enum hinic3_cmdq_cmd_type { HINIC3_CMD_TYPE_NONE, HINIC3_CMD_TYPE_DIRECT_RESP, HINIC3_CMD_TYPE_FAKE_TIMEOUT, HINIC3_CMD_TYPE_TIMEOUT, HINIC3_CMD_TYPE_FORCE_STOP, }; struct hinic3_cmd_buf { void *buf; dma_addr_t dma_addr; __le16 size; refcount_t ref_cnt; }; struct hinic3_cmdq_cmd_info { enum hinic3_cmdq_cmd_type cmd_type; struct completion *done; int *errcode; /* completion code */ int *cmpt_code; __le64 *direct_resp; u64 cmdq_msg_id; struct hinic3_cmd_buf *buf_in; }; struct hinic3_cmdq { struct hinic3_wq wq; enum hinic3_cmdq_type cmdq_type; u8 wrapped; /* synchronize command submission with completions via event queue */ spinlock_t cmdq_lock; struct hinic3_cmdq_cmd_info *cmd_infos; struct hinic3_hwdev *hwdev; }; struct hinic3_cmdqs { struct hinic3_hwdev *hwdev; struct hinic3_cmdq cmdq[HINIC3_MAX_CMDQ_TYPES]; struct dma_pool *cmd_buf_pool; /* doorbell area */ u8 __iomem *cmdqs_db_base; /* When command queue uses multiple memory pages (1-level CLA), this * block will hold aggregated indirection table for all command queues * of cmdqs. Not used for small cmdq (0-level CLA). */ dma_addr_t wq_block_paddr; void *wq_block_vaddr; u32 status; u32 disable_flag; u8 cmdq_num; }; int hinic3_cmdqs_init(struct hinic3_hwdev *hwdev); void hinic3_cmdqs_free(struct hinic3_hwdev *hwdev); struct hinic3_cmd_buf *hinic3_alloc_cmd_buf(struct hinic3_hwdev *hwdev); void hinic3_free_cmd_buf(struct hinic3_hwdev *hwdev, struct hinic3_cmd_buf *cmd_buf); void hinic3_cmdq_ceq_handler(struct hinic3_hwdev *hwdev, __le32 ceqe_data); int hinic3_cmdq_direct_resp(struct hinic3_hwdev *hwdev, u8 mod, u8 cmd, struct hinic3_cmd_buf *buf_in, __le64 *out_param); void hinic3_cmdq_flush_sync_cmd(struct hinic3_hwdev *hwdev); int hinic3_reinit_cmdq_ctxts(struct hinic3_hwdev *hwdev); bool hinic3_cmdq_idle(struct hinic3_cmdq *cmdq); #endif