xref: /dpdk/drivers/net/hinic/base/hinic_pmd_cmdq.c (revision d807dd7d4cd8e3ef4d42bd945cfb8318e4fef5b6)
17fcd6b05SZiyang Xuan /* SPDX-License-Identifier: BSD-3-Clause
27fcd6b05SZiyang Xuan  * Copyright(c) 2017 Huawei Technologies Co., Ltd
37fcd6b05SZiyang Xuan  */
47fcd6b05SZiyang Xuan 
57fcd6b05SZiyang Xuan #include "hinic_compat.h"
67fcd6b05SZiyang Xuan #include "hinic_pmd_hwdev.h"
77fcd6b05SZiyang Xuan #include "hinic_pmd_hwif.h"
87fcd6b05SZiyang Xuan #include "hinic_pmd_wq.h"
97fcd6b05SZiyang Xuan #include "hinic_pmd_mgmt.h"
100194313bSXiaoyun Wang #include "hinic_pmd_mbox.h"
117fcd6b05SZiyang Xuan #include "hinic_pmd_cmdq.h"
127fcd6b05SZiyang Xuan 
137fcd6b05SZiyang Xuan #define CMDQ_CMD_TIMEOUT				5000 /* millisecond */
147fcd6b05SZiyang Xuan 
157fcd6b05SZiyang Xuan #define UPPER_8_BITS(data)				(((data) >> 8) & 0xFF)
167fcd6b05SZiyang Xuan #define LOWER_8_BITS(data)				((data) & 0xFF)
177fcd6b05SZiyang Xuan 
187fcd6b05SZiyang Xuan #define CMDQ_DB_INFO_HI_PROD_IDX_SHIFT			0
197fcd6b05SZiyang Xuan #define CMDQ_DB_INFO_QUEUE_TYPE_SHIFT			23
207fcd6b05SZiyang Xuan #define CMDQ_DB_INFO_CMDQ_TYPE_SHIFT			24
217fcd6b05SZiyang Xuan #define CMDQ_DB_INFO_SRC_TYPE_SHIFT			27
227fcd6b05SZiyang Xuan 
237fcd6b05SZiyang Xuan #define CMDQ_DB_INFO_HI_PROD_IDX_MASK			0xFFU
247fcd6b05SZiyang Xuan #define CMDQ_DB_INFO_QUEUE_TYPE_MASK			0x1U
257fcd6b05SZiyang Xuan #define CMDQ_DB_INFO_CMDQ_TYPE_MASK			0x7U
267fcd6b05SZiyang Xuan #define CMDQ_DB_INFO_SRC_TYPE_MASK			0x1FU
277fcd6b05SZiyang Xuan 
287fcd6b05SZiyang Xuan #define CMDQ_DB_INFO_SET(val, member)		\
297fcd6b05SZiyang Xuan 	(((val) & CMDQ_DB_INFO_##member##_MASK) <<	\
307fcd6b05SZiyang Xuan 		CMDQ_DB_INFO_##member##_SHIFT)
317fcd6b05SZiyang Xuan 
327fcd6b05SZiyang Xuan #define CMDQ_CTRL_PI_SHIFT				0
337fcd6b05SZiyang Xuan #define CMDQ_CTRL_CMD_SHIFT				16
347fcd6b05SZiyang Xuan #define CMDQ_CTRL_MOD_SHIFT				24
357fcd6b05SZiyang Xuan #define CMDQ_CTRL_ACK_TYPE_SHIFT			29
367fcd6b05SZiyang Xuan #define CMDQ_CTRL_HW_BUSY_BIT_SHIFT			31
377fcd6b05SZiyang Xuan 
387fcd6b05SZiyang Xuan #define CMDQ_CTRL_PI_MASK				0xFFFFU
397fcd6b05SZiyang Xuan #define CMDQ_CTRL_CMD_MASK				0xFFU
407fcd6b05SZiyang Xuan #define CMDQ_CTRL_MOD_MASK				0x1FU
417fcd6b05SZiyang Xuan #define CMDQ_CTRL_ACK_TYPE_MASK				0x3U
427fcd6b05SZiyang Xuan #define CMDQ_CTRL_HW_BUSY_BIT_MASK			0x1U
437fcd6b05SZiyang Xuan 
447fcd6b05SZiyang Xuan #define CMDQ_CTRL_SET(val, member)		\
457fcd6b05SZiyang Xuan 	(((val) & CMDQ_CTRL_##member##_MASK) << CMDQ_CTRL_##member##_SHIFT)
467fcd6b05SZiyang Xuan 
477fcd6b05SZiyang Xuan #define CMDQ_CTRL_GET(val, member)		\
487fcd6b05SZiyang Xuan 	(((val) >> CMDQ_CTRL_##member##_SHIFT) & CMDQ_CTRL_##member##_MASK)
497fcd6b05SZiyang Xuan 
507fcd6b05SZiyang Xuan #define CMDQ_WQE_HEADER_BUFDESC_LEN_SHIFT		0
517fcd6b05SZiyang Xuan #define CMDQ_WQE_HEADER_COMPLETE_FMT_SHIFT		15
527fcd6b05SZiyang Xuan #define CMDQ_WQE_HEADER_DATA_FMT_SHIFT			22
537fcd6b05SZiyang Xuan #define CMDQ_WQE_HEADER_COMPLETE_REQ_SHIFT		23
547fcd6b05SZiyang Xuan #define CMDQ_WQE_HEADER_COMPLETE_SECT_LEN_SHIFT		27
557fcd6b05SZiyang Xuan #define CMDQ_WQE_HEADER_CTRL_LEN_SHIFT			29
567fcd6b05SZiyang Xuan #define CMDQ_WQE_HEADER_HW_BUSY_BIT_SHIFT		31
577fcd6b05SZiyang Xuan 
587fcd6b05SZiyang Xuan #define CMDQ_WQE_HEADER_BUFDESC_LEN_MASK		0xFFU
597fcd6b05SZiyang Xuan #define CMDQ_WQE_HEADER_COMPLETE_FMT_MASK		0x1U
607fcd6b05SZiyang Xuan #define CMDQ_WQE_HEADER_DATA_FMT_MASK			0x1U
617fcd6b05SZiyang Xuan #define CMDQ_WQE_HEADER_COMPLETE_REQ_MASK		0x1U
627fcd6b05SZiyang Xuan #define CMDQ_WQE_HEADER_COMPLETE_SECT_LEN_MASK		0x3U
637fcd6b05SZiyang Xuan #define CMDQ_WQE_HEADER_CTRL_LEN_MASK			0x3U
647fcd6b05SZiyang Xuan #define CMDQ_WQE_HEADER_HW_BUSY_BIT_MASK		0x1U
657fcd6b05SZiyang Xuan 
667fcd6b05SZiyang Xuan #define CMDQ_WQE_HEADER_SET(val, member)	\
677fcd6b05SZiyang Xuan 	(((val) & CMDQ_WQE_HEADER_##member##_MASK) <<	\
687fcd6b05SZiyang Xuan 		CMDQ_WQE_HEADER_##member##_SHIFT)
697fcd6b05SZiyang Xuan 
707fcd6b05SZiyang Xuan #define CMDQ_WQE_HEADER_GET(val, member)	\
717fcd6b05SZiyang Xuan 	(((val) >> CMDQ_WQE_HEADER_##member##_SHIFT) &	\
727fcd6b05SZiyang Xuan 		CMDQ_WQE_HEADER_##member##_MASK)
737fcd6b05SZiyang Xuan 
747fcd6b05SZiyang Xuan #define CMDQ_CTXT_CURR_WQE_PAGE_PFN_SHIFT		0
757fcd6b05SZiyang Xuan #define CMDQ_CTXT_EQ_ID_SHIFT				56
767fcd6b05SZiyang Xuan #define CMDQ_CTXT_CEQ_ARM_SHIFT				61
777fcd6b05SZiyang Xuan #define CMDQ_CTXT_CEQ_EN_SHIFT				62
787fcd6b05SZiyang Xuan #define CMDQ_CTXT_HW_BUSY_BIT_SHIFT			63
797fcd6b05SZiyang Xuan 
807fcd6b05SZiyang Xuan #define CMDQ_CTXT_CURR_WQE_PAGE_PFN_MASK		0xFFFFFFFFFFFFF
817fcd6b05SZiyang Xuan #define CMDQ_CTXT_EQ_ID_MASK				0x1F
827fcd6b05SZiyang Xuan #define CMDQ_CTXT_CEQ_ARM_MASK				0x1
837fcd6b05SZiyang Xuan #define CMDQ_CTXT_CEQ_EN_MASK				0x1
847fcd6b05SZiyang Xuan #define CMDQ_CTXT_HW_BUSY_BIT_MASK			0x1
857fcd6b05SZiyang Xuan 
867fcd6b05SZiyang Xuan #define CMDQ_CTXT_PAGE_INFO_SET(val, member)		\
877fcd6b05SZiyang Xuan 	(((u64)(val) & CMDQ_CTXT_##member##_MASK) << CMDQ_CTXT_##member##_SHIFT)
887fcd6b05SZiyang Xuan 
897fcd6b05SZiyang Xuan #define CMDQ_CTXT_PAGE_INFO_CLEAR(val, member)		\
907fcd6b05SZiyang Xuan 	((val) & (~((u64)CMDQ_CTXT_##member##_MASK <<	\
917fcd6b05SZiyang Xuan 		CMDQ_CTXT_##member##_SHIFT)))
927fcd6b05SZiyang Xuan 
937fcd6b05SZiyang Xuan #define CMDQ_CTXT_WQ_BLOCK_PFN_SHIFT			0
947fcd6b05SZiyang Xuan #define CMDQ_CTXT_CI_SHIFT				52
957fcd6b05SZiyang Xuan 
967fcd6b05SZiyang Xuan #define CMDQ_CTXT_WQ_BLOCK_PFN_MASK			0xFFFFFFFFFFFFF
977fcd6b05SZiyang Xuan #define CMDQ_CTXT_CI_MASK				0xFFF
987fcd6b05SZiyang Xuan 
997fcd6b05SZiyang Xuan #define CMDQ_CTXT_BLOCK_INFO_SET(val, member)		\
1007fcd6b05SZiyang Xuan 	(((u64)(val) & CMDQ_CTXT_##member##_MASK) << CMDQ_CTXT_##member##_SHIFT)
1017fcd6b05SZiyang Xuan 
1027fcd6b05SZiyang Xuan #define SAVED_DATA_ARM_SHIFT			31
1037fcd6b05SZiyang Xuan 
1047fcd6b05SZiyang Xuan #define SAVED_DATA_ARM_MASK			0x1U
1057fcd6b05SZiyang Xuan 
1067fcd6b05SZiyang Xuan #define SAVED_DATA_SET(val, member)		\
1077fcd6b05SZiyang Xuan 	(((val) & SAVED_DATA_##member##_MASK) << SAVED_DATA_##member##_SHIFT)
1087fcd6b05SZiyang Xuan 
1097fcd6b05SZiyang Xuan #define SAVED_DATA_CLEAR(val, member)		\
1107fcd6b05SZiyang Xuan 	((val) & (~(SAVED_DATA_##member##_MASK << SAVED_DATA_##member##_SHIFT)))
1117fcd6b05SZiyang Xuan 
1127fcd6b05SZiyang Xuan #define WQE_ERRCODE_VAL_SHIFT			20
1137fcd6b05SZiyang Xuan 
1147fcd6b05SZiyang Xuan #define WQE_ERRCODE_VAL_MASK			0xF
1157fcd6b05SZiyang Xuan 
1167fcd6b05SZiyang Xuan #define WQE_ERRCODE_GET(val, member)		\
1177fcd6b05SZiyang Xuan 	(((val) >> WQE_ERRCODE_##member##_SHIFT) & WQE_ERRCODE_##member##_MASK)
1187fcd6b05SZiyang Xuan 
1197fcd6b05SZiyang Xuan #define WQE_COMPLETED(ctrl_info)	CMDQ_CTRL_GET(ctrl_info, HW_BUSY_BIT)
1207fcd6b05SZiyang Xuan 
1217fcd6b05SZiyang Xuan #define WQE_HEADER(wqe)		((struct hinic_cmdq_header *)(wqe))
1227fcd6b05SZiyang Xuan 
1237fcd6b05SZiyang Xuan #define CMDQ_DB_PI_OFF(pi)		(((u16)LOWER_8_BITS(pi)) << 3)
1247fcd6b05SZiyang Xuan 
1257fcd6b05SZiyang Xuan #define CMDQ_DB_ADDR(db_base, pi)	\
1267fcd6b05SZiyang Xuan 	(((u8 *)(db_base) + HINIC_DB_OFF) + CMDQ_DB_PI_OFF(pi))
1277fcd6b05SZiyang Xuan 
1287fcd6b05SZiyang Xuan #define CMDQ_PFN(addr, page_size)	((addr) >> (ilog2(page_size)))
1297fcd6b05SZiyang Xuan 
1307fcd6b05SZiyang Xuan #define FIRST_DATA_TO_WRITE_LAST	sizeof(u64)
1317fcd6b05SZiyang Xuan 
1327fcd6b05SZiyang Xuan #define WQE_LCMD_SIZE		64
1337fcd6b05SZiyang Xuan #define WQE_SCMD_SIZE		64
1347fcd6b05SZiyang Xuan 
1357fcd6b05SZiyang Xuan #define COMPLETE_LEN		3
1367fcd6b05SZiyang Xuan 
1377fcd6b05SZiyang Xuan #define CMDQ_WQEBB_SIZE		64
1387fcd6b05SZiyang Xuan #define CMDQ_WQEBB_SHIFT	6
1397fcd6b05SZiyang Xuan 
1407fcd6b05SZiyang Xuan #define CMDQ_WQE_SIZE		64
1417fcd6b05SZiyang Xuan 
1427fcd6b05SZiyang Xuan #define HINIC_CMDQ_WQ_BUF_SIZE	4096
1437fcd6b05SZiyang Xuan 
1447fcd6b05SZiyang Xuan #define WQE_NUM_WQEBBS(wqe_size, wq)	\
1457fcd6b05SZiyang Xuan 	((u16)(ALIGN((u32)(wqe_size), (wq)->wqebb_size) / (wq)->wqebb_size))
1467fcd6b05SZiyang Xuan 
1477fcd6b05SZiyang Xuan #define cmdq_to_cmdqs(cmdq)	container_of((cmdq) - (cmdq)->cmdq_type, \
1487fcd6b05SZiyang Xuan 				struct hinic_cmdqs, cmdq[0])
1497fcd6b05SZiyang Xuan 
1507fcd6b05SZiyang Xuan #define WAIT_CMDQ_ENABLE_TIMEOUT	300
1517fcd6b05SZiyang Xuan 
1527fcd6b05SZiyang Xuan 
1537fcd6b05SZiyang Xuan static void cmdq_init_queue_ctxt(struct hinic_cmdq *cmdq,
1547fcd6b05SZiyang Xuan 				 struct hinic_cmdq_ctxt *cmdq_ctxt);
1557fcd6b05SZiyang Xuan static void hinic_cmdqs_free(struct hinic_hwdev *hwdev);
1567fcd6b05SZiyang Xuan 
hinic_cmdq_idle(struct hinic_cmdq * cmdq)1577fcd6b05SZiyang Xuan bool hinic_cmdq_idle(struct hinic_cmdq *cmdq)
1587fcd6b05SZiyang Xuan {
1597fcd6b05SZiyang Xuan 	struct hinic_wq *wq = cmdq->wq;
1607fcd6b05SZiyang Xuan 
1617fcd6b05SZiyang Xuan 	return ((wq->delta) == wq->q_depth ? true : false);
1627fcd6b05SZiyang Xuan }
1637fcd6b05SZiyang Xuan 
hinic_alloc_cmd_buf(void * hwdev)1647fcd6b05SZiyang Xuan struct hinic_cmd_buf *hinic_alloc_cmd_buf(void *hwdev)
1657fcd6b05SZiyang Xuan {
1667fcd6b05SZiyang Xuan 	struct hinic_cmdqs *cmdqs = ((struct hinic_hwdev *)hwdev)->cmdqs;
1677fcd6b05SZiyang Xuan 	struct hinic_cmd_buf *cmd_buf;
1687fcd6b05SZiyang Xuan 
1697fcd6b05SZiyang Xuan 	cmd_buf = kzalloc(sizeof(*cmd_buf), GFP_KERNEL);
1707fcd6b05SZiyang Xuan 	if (!cmd_buf) {
1717fcd6b05SZiyang Xuan 		PMD_DRV_LOG(ERR, "Allocate cmd buffer failed");
1727fcd6b05SZiyang Xuan 		return NULL;
1737fcd6b05SZiyang Xuan 	}
1747fcd6b05SZiyang Xuan 
1751b7b9f17SXiaoyun Wang 	cmd_buf->buf = pci_pool_alloc(cmdqs->cmd_buf_pool, &cmd_buf->dma_addr);
1767fcd6b05SZiyang Xuan 	if (!cmd_buf->buf) {
1777fcd6b05SZiyang Xuan 		PMD_DRV_LOG(ERR, "Allocate cmd from the pool failed");
1787fcd6b05SZiyang Xuan 		goto alloc_pci_buf_err;
1797fcd6b05SZiyang Xuan 	}
1807fcd6b05SZiyang Xuan 
1817fcd6b05SZiyang Xuan 	return cmd_buf;
1827fcd6b05SZiyang Xuan 
1837fcd6b05SZiyang Xuan alloc_pci_buf_err:
1847fcd6b05SZiyang Xuan 	kfree(cmd_buf);
1857fcd6b05SZiyang Xuan 	return NULL;
1867fcd6b05SZiyang Xuan }
1877fcd6b05SZiyang Xuan 
hinic_free_cmd_buf(void * hwdev,struct hinic_cmd_buf * cmd_buf)1887fcd6b05SZiyang Xuan void hinic_free_cmd_buf(void *hwdev, struct hinic_cmd_buf *cmd_buf)
1897fcd6b05SZiyang Xuan {
1907fcd6b05SZiyang Xuan 	struct hinic_cmdqs *cmdqs = ((struct hinic_hwdev *)hwdev)->cmdqs;
1917fcd6b05SZiyang Xuan 
1927fcd6b05SZiyang Xuan 	pci_pool_free(cmdqs->cmd_buf_pool, cmd_buf->buf, cmd_buf->dma_addr);
1937fcd6b05SZiyang Xuan 	kfree(cmd_buf);
1947fcd6b05SZiyang Xuan }
1957fcd6b05SZiyang Xuan 
cmdq_wqe_size(enum cmdq_wqe_type wqe_type)1967fcd6b05SZiyang Xuan static u32 cmdq_wqe_size(enum cmdq_wqe_type wqe_type)
1977fcd6b05SZiyang Xuan {
1987fcd6b05SZiyang Xuan 	u32 wqe_size = 0;
1997fcd6b05SZiyang Xuan 
2007fcd6b05SZiyang Xuan 	switch (wqe_type) {
2017fcd6b05SZiyang Xuan 	case WQE_LCMD_TYPE:
2027fcd6b05SZiyang Xuan 		wqe_size = WQE_LCMD_SIZE;
2037fcd6b05SZiyang Xuan 		break;
2047fcd6b05SZiyang Xuan 	case WQE_SCMD_TYPE:
2057fcd6b05SZiyang Xuan 		wqe_size = WQE_SCMD_SIZE;
2067fcd6b05SZiyang Xuan 		break;
2077fcd6b05SZiyang Xuan 	}
2087fcd6b05SZiyang Xuan 
2097fcd6b05SZiyang Xuan 	return wqe_size;
2107fcd6b05SZiyang Xuan }
2117fcd6b05SZiyang Xuan 
cmdq_get_wqe_size(enum bufdesc_len len)2127fcd6b05SZiyang Xuan static int cmdq_get_wqe_size(enum bufdesc_len len)
2137fcd6b05SZiyang Xuan {
2147fcd6b05SZiyang Xuan 	int wqe_size = 0;
2157fcd6b05SZiyang Xuan 
2167fcd6b05SZiyang Xuan 	switch (len) {
2177fcd6b05SZiyang Xuan 	case BUFDESC_LCMD_LEN:
2187fcd6b05SZiyang Xuan 		wqe_size = WQE_LCMD_SIZE;
2197fcd6b05SZiyang Xuan 		break;
2207fcd6b05SZiyang Xuan 	case BUFDESC_SCMD_LEN:
2217fcd6b05SZiyang Xuan 		wqe_size = WQE_SCMD_SIZE;
2227fcd6b05SZiyang Xuan 		break;
2237fcd6b05SZiyang Xuan 	}
2247fcd6b05SZiyang Xuan 
2257fcd6b05SZiyang Xuan 	return wqe_size;
2267fcd6b05SZiyang Xuan }
2277fcd6b05SZiyang Xuan 
cmdq_set_completion(struct hinic_cmdq_completion * complete,struct hinic_cmd_buf * buf_out)2287fcd6b05SZiyang Xuan static void cmdq_set_completion(struct hinic_cmdq_completion *complete,
2297fcd6b05SZiyang Xuan 					struct hinic_cmd_buf *buf_out)
2307fcd6b05SZiyang Xuan {
2317fcd6b05SZiyang Xuan 	struct hinic_sge_resp *sge_resp = &complete->sge_resp;
2327fcd6b05SZiyang Xuan 
2337fcd6b05SZiyang Xuan 	hinic_set_sge(&sge_resp->sge, buf_out->dma_addr,
2347fcd6b05SZiyang Xuan 		      HINIC_CMDQ_BUF_SIZE);
2357fcd6b05SZiyang Xuan }
2367fcd6b05SZiyang Xuan 
cmdq_set_lcmd_bufdesc(struct hinic_cmdq_wqe_lcmd * wqe,struct hinic_cmd_buf * buf_in)2377fcd6b05SZiyang Xuan static void cmdq_set_lcmd_bufdesc(struct hinic_cmdq_wqe_lcmd *wqe,
2387fcd6b05SZiyang Xuan 					struct hinic_cmd_buf *buf_in)
2397fcd6b05SZiyang Xuan {
2407fcd6b05SZiyang Xuan 	hinic_set_sge(&wqe->buf_desc.sge, buf_in->dma_addr, buf_in->size);
2417fcd6b05SZiyang Xuan }
2427fcd6b05SZiyang Xuan 
cmdq_fill_db(struct hinic_cmdq_db * db,enum hinic_cmdq_type cmdq_type,u16 prod_idx)2437fcd6b05SZiyang Xuan static void cmdq_fill_db(struct hinic_cmdq_db *db,
2447fcd6b05SZiyang Xuan 			enum hinic_cmdq_type cmdq_type, u16 prod_idx)
2457fcd6b05SZiyang Xuan {
2467fcd6b05SZiyang Xuan 	db->db_info = CMDQ_DB_INFO_SET(UPPER_8_BITS(prod_idx), HI_PROD_IDX) |
2477fcd6b05SZiyang Xuan 			CMDQ_DB_INFO_SET(HINIC_DB_CMDQ_TYPE, QUEUE_TYPE) |
2487fcd6b05SZiyang Xuan 			CMDQ_DB_INFO_SET(cmdq_type, CMDQ_TYPE)		|
2497fcd6b05SZiyang Xuan 			CMDQ_DB_INFO_SET(HINIC_DB_SRC_CMDQ_TYPE, SRC_TYPE);
2507fcd6b05SZiyang Xuan }
2517fcd6b05SZiyang Xuan 
cmdq_set_db(struct hinic_cmdq * cmdq,enum hinic_cmdq_type cmdq_type,u16 prod_idx)2527fcd6b05SZiyang Xuan static void cmdq_set_db(struct hinic_cmdq *cmdq,
2537fcd6b05SZiyang Xuan 			enum hinic_cmdq_type cmdq_type, u16 prod_idx)
2547fcd6b05SZiyang Xuan {
2557fcd6b05SZiyang Xuan 	struct hinic_cmdq_db db;
2567fcd6b05SZiyang Xuan 
2577fcd6b05SZiyang Xuan 	cmdq_fill_db(&db, cmdq_type, prod_idx);
2587fcd6b05SZiyang Xuan 
2597fcd6b05SZiyang Xuan 	/* The data that is written to HW should be in Big Endian Format */
2607fcd6b05SZiyang Xuan 	db.db_info = cpu_to_be32(db.db_info);
2617fcd6b05SZiyang Xuan 
2627fcd6b05SZiyang Xuan 	rte_wmb();	/* write all before the doorbell */
2637fcd6b05SZiyang Xuan 
2647fcd6b05SZiyang Xuan 	writel(db.db_info, CMDQ_DB_ADDR(cmdq->db_base, prod_idx));
2657fcd6b05SZiyang Xuan }
2667fcd6b05SZiyang Xuan 
cmdq_wqe_fill(void * dst,void * src)2677fcd6b05SZiyang Xuan static void cmdq_wqe_fill(void *dst, void *src)
2687fcd6b05SZiyang Xuan {
2697fcd6b05SZiyang Xuan 	memcpy((u8 *)dst + FIRST_DATA_TO_WRITE_LAST,
2707fcd6b05SZiyang Xuan 	       (u8 *)src + FIRST_DATA_TO_WRITE_LAST,
2717fcd6b05SZiyang Xuan 	       CMDQ_WQE_SIZE - FIRST_DATA_TO_WRITE_LAST);
2727fcd6b05SZiyang Xuan 
2737fcd6b05SZiyang Xuan 	rte_wmb();/* The first 8 bytes should be written last */
2747fcd6b05SZiyang Xuan 
2757fcd6b05SZiyang Xuan 	*(u64 *)dst = *(u64 *)src;
2767fcd6b05SZiyang Xuan }
2777fcd6b05SZiyang Xuan 
cmdq_prepare_wqe_ctrl(struct hinic_cmdq_wqe * wqe,int wrapped,enum hinic_ack_type ack_type,enum hinic_mod_type mod,u8 cmd,u16 prod_idx,enum completion_format complete_format,enum data_format local_data_format,enum bufdesc_len buf_len)2787fcd6b05SZiyang Xuan static void cmdq_prepare_wqe_ctrl(struct hinic_cmdq_wqe *wqe, int wrapped,
2797fcd6b05SZiyang Xuan 				  enum hinic_ack_type ack_type,
2807fcd6b05SZiyang Xuan 				  enum hinic_mod_type mod, u8 cmd, u16 prod_idx,
2817fcd6b05SZiyang Xuan 				  enum completion_format complete_format,
2827fcd6b05SZiyang Xuan 				  enum data_format local_data_format,
2837fcd6b05SZiyang Xuan 				  enum bufdesc_len buf_len)
2847fcd6b05SZiyang Xuan {
2857fcd6b05SZiyang Xuan 	struct hinic_ctrl *ctrl;
2867fcd6b05SZiyang Xuan 	enum ctrl_sect_len ctrl_len;
2877fcd6b05SZiyang Xuan 	struct hinic_cmdq_wqe_lcmd *wqe_lcmd;
2887fcd6b05SZiyang Xuan 	struct hinic_cmdq_wqe_scmd *wqe_scmd;
2897fcd6b05SZiyang Xuan 	u32 saved_data = WQE_HEADER(wqe)->saved_data;
2907fcd6b05SZiyang Xuan 
2917fcd6b05SZiyang Xuan 	if (local_data_format == DATA_SGE) {
2927fcd6b05SZiyang Xuan 		wqe_lcmd = &wqe->wqe_lcmd;
2937fcd6b05SZiyang Xuan 
2947fcd6b05SZiyang Xuan 		wqe_lcmd->status.status_info = 0;
2957fcd6b05SZiyang Xuan 		ctrl = &wqe_lcmd->ctrl;
2967fcd6b05SZiyang Xuan 		ctrl_len = CTRL_SECT_LEN;
2977fcd6b05SZiyang Xuan 	} else {
2987fcd6b05SZiyang Xuan 		wqe_scmd = &wqe->inline_wqe.wqe_scmd;
2997fcd6b05SZiyang Xuan 
3007fcd6b05SZiyang Xuan 		wqe_scmd->status.status_info = 0;
3017fcd6b05SZiyang Xuan 		ctrl = &wqe_scmd->ctrl;
3027fcd6b05SZiyang Xuan 		ctrl_len = CTRL_DIRECT_SECT_LEN;
3037fcd6b05SZiyang Xuan 	}
3047fcd6b05SZiyang Xuan 
3057fcd6b05SZiyang Xuan 	ctrl->ctrl_info = CMDQ_CTRL_SET(prod_idx, PI)		|
3067fcd6b05SZiyang Xuan 			CMDQ_CTRL_SET(cmd, CMD)			|
3077fcd6b05SZiyang Xuan 			CMDQ_CTRL_SET(mod, MOD)			|
3087fcd6b05SZiyang Xuan 			CMDQ_CTRL_SET(ack_type, ACK_TYPE);
3097fcd6b05SZiyang Xuan 
3107fcd6b05SZiyang Xuan 	WQE_HEADER(wqe)->header_info =
3117fcd6b05SZiyang Xuan 		CMDQ_WQE_HEADER_SET(buf_len, BUFDESC_LEN) |
3127fcd6b05SZiyang Xuan 		CMDQ_WQE_HEADER_SET(complete_format, COMPLETE_FMT) |
3137fcd6b05SZiyang Xuan 		CMDQ_WQE_HEADER_SET(local_data_format, DATA_FMT)	|
3147fcd6b05SZiyang Xuan 		CMDQ_WQE_HEADER_SET(CEQ_SET, COMPLETE_REQ)	|
3157fcd6b05SZiyang Xuan 		CMDQ_WQE_HEADER_SET(COMPLETE_LEN, COMPLETE_SECT_LEN) |
3167fcd6b05SZiyang Xuan 		CMDQ_WQE_HEADER_SET(ctrl_len, CTRL_LEN)		|
3177fcd6b05SZiyang Xuan 		CMDQ_WQE_HEADER_SET((u32)wrapped, HW_BUSY_BIT);
3187fcd6b05SZiyang Xuan 
3197fcd6b05SZiyang Xuan 	if (cmd == CMDQ_SET_ARM_CMD && mod == HINIC_MOD_COMM) {
3207fcd6b05SZiyang Xuan 		saved_data &= SAVED_DATA_CLEAR(saved_data, ARM);
3217fcd6b05SZiyang Xuan 		WQE_HEADER(wqe)->saved_data = saved_data |
3227fcd6b05SZiyang Xuan 						SAVED_DATA_SET(1, ARM);
3237fcd6b05SZiyang Xuan 	} else {
3247fcd6b05SZiyang Xuan 		saved_data &= SAVED_DATA_CLEAR(saved_data, ARM);
3257fcd6b05SZiyang Xuan 		WQE_HEADER(wqe)->saved_data = saved_data;
3267fcd6b05SZiyang Xuan 	}
3277fcd6b05SZiyang Xuan }
3287fcd6b05SZiyang Xuan 
cmdq_set_lcmd_wqe(struct hinic_cmdq_wqe * wqe,enum cmdq_cmd_type cmd_type,struct hinic_cmd_buf * buf_in,struct hinic_cmd_buf * buf_out,int wrapped,enum hinic_ack_type ack_type,enum hinic_mod_type mod,u8 cmd,u16 prod_idx)3297fcd6b05SZiyang Xuan static void cmdq_set_lcmd_wqe(struct hinic_cmdq_wqe *wqe,
3307fcd6b05SZiyang Xuan 			      enum cmdq_cmd_type cmd_type,
3317fcd6b05SZiyang Xuan 			      struct hinic_cmd_buf *buf_in,
3327fcd6b05SZiyang Xuan 			      struct hinic_cmd_buf *buf_out, int wrapped,
3337fcd6b05SZiyang Xuan 			      enum hinic_ack_type ack_type,
3347fcd6b05SZiyang Xuan 			      enum hinic_mod_type mod, u8 cmd, u16 prod_idx)
3357fcd6b05SZiyang Xuan {
3367fcd6b05SZiyang Xuan 	struct hinic_cmdq_wqe_lcmd *wqe_lcmd = &wqe->wqe_lcmd;
3377fcd6b05SZiyang Xuan 	enum completion_format complete_format = COMPLETE_DIRECT;
3387fcd6b05SZiyang Xuan 
3397fcd6b05SZiyang Xuan 	switch (cmd_type) {
3407fcd6b05SZiyang Xuan 	case SYNC_CMD_SGE_RESP:
3417fcd6b05SZiyang Xuan 		if (buf_out) {
3427fcd6b05SZiyang Xuan 			complete_format = COMPLETE_SGE;
3437fcd6b05SZiyang Xuan 			cmdq_set_completion(&wqe_lcmd->completion, buf_out);
3447fcd6b05SZiyang Xuan 		}
3457fcd6b05SZiyang Xuan 		break;
3467fcd6b05SZiyang Xuan 	case SYNC_CMD_DIRECT_RESP:
3477fcd6b05SZiyang Xuan 		complete_format = COMPLETE_DIRECT;
3487fcd6b05SZiyang Xuan 		wqe_lcmd->completion.direct_resp = 0;
3497fcd6b05SZiyang Xuan 		break;
3507fcd6b05SZiyang Xuan 	case ASYNC_CMD:
3517fcd6b05SZiyang Xuan 		complete_format = COMPLETE_DIRECT;
3527fcd6b05SZiyang Xuan 		wqe_lcmd->completion.direct_resp = 0;
3537fcd6b05SZiyang Xuan 
3547fcd6b05SZiyang Xuan 		wqe_lcmd->buf_desc.saved_async_buf = (u64)(buf_in);
3557fcd6b05SZiyang Xuan 		break;
3567fcd6b05SZiyang Xuan 	}
3577fcd6b05SZiyang Xuan 
3587fcd6b05SZiyang Xuan 	cmdq_prepare_wqe_ctrl(wqe, wrapped, ack_type, mod, cmd,
3597fcd6b05SZiyang Xuan 			      prod_idx, complete_format, DATA_SGE,
3607fcd6b05SZiyang Xuan 			      BUFDESC_LCMD_LEN);
3617fcd6b05SZiyang Xuan 
3627fcd6b05SZiyang Xuan 	cmdq_set_lcmd_bufdesc(wqe_lcmd, buf_in);
3637fcd6b05SZiyang Xuan }
3647fcd6b05SZiyang Xuan 
cmdq_params_valid(struct hinic_cmd_buf * buf_in)3657fcd6b05SZiyang Xuan static int cmdq_params_valid(struct hinic_cmd_buf *buf_in)
3667fcd6b05SZiyang Xuan {
3677fcd6b05SZiyang Xuan 	if (buf_in->size > HINIC_CMDQ_MAX_DATA_SIZE) {
3687fcd6b05SZiyang Xuan 		PMD_DRV_LOG(ERR, "Invalid CMDQ buffer size");
3697fcd6b05SZiyang Xuan 		return -EINVAL;
3707fcd6b05SZiyang Xuan 	}
3717fcd6b05SZiyang Xuan 
3727fcd6b05SZiyang Xuan 	return 0;
3737fcd6b05SZiyang Xuan }
3747fcd6b05SZiyang Xuan 
wait_cmdqs_enable(struct hinic_cmdqs * cmdqs)3757fcd6b05SZiyang Xuan static int wait_cmdqs_enable(struct hinic_cmdqs *cmdqs)
3767fcd6b05SZiyang Xuan {
3777fcd6b05SZiyang Xuan 	unsigned long end;
3787fcd6b05SZiyang Xuan 
3797fcd6b05SZiyang Xuan 	end = jiffies + msecs_to_jiffies(WAIT_CMDQ_ENABLE_TIMEOUT);
3807fcd6b05SZiyang Xuan 	do {
3817fcd6b05SZiyang Xuan 		if (cmdqs->status & HINIC_CMDQ_ENABLE)
3827fcd6b05SZiyang Xuan 			return 0;
3837fcd6b05SZiyang Xuan 
3847fcd6b05SZiyang Xuan 	} while (time_before(jiffies, end));
3857fcd6b05SZiyang Xuan 
3867fcd6b05SZiyang Xuan 	return -EBUSY;
3877fcd6b05SZiyang Xuan }
3887fcd6b05SZiyang Xuan 
cmdq_update_errcode(struct hinic_cmdq * cmdq,u16 prod_idx,int errcode)3897fcd6b05SZiyang Xuan static void cmdq_update_errcode(struct hinic_cmdq *cmdq, u16 prod_idx,
3907fcd6b05SZiyang Xuan 				int errcode)
3917fcd6b05SZiyang Xuan {
3927fcd6b05SZiyang Xuan 	cmdq->errcode[prod_idx] = errcode;
3937fcd6b05SZiyang Xuan }
3947fcd6b05SZiyang Xuan 
clear_wqe_complete_bit(struct hinic_cmdq * cmdq,struct hinic_cmdq_wqe * wqe)3957fcd6b05SZiyang Xuan static void clear_wqe_complete_bit(struct hinic_cmdq *cmdq,
3967fcd6b05SZiyang Xuan 				   struct hinic_cmdq_wqe *wqe)
3977fcd6b05SZiyang Xuan {
3987fcd6b05SZiyang Xuan 	struct hinic_cmdq_wqe_lcmd *wqe_lcmd;
3997fcd6b05SZiyang Xuan 	struct hinic_cmdq_inline_wqe *inline_wqe;
4007fcd6b05SZiyang Xuan 	struct hinic_cmdq_wqe_scmd *wqe_scmd;
4017fcd6b05SZiyang Xuan 	struct hinic_ctrl *ctrl;
4027fcd6b05SZiyang Xuan 	u32 header_info = be32_to_cpu(WQE_HEADER(wqe)->header_info);
4037fcd6b05SZiyang Xuan 	int buf_len = CMDQ_WQE_HEADER_GET(header_info, BUFDESC_LEN);
4047fcd6b05SZiyang Xuan 	int wqe_size = cmdq_get_wqe_size(buf_len);
4057fcd6b05SZiyang Xuan 	u16 num_wqebbs;
4067fcd6b05SZiyang Xuan 
4077fcd6b05SZiyang Xuan 	if (wqe_size == WQE_LCMD_SIZE) {
4087fcd6b05SZiyang Xuan 		wqe_lcmd = &wqe->wqe_lcmd;
4097fcd6b05SZiyang Xuan 		ctrl = &wqe_lcmd->ctrl;
4107fcd6b05SZiyang Xuan 	} else {
4117fcd6b05SZiyang Xuan 		inline_wqe = &wqe->inline_wqe;
4127fcd6b05SZiyang Xuan 		wqe_scmd = &inline_wqe->wqe_scmd;
4137fcd6b05SZiyang Xuan 		ctrl = &wqe_scmd->ctrl;
4147fcd6b05SZiyang Xuan 	}
4157fcd6b05SZiyang Xuan 
4167fcd6b05SZiyang Xuan 	/* clear HW busy bit */
4177fcd6b05SZiyang Xuan 	ctrl->ctrl_info = 0;
4187fcd6b05SZiyang Xuan 
4197fcd6b05SZiyang Xuan 	rte_wmb();	/* verify wqe is clear */
4207fcd6b05SZiyang Xuan 
4217fcd6b05SZiyang Xuan 	num_wqebbs = WQE_NUM_WQEBBS(wqe_size, cmdq->wq);
4227fcd6b05SZiyang Xuan 	hinic_put_wqe(cmdq->wq, num_wqebbs);
4237fcd6b05SZiyang Xuan }
4247fcd6b05SZiyang Xuan 
hinic_set_cmdq_ctxts(struct hinic_hwdev * hwdev)4257fcd6b05SZiyang Xuan static int hinic_set_cmdq_ctxts(struct hinic_hwdev *hwdev)
4267fcd6b05SZiyang Xuan {
4277fcd6b05SZiyang Xuan 	struct hinic_cmdqs *cmdqs = hwdev->cmdqs;
4287fcd6b05SZiyang Xuan 	struct hinic_cmdq_ctxt *cmdq_ctxt;
429*d807dd7dSXiaoyun Wang 	struct hinic_cmdq_ctxt cmdq_ctxt_out;
4307fcd6b05SZiyang Xuan 	enum hinic_cmdq_type cmdq_type;
431*d807dd7dSXiaoyun Wang 	u16 out_size = sizeof(cmdq_ctxt_out);
4327fcd6b05SZiyang Xuan 	u16 in_size;
4337fcd6b05SZiyang Xuan 	int err;
4347fcd6b05SZiyang Xuan 
4357fcd6b05SZiyang Xuan 	cmdq_type = HINIC_CMDQ_SYNC;
436*d807dd7dSXiaoyun Wang 	memset(&cmdq_ctxt_out, 0, out_size);
4377fcd6b05SZiyang Xuan 	for (; cmdq_type < HINIC_MAX_CMDQ_TYPES; cmdq_type++) {
4387fcd6b05SZiyang Xuan 		cmdq_ctxt = &cmdqs->cmdq[cmdq_type].cmdq_ctxt;
4397fcd6b05SZiyang Xuan 		cmdq_ctxt->resp_aeq_num = HINIC_AEQ1;
4407fcd6b05SZiyang Xuan 		in_size = sizeof(*cmdq_ctxt);
4417fcd6b05SZiyang Xuan 		err = hinic_msg_to_mgmt_sync(hwdev, HINIC_MOD_COMM,
4427fcd6b05SZiyang Xuan 					     HINIC_MGMT_CMD_CMDQ_CTXT_SET,
443*d807dd7dSXiaoyun Wang 					     cmdq_ctxt, in_size, &cmdq_ctxt_out,
444*d807dd7dSXiaoyun Wang 					     &out_size, 0);
445*d807dd7dSXiaoyun Wang 		if (err || !out_size || cmdq_ctxt_out.status) {
446036b61d8SXiaoyun Wang 			if (err == HINIC_MBOX_PF_BUSY_ACTIVE_FW ||
447036b61d8SXiaoyun Wang 				err == HINIC_DEV_BUSY_ACTIVE_FW) {
4480194313bSXiaoyun Wang 				cmdqs->status |= HINIC_CMDQ_SET_FAIL;
449036b61d8SXiaoyun Wang 				PMD_DRV_LOG(ERR, "PF or VF fw is hot active");
450036b61d8SXiaoyun Wang 			}
451*d807dd7dSXiaoyun Wang 			PMD_DRV_LOG(ERR, "Set cmdq ctxt failed, err: %d, status: 0x%x, out_size: 0x%x",
452*d807dd7dSXiaoyun Wang 				err, cmdq_ctxt_out.status, out_size);
453*d807dd7dSXiaoyun Wang 			return -EIO;
4547fcd6b05SZiyang Xuan 		}
4557fcd6b05SZiyang Xuan 	}
4567fcd6b05SZiyang Xuan 
4570194313bSXiaoyun Wang 	cmdqs->status &= ~HINIC_CMDQ_SET_FAIL;
4587fcd6b05SZiyang Xuan 	cmdqs->status |= HINIC_CMDQ_ENABLE;
4597fcd6b05SZiyang Xuan 
4607fcd6b05SZiyang Xuan 	return 0;
4617fcd6b05SZiyang Xuan }
4627fcd6b05SZiyang Xuan 
hinic_comm_cmdqs_free(struct hinic_hwdev * hwdev)4637fcd6b05SZiyang Xuan void hinic_comm_cmdqs_free(struct hinic_hwdev *hwdev)
4647fcd6b05SZiyang Xuan {
4657fcd6b05SZiyang Xuan 	hinic_cmdqs_free(hwdev);
4667fcd6b05SZiyang Xuan }
4677fcd6b05SZiyang Xuan 
hinic_reinit_cmdq_ctxts(struct hinic_hwdev * hwdev)4687fcd6b05SZiyang Xuan int hinic_reinit_cmdq_ctxts(struct hinic_hwdev *hwdev)
4697fcd6b05SZiyang Xuan {
4707fcd6b05SZiyang Xuan 	struct hinic_cmdqs *cmdqs = hwdev->cmdqs;
4717fcd6b05SZiyang Xuan 	enum hinic_cmdq_type cmdq_type;
4727fcd6b05SZiyang Xuan 
4737fcd6b05SZiyang Xuan 	cmdq_type = HINIC_CMDQ_SYNC;
4747fcd6b05SZiyang Xuan 	for (; cmdq_type < HINIC_MAX_CMDQ_TYPES; cmdq_type++) {
4757fcd6b05SZiyang Xuan 		cmdqs->cmdq[cmdq_type].wrapped = 1;
4767fcd6b05SZiyang Xuan 		hinic_wq_wqe_pg_clear(cmdqs->cmdq[cmdq_type].wq);
4777fcd6b05SZiyang Xuan 	}
4787fcd6b05SZiyang Xuan 
4797fcd6b05SZiyang Xuan 	return hinic_set_cmdq_ctxts(hwdev);
4807fcd6b05SZiyang Xuan }
4817fcd6b05SZiyang Xuan 
init_cmdq(struct hinic_cmdq * cmdq,struct hinic_hwdev * hwdev,struct hinic_wq * wq,enum hinic_cmdq_type q_type)4827fcd6b05SZiyang Xuan static int init_cmdq(struct hinic_cmdq *cmdq, struct hinic_hwdev *hwdev,
4837fcd6b05SZiyang Xuan 		     struct hinic_wq *wq, enum hinic_cmdq_type q_type)
4847fcd6b05SZiyang Xuan {
4857fcd6b05SZiyang Xuan 	void __iomem *db_base;
4867fcd6b05SZiyang Xuan 	int err = 0;
4877fcd6b05SZiyang Xuan 	size_t errcode_size;
4887fcd6b05SZiyang Xuan 	size_t cmd_infos_size;
4897fcd6b05SZiyang Xuan 
4907fcd6b05SZiyang Xuan 	cmdq->wq = wq;
4917fcd6b05SZiyang Xuan 	cmdq->cmdq_type = q_type;
4927fcd6b05SZiyang Xuan 	cmdq->wrapped = 1;
4937fcd6b05SZiyang Xuan 
4947fcd6b05SZiyang Xuan 	spin_lock_init(&cmdq->cmdq_lock);
4957fcd6b05SZiyang Xuan 
4967fcd6b05SZiyang Xuan 	errcode_size = wq->q_depth * sizeof(*cmdq->errcode);
4977fcd6b05SZiyang Xuan 	cmdq->errcode = kzalloc(errcode_size, GFP_KERNEL);
4987fcd6b05SZiyang Xuan 	if (!cmdq->errcode) {
4997fcd6b05SZiyang Xuan 		PMD_DRV_LOG(ERR, "Allocate errcode for cmdq failed");
5007fcd6b05SZiyang Xuan 		spin_lock_deinit(&cmdq->cmdq_lock);
5017fcd6b05SZiyang Xuan 		return -ENOMEM;
5027fcd6b05SZiyang Xuan 	}
5037fcd6b05SZiyang Xuan 
5047fcd6b05SZiyang Xuan 	cmd_infos_size = wq->q_depth * sizeof(*cmdq->cmd_infos);
5057fcd6b05SZiyang Xuan 	cmdq->cmd_infos = kzalloc(cmd_infos_size, GFP_KERNEL);
5067fcd6b05SZiyang Xuan 	if (!cmdq->cmd_infos) {
5077fcd6b05SZiyang Xuan 		PMD_DRV_LOG(ERR, "Allocate errcode for cmdq failed");
5087fcd6b05SZiyang Xuan 		err = -ENOMEM;
5097fcd6b05SZiyang Xuan 		goto cmd_infos_err;
5107fcd6b05SZiyang Xuan 	}
5117fcd6b05SZiyang Xuan 
5127fcd6b05SZiyang Xuan 	err = hinic_alloc_db_addr(hwdev, &db_base);
5137fcd6b05SZiyang Xuan 	if (err)
5147fcd6b05SZiyang Xuan 		goto alloc_db_err;
5157fcd6b05SZiyang Xuan 
5167fcd6b05SZiyang Xuan 	cmdq->db_base = (u8 *)db_base;
5177fcd6b05SZiyang Xuan 	return 0;
5187fcd6b05SZiyang Xuan 
5197fcd6b05SZiyang Xuan alloc_db_err:
5207fcd6b05SZiyang Xuan 	kfree(cmdq->cmd_infos);
5217fcd6b05SZiyang Xuan 
5227fcd6b05SZiyang Xuan cmd_infos_err:
5237fcd6b05SZiyang Xuan 	kfree(cmdq->errcode);
5247fcd6b05SZiyang Xuan 	spin_lock_deinit(&cmdq->cmdq_lock);
5257fcd6b05SZiyang Xuan 
5267fcd6b05SZiyang Xuan 	return err;
5277fcd6b05SZiyang Xuan }
5287fcd6b05SZiyang Xuan 
free_cmdq(struct hinic_hwdev * hwdev,struct hinic_cmdq * cmdq)5297fcd6b05SZiyang Xuan static void free_cmdq(struct hinic_hwdev *hwdev, struct hinic_cmdq *cmdq)
5307fcd6b05SZiyang Xuan {
5317fcd6b05SZiyang Xuan 	hinic_free_db_addr(hwdev, cmdq->db_base);
5327fcd6b05SZiyang Xuan 	kfree(cmdq->cmd_infos);
5337fcd6b05SZiyang Xuan 	kfree(cmdq->errcode);
5347fcd6b05SZiyang Xuan 	spin_lock_deinit(&cmdq->cmdq_lock);
5357fcd6b05SZiyang Xuan }
5367fcd6b05SZiyang Xuan 
hinic_cmdqs_init(struct hinic_hwdev * hwdev)5377fcd6b05SZiyang Xuan static int hinic_cmdqs_init(struct hinic_hwdev *hwdev)
5387fcd6b05SZiyang Xuan {
5397fcd6b05SZiyang Xuan 	struct hinic_cmdqs *cmdqs;
5407fcd6b05SZiyang Xuan 	struct hinic_cmdq_ctxt *cmdq_ctxt;
5417fcd6b05SZiyang Xuan 	enum hinic_cmdq_type type, cmdq_type;
5427fcd6b05SZiyang Xuan 	size_t saved_wqs_size;
5437fcd6b05SZiyang Xuan 	int err;
5447fcd6b05SZiyang Xuan 
5457fcd6b05SZiyang Xuan 	cmdqs = kzalloc(sizeof(*cmdqs), GFP_KERNEL);
5467fcd6b05SZiyang Xuan 	if (!cmdqs)
5477fcd6b05SZiyang Xuan 		return -ENOMEM;
5487fcd6b05SZiyang Xuan 
5497fcd6b05SZiyang Xuan 	hwdev->cmdqs = cmdqs;
5507fcd6b05SZiyang Xuan 	cmdqs->hwdev = hwdev;
5517fcd6b05SZiyang Xuan 
5527fcd6b05SZiyang Xuan 	saved_wqs_size = HINIC_MAX_CMDQ_TYPES * sizeof(struct hinic_wq);
5537fcd6b05SZiyang Xuan 	cmdqs->saved_wqs = kzalloc(saved_wqs_size, GFP_KERNEL);
5547fcd6b05SZiyang Xuan 	if (!cmdqs->saved_wqs) {
5557fcd6b05SZiyang Xuan 		PMD_DRV_LOG(ERR, "Allocate saved wqs failed");
5567fcd6b05SZiyang Xuan 		err = -ENOMEM;
5577fcd6b05SZiyang Xuan 		goto alloc_wqs_err;
5587fcd6b05SZiyang Xuan 	}
5597fcd6b05SZiyang Xuan 
5607fcd6b05SZiyang Xuan 	cmdqs->cmd_buf_pool = dma_pool_create("hinic_cmdq", hwdev,
5617fcd6b05SZiyang Xuan 					      HINIC_CMDQ_BUF_SIZE,
5627fcd6b05SZiyang Xuan 					      HINIC_CMDQ_BUF_SIZE, 0ULL);
5637fcd6b05SZiyang Xuan 	if (!cmdqs->cmd_buf_pool) {
5647fcd6b05SZiyang Xuan 		PMD_DRV_LOG(ERR, "Create cmdq buffer pool failed");
5657fcd6b05SZiyang Xuan 		err = -ENOMEM;
5667fcd6b05SZiyang Xuan 		goto pool_create_err;
5677fcd6b05SZiyang Xuan 	}
5687fcd6b05SZiyang Xuan 
5697fcd6b05SZiyang Xuan 	err = hinic_cmdq_alloc(cmdqs->saved_wqs, hwdev,
5707fcd6b05SZiyang Xuan 			       HINIC_MAX_CMDQ_TYPES, HINIC_CMDQ_WQ_BUF_SIZE,
5717fcd6b05SZiyang Xuan 			       CMDQ_WQEBB_SHIFT, HINIC_CMDQ_DEPTH);
5727fcd6b05SZiyang Xuan 	if (err) {
5737fcd6b05SZiyang Xuan 		PMD_DRV_LOG(ERR, "Allocate cmdq failed");
5747fcd6b05SZiyang Xuan 		goto cmdq_alloc_err;
5757fcd6b05SZiyang Xuan 	}
5767fcd6b05SZiyang Xuan 
5777fcd6b05SZiyang Xuan 	cmdq_type = HINIC_CMDQ_SYNC;
5787fcd6b05SZiyang Xuan 	for (; cmdq_type < HINIC_MAX_CMDQ_TYPES; cmdq_type++) {
5797fcd6b05SZiyang Xuan 		err = init_cmdq(&cmdqs->cmdq[cmdq_type], hwdev,
5807fcd6b05SZiyang Xuan 				&cmdqs->saved_wqs[cmdq_type], cmdq_type);
5817fcd6b05SZiyang Xuan 		if (err) {
5827fcd6b05SZiyang Xuan 			PMD_DRV_LOG(ERR, "Initialize cmdq failed");
5837fcd6b05SZiyang Xuan 			goto init_cmdq_err;
5847fcd6b05SZiyang Xuan 		}
5857fcd6b05SZiyang Xuan 
5867fcd6b05SZiyang Xuan 		cmdq_ctxt = &cmdqs->cmdq[cmdq_type].cmdq_ctxt;
5877fcd6b05SZiyang Xuan 		cmdq_init_queue_ctxt(&cmdqs->cmdq[cmdq_type], cmdq_ctxt);
5887fcd6b05SZiyang Xuan 	}
5897fcd6b05SZiyang Xuan 
5907fcd6b05SZiyang Xuan 	err = hinic_set_cmdq_ctxts(hwdev);
5917fcd6b05SZiyang Xuan 	if (err)
5927fcd6b05SZiyang Xuan 		goto init_cmdq_err;
5937fcd6b05SZiyang Xuan 
5947fcd6b05SZiyang Xuan 	return 0;
5957fcd6b05SZiyang Xuan 
5967fcd6b05SZiyang Xuan init_cmdq_err:
5977fcd6b05SZiyang Xuan 	type = HINIC_CMDQ_SYNC;
5987fcd6b05SZiyang Xuan 	for ( ; type < cmdq_type; type++)
5997fcd6b05SZiyang Xuan 		free_cmdq(hwdev, &cmdqs->cmdq[type]);
6007fcd6b05SZiyang Xuan 
6017fcd6b05SZiyang Xuan 	hinic_cmdq_free(hwdev, cmdqs->saved_wqs, HINIC_MAX_CMDQ_TYPES);
6027fcd6b05SZiyang Xuan 
6037fcd6b05SZiyang Xuan cmdq_alloc_err:
6047fcd6b05SZiyang Xuan 	dma_pool_destroy(cmdqs->cmd_buf_pool);
6057fcd6b05SZiyang Xuan 
6067fcd6b05SZiyang Xuan pool_create_err:
6077fcd6b05SZiyang Xuan 	kfree(cmdqs->saved_wqs);
6087fcd6b05SZiyang Xuan 
6097fcd6b05SZiyang Xuan alloc_wqs_err:
6107fcd6b05SZiyang Xuan 	kfree(cmdqs);
6117fcd6b05SZiyang Xuan 
6127fcd6b05SZiyang Xuan 	return err;
6137fcd6b05SZiyang Xuan }
6147fcd6b05SZiyang Xuan 
hinic_cmdqs_free(struct hinic_hwdev * hwdev)6157fcd6b05SZiyang Xuan static void hinic_cmdqs_free(struct hinic_hwdev *hwdev)
6167fcd6b05SZiyang Xuan {
6177fcd6b05SZiyang Xuan 	struct hinic_cmdqs *cmdqs = hwdev->cmdqs;
6187fcd6b05SZiyang Xuan 	enum hinic_cmdq_type cmdq_type = HINIC_CMDQ_SYNC;
6197fcd6b05SZiyang Xuan 
6207fcd6b05SZiyang Xuan 	cmdqs->status &= ~HINIC_CMDQ_ENABLE;
6217fcd6b05SZiyang Xuan 
6227fcd6b05SZiyang Xuan 	for ( ; cmdq_type < HINIC_MAX_CMDQ_TYPES; cmdq_type++)
6237fcd6b05SZiyang Xuan 		free_cmdq(cmdqs->hwdev, &cmdqs->cmdq[cmdq_type]);
6247fcd6b05SZiyang Xuan 
6257fcd6b05SZiyang Xuan 	hinic_cmdq_free(hwdev, cmdqs->saved_wqs,
6267fcd6b05SZiyang Xuan 			HINIC_MAX_CMDQ_TYPES);
6277fcd6b05SZiyang Xuan 
6287fcd6b05SZiyang Xuan 	dma_pool_destroy(cmdqs->cmd_buf_pool);
6297fcd6b05SZiyang Xuan 
6307fcd6b05SZiyang Xuan 	kfree(cmdqs->saved_wqs);
6317fcd6b05SZiyang Xuan 
6327fcd6b05SZiyang Xuan 	kfree(cmdqs);
6337fcd6b05SZiyang Xuan }
6347fcd6b05SZiyang Xuan 
hinic_set_cmdq_depth(struct hinic_hwdev * hwdev,u16 cmdq_depth)6357fcd6b05SZiyang Xuan static int hinic_set_cmdq_depth(struct hinic_hwdev *hwdev, u16 cmdq_depth)
6367fcd6b05SZiyang Xuan {
6377fcd6b05SZiyang Xuan 	struct hinic_root_ctxt root_ctxt;
638*d807dd7dSXiaoyun Wang 	u16 out_size = sizeof(root_ctxt);
639*d807dd7dSXiaoyun Wang 	int err;
6407fcd6b05SZiyang Xuan 
6417fcd6b05SZiyang Xuan 	memset(&root_ctxt, 0, sizeof(root_ctxt));
6427fcd6b05SZiyang Xuan 	root_ctxt.mgmt_msg_head.resp_aeq_num = HINIC_AEQ1;
6437fcd6b05SZiyang Xuan 	root_ctxt.func_idx = hinic_global_func_id(hwdev);
6447fcd6b05SZiyang Xuan 	root_ctxt.ppf_idx = hinic_ppf_idx(hwdev);
6457fcd6b05SZiyang Xuan 	root_ctxt.set_cmdq_depth = 1;
6467fcd6b05SZiyang Xuan 	root_ctxt.cmdq_depth = (u8)ilog2(cmdq_depth);
647*d807dd7dSXiaoyun Wang 	err = hinic_msg_to_mgmt_sync(hwdev, HINIC_MOD_COMM,
6487fcd6b05SZiyang Xuan 				     HINIC_MGMT_CMD_VAT_SET,
6497fcd6b05SZiyang Xuan 				     &root_ctxt, sizeof(root_ctxt),
650*d807dd7dSXiaoyun Wang 				     &root_ctxt, &out_size, 0);
651*d807dd7dSXiaoyun Wang 	if (err || !out_size || root_ctxt.mgmt_msg_head.status) {
652*d807dd7dSXiaoyun Wang 		PMD_DRV_LOG(ERR, "Set cmdq depth failed, err: %d, status: 0x%x, out_size: 0x%x",
653*d807dd7dSXiaoyun Wang 			err, root_ctxt.mgmt_msg_head.status, out_size);
654*d807dd7dSXiaoyun Wang 		return -EIO;
655*d807dd7dSXiaoyun Wang 	}
656*d807dd7dSXiaoyun Wang 
657*d807dd7dSXiaoyun Wang 	return 0;
6587fcd6b05SZiyang Xuan }
6597fcd6b05SZiyang Xuan 
hinic_comm_cmdqs_init(struct hinic_hwdev * hwdev)6607fcd6b05SZiyang Xuan int hinic_comm_cmdqs_init(struct hinic_hwdev *hwdev)
6617fcd6b05SZiyang Xuan {
6627fcd6b05SZiyang Xuan 	int err;
6637fcd6b05SZiyang Xuan 
6647fcd6b05SZiyang Xuan 	err = hinic_cmdqs_init(hwdev);
6657fcd6b05SZiyang Xuan 	if (err) {
6667fcd6b05SZiyang Xuan 		PMD_DRV_LOG(ERR, "Init cmd queues failed");
6677fcd6b05SZiyang Xuan 		return err;
6687fcd6b05SZiyang Xuan 	}
6697fcd6b05SZiyang Xuan 
6707fcd6b05SZiyang Xuan 	err = hinic_set_cmdq_depth(hwdev, HINIC_CMDQ_DEPTH);
6717fcd6b05SZiyang Xuan 	if (err) {
6727fcd6b05SZiyang Xuan 		PMD_DRV_LOG(ERR, "Set cmdq depth failed");
6737fcd6b05SZiyang Xuan 		goto set_cmdq_depth_err;
6747fcd6b05SZiyang Xuan 	}
6757fcd6b05SZiyang Xuan 
6767fcd6b05SZiyang Xuan 	return 0;
6777fcd6b05SZiyang Xuan 
6787fcd6b05SZiyang Xuan set_cmdq_depth_err:
6797fcd6b05SZiyang Xuan 	hinic_cmdqs_free(hwdev);
6807fcd6b05SZiyang Xuan 
6817fcd6b05SZiyang Xuan 	return err;
6827fcd6b05SZiyang Xuan }
6837fcd6b05SZiyang Xuan 
cmdq_init_queue_ctxt(struct hinic_cmdq * cmdq,struct hinic_cmdq_ctxt * cmdq_ctxt)6847fcd6b05SZiyang Xuan static void cmdq_init_queue_ctxt(struct hinic_cmdq *cmdq,
6857fcd6b05SZiyang Xuan 				 struct hinic_cmdq_ctxt *cmdq_ctxt)
6867fcd6b05SZiyang Xuan {
6877fcd6b05SZiyang Xuan 	struct hinic_cmdqs *cmdqs = (struct hinic_cmdqs *)cmdq_to_cmdqs(cmdq);
6887fcd6b05SZiyang Xuan 	struct hinic_hwdev *hwdev = cmdqs->hwdev;
6897fcd6b05SZiyang Xuan 	struct hinic_wq *wq = cmdq->wq;
6907fcd6b05SZiyang Xuan 	struct hinic_cmdq_ctxt_info *ctxt_info = &cmdq_ctxt->ctxt_info;
6917fcd6b05SZiyang Xuan 	u64 wq_first_page_paddr, pfn;
6927fcd6b05SZiyang Xuan 
6937fcd6b05SZiyang Xuan 	u16 start_ci = (u16)(wq->cons_idx);
6947fcd6b05SZiyang Xuan 
6957fcd6b05SZiyang Xuan 	/* The data in the HW is in Big Endian Format */
6967fcd6b05SZiyang Xuan 	wq_first_page_paddr = wq->queue_buf_paddr;
6977fcd6b05SZiyang Xuan 
6987fcd6b05SZiyang Xuan 	pfn = CMDQ_PFN(wq_first_page_paddr, HINIC_PAGE_SIZE);
6997fcd6b05SZiyang Xuan 	ctxt_info->curr_wqe_page_pfn =
7007fcd6b05SZiyang Xuan 		CMDQ_CTXT_PAGE_INFO_SET(1, HW_BUSY_BIT) |
7017fcd6b05SZiyang Xuan 		CMDQ_CTXT_PAGE_INFO_SET(1, CEQ_EN)	|
7027fcd6b05SZiyang Xuan 		CMDQ_CTXT_PAGE_INFO_SET(0, CEQ_ARM)	|
7037fcd6b05SZiyang Xuan 		CMDQ_CTXT_PAGE_INFO_SET(HINIC_CEQ_ID_CMDQ, EQ_ID) |
7047fcd6b05SZiyang Xuan 		CMDQ_CTXT_PAGE_INFO_SET(pfn, CURR_WQE_PAGE_PFN);
7057fcd6b05SZiyang Xuan 
7067fcd6b05SZiyang Xuan 	ctxt_info->wq_block_pfn = CMDQ_CTXT_BLOCK_INFO_SET(start_ci, CI) |
7077fcd6b05SZiyang Xuan 				CMDQ_CTXT_BLOCK_INFO_SET(pfn, WQ_BLOCK_PFN);
7087fcd6b05SZiyang Xuan 	cmdq_ctxt->func_idx = HINIC_HWIF_GLOBAL_IDX(hwdev->hwif);
7097fcd6b05SZiyang Xuan 	cmdq_ctxt->ppf_idx  = HINIC_HWIF_PPF_IDX(hwdev->hwif);
7107fcd6b05SZiyang Xuan 	cmdq_ctxt->cmdq_id  = cmdq->cmdq_type;
7117fcd6b05SZiyang Xuan }
7127fcd6b05SZiyang Xuan 
hinic_cmdq_poll_msg(struct hinic_cmdq * cmdq,u32 timeout)7137fcd6b05SZiyang Xuan static int hinic_cmdq_poll_msg(struct hinic_cmdq *cmdq, u32 timeout)
7147fcd6b05SZiyang Xuan {
7157fcd6b05SZiyang Xuan 	struct hinic_cmdq_wqe *wqe;
7167fcd6b05SZiyang Xuan 	struct hinic_cmdq_wqe_lcmd *wqe_lcmd;
7177fcd6b05SZiyang Xuan 	struct hinic_ctrl *ctrl;
7187fcd6b05SZiyang Xuan 	struct hinic_cmdq_cmd_info *cmd_info;
7197fcd6b05SZiyang Xuan 	u32 status_info, ctrl_info;
7207fcd6b05SZiyang Xuan 	u16 ci;
7217fcd6b05SZiyang Xuan 	int errcode;
7227fcd6b05SZiyang Xuan 	unsigned long end;
7237fcd6b05SZiyang Xuan 	int done = 0;
7247fcd6b05SZiyang Xuan 	int rc = 0;
7257fcd6b05SZiyang Xuan 
7267fcd6b05SZiyang Xuan 	wqe = hinic_read_wqe(cmdq->wq, 1, &ci);
7277fcd6b05SZiyang Xuan 	if (wqe == NULL) {
7287fcd6b05SZiyang Xuan 		PMD_DRV_LOG(ERR, "No outstanding cmdq msg");
7297fcd6b05SZiyang Xuan 		return -EINVAL;
7307fcd6b05SZiyang Xuan 	}
7317fcd6b05SZiyang Xuan 
7327fcd6b05SZiyang Xuan 	cmd_info = &cmdq->cmd_infos[ci];
7337fcd6b05SZiyang Xuan 	/* this cmd has not been filled and send to hw, or get TMO msg ack*/
7347fcd6b05SZiyang Xuan 	if (cmd_info->cmd_type == HINIC_CMD_TYPE_NONE) {
7357fcd6b05SZiyang Xuan 		PMD_DRV_LOG(ERR, "Cmdq msg has not been filled and send to hw, or get TMO msg ack. cmdq ci: %u",
7367fcd6b05SZiyang Xuan 			    ci);
7377fcd6b05SZiyang Xuan 		return -EINVAL;
7387fcd6b05SZiyang Xuan 	}
7397fcd6b05SZiyang Xuan 
7407fcd6b05SZiyang Xuan 	/* only arm bit is using scmd wqe, the wqe is lcmd */
7417fcd6b05SZiyang Xuan 	wqe_lcmd = &wqe->wqe_lcmd;
7427fcd6b05SZiyang Xuan 	ctrl = &wqe_lcmd->ctrl;
7437fcd6b05SZiyang Xuan 	end = jiffies + msecs_to_jiffies(timeout);
7447fcd6b05SZiyang Xuan 	do {
7457fcd6b05SZiyang Xuan 		ctrl_info = be32_to_cpu((ctrl)->ctrl_info);
7467fcd6b05SZiyang Xuan 		if (WQE_COMPLETED(ctrl_info)) {
7477fcd6b05SZiyang Xuan 			done = 1;
7487fcd6b05SZiyang Xuan 			break;
7497fcd6b05SZiyang Xuan 		}
7507fcd6b05SZiyang Xuan 
7517fcd6b05SZiyang Xuan 		rte_delay_ms(1);
7527fcd6b05SZiyang Xuan 	} while (time_before(jiffies, end));
7537fcd6b05SZiyang Xuan 
7547fcd6b05SZiyang Xuan 	if (done) {
7557fcd6b05SZiyang Xuan 		status_info = be32_to_cpu(wqe_lcmd->status.status_info);
7567fcd6b05SZiyang Xuan 		errcode = WQE_ERRCODE_GET(status_info, VAL);
7577fcd6b05SZiyang Xuan 		cmdq_update_errcode(cmdq, ci, errcode);
7587fcd6b05SZiyang Xuan 		clear_wqe_complete_bit(cmdq, wqe);
7597fcd6b05SZiyang Xuan 		rc = 0;
7607fcd6b05SZiyang Xuan 	} else {
7617fcd6b05SZiyang Xuan 		PMD_DRV_LOG(ERR, "Poll cmdq msg time out, ci: %u", ci);
7627fcd6b05SZiyang Xuan 		rc = -ETIMEDOUT;
7637fcd6b05SZiyang Xuan 	}
7647fcd6b05SZiyang Xuan 
7657fcd6b05SZiyang Xuan 	/* set this cmd invalid */
7667fcd6b05SZiyang Xuan 	cmd_info->cmd_type = HINIC_CMD_TYPE_NONE;
7677fcd6b05SZiyang Xuan 
7687fcd6b05SZiyang Xuan 	return rc;
7697fcd6b05SZiyang Xuan }
7707fcd6b05SZiyang Xuan 
cmdq_sync_cmd_direct_resp(struct hinic_cmdq * cmdq,enum hinic_ack_type ack_type,enum hinic_mod_type mod,u8 cmd,struct hinic_cmd_buf * buf_in,u64 * out_param,u32 timeout)7717fcd6b05SZiyang Xuan static int cmdq_sync_cmd_direct_resp(struct hinic_cmdq *cmdq,
7727fcd6b05SZiyang Xuan 				     enum hinic_ack_type ack_type,
7737fcd6b05SZiyang Xuan 				     enum hinic_mod_type mod, u8 cmd,
7747fcd6b05SZiyang Xuan 				     struct hinic_cmd_buf *buf_in,
7757fcd6b05SZiyang Xuan 				     u64 *out_param, u32 timeout)
7767fcd6b05SZiyang Xuan {
7777fcd6b05SZiyang Xuan 	struct hinic_wq *wq = cmdq->wq;
7787fcd6b05SZiyang Xuan 	struct hinic_cmdq_wqe *curr_wqe, wqe;
7797fcd6b05SZiyang Xuan 	struct hinic_cmdq_wqe_lcmd *wqe_lcmd;
7807fcd6b05SZiyang Xuan 	u16 curr_prod_idx, next_prod_idx, num_wqebbs;
7817fcd6b05SZiyang Xuan 	int wrapped;
7827fcd6b05SZiyang Xuan 	u32 timeo, wqe_size;
7837fcd6b05SZiyang Xuan 	int err;
7847fcd6b05SZiyang Xuan 
7857fcd6b05SZiyang Xuan 	wqe_size = cmdq_wqe_size(WQE_LCMD_TYPE);
7867fcd6b05SZiyang Xuan 	num_wqebbs = WQE_NUM_WQEBBS(wqe_size, wq);
7877fcd6b05SZiyang Xuan 
7887fcd6b05SZiyang Xuan 	/* Keep wrapped and doorbell index correct. */
7897fcd6b05SZiyang Xuan 	spin_lock(&cmdq->cmdq_lock);
7907fcd6b05SZiyang Xuan 
7917fcd6b05SZiyang Xuan 	curr_wqe = hinic_get_wqe(cmdq->wq, num_wqebbs, &curr_prod_idx);
7927fcd6b05SZiyang Xuan 	if (!curr_wqe) {
7937fcd6b05SZiyang Xuan 		err = -EBUSY;
7947fcd6b05SZiyang Xuan 		goto cmdq_unlock;
7957fcd6b05SZiyang Xuan 	}
7967fcd6b05SZiyang Xuan 
7977fcd6b05SZiyang Xuan 	memset(&wqe, 0, sizeof(wqe));
7987fcd6b05SZiyang Xuan 	wrapped = cmdq->wrapped;
7997fcd6b05SZiyang Xuan 
8007fcd6b05SZiyang Xuan 	next_prod_idx = curr_prod_idx + num_wqebbs;
8017fcd6b05SZiyang Xuan 	if (next_prod_idx >= wq->q_depth) {
8027fcd6b05SZiyang Xuan 		cmdq->wrapped = !cmdq->wrapped;
8037fcd6b05SZiyang Xuan 		next_prod_idx -= wq->q_depth;
8047fcd6b05SZiyang Xuan 	}
8057fcd6b05SZiyang Xuan 
8067fcd6b05SZiyang Xuan 	cmdq_set_lcmd_wqe(&wqe, SYNC_CMD_DIRECT_RESP, buf_in, NULL,
8077fcd6b05SZiyang Xuan 			  wrapped, ack_type, mod, cmd, curr_prod_idx);
8087fcd6b05SZiyang Xuan 
8097fcd6b05SZiyang Xuan 	/* The data that is written to HW should be in Big Endian Format */
8107fcd6b05SZiyang Xuan 	hinic_cpu_to_be32(&wqe, wqe_size);
8117fcd6b05SZiyang Xuan 
8127fcd6b05SZiyang Xuan 	/* CMDQ WQE is not shadow, therefore wqe will be written to wq */
8137fcd6b05SZiyang Xuan 	cmdq_wqe_fill(curr_wqe, &wqe);
8147fcd6b05SZiyang Xuan 
8157fcd6b05SZiyang Xuan 	cmdq->cmd_infos[curr_prod_idx].cmd_type = HINIC_CMD_TYPE_NORMAL;
8167fcd6b05SZiyang Xuan 
8177fcd6b05SZiyang Xuan 	cmdq_set_db(cmdq, HINIC_CMDQ_SYNC, next_prod_idx);
8187fcd6b05SZiyang Xuan 
8197fcd6b05SZiyang Xuan 	timeo = msecs_to_jiffies(timeout ? timeout : CMDQ_CMD_TIMEOUT);
8207fcd6b05SZiyang Xuan 	err = hinic_cmdq_poll_msg(cmdq, timeo);
8217fcd6b05SZiyang Xuan 	if (err) {
8227fcd6b05SZiyang Xuan 		PMD_DRV_LOG(ERR, "Cmdq poll msg ack failed, prod idx: 0x%x",
8237fcd6b05SZiyang Xuan 			curr_prod_idx);
8247fcd6b05SZiyang Xuan 		err = -ETIMEDOUT;
8257fcd6b05SZiyang Xuan 		goto cmdq_unlock;
8267fcd6b05SZiyang Xuan 	}
8277fcd6b05SZiyang Xuan 
8287fcd6b05SZiyang Xuan 	rte_smp_rmb();	/* read error code after completion */
8297fcd6b05SZiyang Xuan 
8307fcd6b05SZiyang Xuan 	if (out_param) {
8317fcd6b05SZiyang Xuan 		wqe_lcmd = &curr_wqe->wqe_lcmd;
8327fcd6b05SZiyang Xuan 		*out_param = cpu_to_be64(wqe_lcmd->completion.direct_resp);
8337fcd6b05SZiyang Xuan 	}
8347fcd6b05SZiyang Xuan 
8357fcd6b05SZiyang Xuan 	if (cmdq->errcode[curr_prod_idx] > 1) {
8367fcd6b05SZiyang Xuan 		err = cmdq->errcode[curr_prod_idx];
8377fcd6b05SZiyang Xuan 		goto cmdq_unlock;
8387fcd6b05SZiyang Xuan 	}
8397fcd6b05SZiyang Xuan 
8407fcd6b05SZiyang Xuan cmdq_unlock:
8417fcd6b05SZiyang Xuan 	spin_unlock(&cmdq->cmdq_lock);
8427fcd6b05SZiyang Xuan 
8437fcd6b05SZiyang Xuan 	return err;
8447fcd6b05SZiyang Xuan }
8457fcd6b05SZiyang Xuan 
hinic_cmdq_direct_resp(void * hwdev,enum hinic_ack_type ack_type,enum hinic_mod_type mod,u8 cmd,struct hinic_cmd_buf * buf_in,u64 * out_param,u32 timeout)8467fcd6b05SZiyang Xuan int hinic_cmdq_direct_resp(void *hwdev, enum hinic_ack_type ack_type,
8477fcd6b05SZiyang Xuan 			   enum hinic_mod_type mod, u8 cmd,
8487fcd6b05SZiyang Xuan 			   struct hinic_cmd_buf *buf_in,
8497fcd6b05SZiyang Xuan 			   u64 *out_param, u32 timeout)
8507fcd6b05SZiyang Xuan {
8517fcd6b05SZiyang Xuan 	struct hinic_cmdqs *cmdqs = ((struct hinic_hwdev *)hwdev)->cmdqs;
8527fcd6b05SZiyang Xuan 	int err = cmdq_params_valid(buf_in);
8537fcd6b05SZiyang Xuan 
8547fcd6b05SZiyang Xuan 	if (err) {
8557fcd6b05SZiyang Xuan 		PMD_DRV_LOG(ERR, "Invalid CMDQ parameters");
8567fcd6b05SZiyang Xuan 		return err;
8577fcd6b05SZiyang Xuan 	}
8587fcd6b05SZiyang Xuan 
8597fcd6b05SZiyang Xuan 	err = wait_cmdqs_enable(cmdqs);
8607fcd6b05SZiyang Xuan 	if (err) {
8617fcd6b05SZiyang Xuan 		PMD_DRV_LOG(ERR, "Cmdq is disable");
8627fcd6b05SZiyang Xuan 		return err;
8637fcd6b05SZiyang Xuan 	}
8647fcd6b05SZiyang Xuan 
8657fcd6b05SZiyang Xuan 	return cmdq_sync_cmd_direct_resp(&cmdqs->cmdq[HINIC_CMDQ_SYNC],
8667fcd6b05SZiyang Xuan 					 ack_type, mod, cmd, buf_in,
8677fcd6b05SZiyang Xuan 					 out_param, timeout);
8687fcd6b05SZiyang Xuan }
869