xref: /linux/drivers/net/ethernet/huawei/hinic3/hinic3_cmdq.c (revision db03a1ced61c4b9297996c67cc4b8ade9fdb7cd1)
1*db03a1ceSFan Gong // SPDX-License-Identifier: GPL-2.0
2*db03a1ceSFan Gong // Copyright (c) Huawei Technologies Co., Ltd. 2025. All rights reserved.
3*db03a1ceSFan Gong 
4*db03a1ceSFan Gong #include <linux/bitfield.h>
5*db03a1ceSFan Gong #include <linux/dma-mapping.h>
6*db03a1ceSFan Gong 
7*db03a1ceSFan Gong #include "hinic3_cmdq.h"
8*db03a1ceSFan Gong #include "hinic3_hwdev.h"
9*db03a1ceSFan Gong #include "hinic3_hwif.h"
10*db03a1ceSFan Gong #include "hinic3_mbox.h"
11*db03a1ceSFan Gong 
12*db03a1ceSFan Gong #define CMDQ_BUF_SIZE             2048
13*db03a1ceSFan Gong #define CMDQ_WQEBB_SIZE           64
14*db03a1ceSFan Gong 
15*db03a1ceSFan Gong #define CMDQ_CTXT_CURR_WQE_PAGE_PFN_MASK  GENMASK_ULL(51, 0)
16*db03a1ceSFan Gong #define CMDQ_CTXT_EQ_ID_MASK              GENMASK_ULL(60, 53)
17*db03a1ceSFan Gong #define CMDQ_CTXT_CEQ_ARM_MASK            BIT_ULL(61)
18*db03a1ceSFan Gong #define CMDQ_CTXT_CEQ_EN_MASK             BIT_ULL(62)
19*db03a1ceSFan Gong #define CMDQ_CTXT_HW_BUSY_BIT_MASK        BIT_ULL(63)
20*db03a1ceSFan Gong 
21*db03a1ceSFan Gong #define CMDQ_CTXT_WQ_BLOCK_PFN_MASK       GENMASK_ULL(51, 0)
22*db03a1ceSFan Gong #define CMDQ_CTXT_CI_MASK                 GENMASK_ULL(63, 52)
23*db03a1ceSFan Gong #define CMDQ_CTXT_SET(val, member)  \
24*db03a1ceSFan Gong 	FIELD_PREP(CMDQ_CTXT_##member##_MASK, val)
25*db03a1ceSFan Gong 
26*db03a1ceSFan Gong #define CMDQ_PFN(addr)  ((addr) >> 12)
27*db03a1ceSFan Gong 
28*db03a1ceSFan Gong /* cmdq work queue's chip logical address table is up to 512B */
29*db03a1ceSFan Gong #define CMDQ_WQ_CLA_SIZE  512
30*db03a1ceSFan Gong 
31*db03a1ceSFan Gong /* Completion codes: send, direct sync, force stop */
32*db03a1ceSFan Gong #define CMDQ_SEND_CMPT_CODE         10
33*db03a1ceSFan Gong #define CMDQ_DIRECT_SYNC_CMPT_CODE  11
34*db03a1ceSFan Gong #define CMDQ_FORCE_STOP_CMPT_CODE   12
35*db03a1ceSFan Gong 
36*db03a1ceSFan Gong #define CMDQ_WQE_NUM_WQEBBS  1
37*db03a1ceSFan Gong 
38*db03a1ceSFan Gong static struct cmdq_wqe *cmdq_read_wqe(struct hinic3_wq *wq, u16 *ci)
39*db03a1ceSFan Gong {
40*db03a1ceSFan Gong 	if (hinic3_wq_get_used(wq) == 0)
41*db03a1ceSFan Gong 		return NULL;
42*db03a1ceSFan Gong 
43*db03a1ceSFan Gong 	*ci = wq->cons_idx & wq->idx_mask;
44*db03a1ceSFan Gong 
45*db03a1ceSFan Gong 	return get_q_element(&wq->qpages, wq->cons_idx, NULL);
46*db03a1ceSFan Gong }
47*db03a1ceSFan Gong 
48*db03a1ceSFan Gong void hinic3_free_cmd_buf(struct hinic3_hwdev *hwdev,
49*db03a1ceSFan Gong 			 struct hinic3_cmd_buf *cmd_buf)
50*db03a1ceSFan Gong {
51*db03a1ceSFan Gong 	struct hinic3_cmdqs *cmdqs;
52*db03a1ceSFan Gong 
53*db03a1ceSFan Gong 	if (!refcount_dec_and_test(&cmd_buf->ref_cnt))
54*db03a1ceSFan Gong 		return;
55*db03a1ceSFan Gong 
56*db03a1ceSFan Gong 	cmdqs = hwdev->cmdqs;
57*db03a1ceSFan Gong 
58*db03a1ceSFan Gong 	dma_pool_free(cmdqs->cmd_buf_pool, cmd_buf->buf, cmd_buf->dma_addr);
59*db03a1ceSFan Gong 	kfree(cmd_buf);
60*db03a1ceSFan Gong }
61*db03a1ceSFan Gong 
62*db03a1ceSFan Gong static void cmdq_clear_cmd_buf(struct hinic3_cmdq_cmd_info *cmd_info,
63*db03a1ceSFan Gong 			       struct hinic3_hwdev *hwdev)
64*db03a1ceSFan Gong {
65*db03a1ceSFan Gong 	if (cmd_info->buf_in) {
66*db03a1ceSFan Gong 		hinic3_free_cmd_buf(hwdev, cmd_info->buf_in);
67*db03a1ceSFan Gong 		cmd_info->buf_in = NULL;
68*db03a1ceSFan Gong 	}
69*db03a1ceSFan Gong }
70*db03a1ceSFan Gong 
71*db03a1ceSFan Gong static void cmdq_init_queue_ctxt(struct hinic3_hwdev *hwdev, u8 cmdq_id,
72*db03a1ceSFan Gong 				 struct comm_cmdq_ctxt_info *ctxt_info)
73*db03a1ceSFan Gong {
74*db03a1ceSFan Gong 	const struct hinic3_cmdqs *cmdqs;
75*db03a1ceSFan Gong 	u64 cmdq_first_block_paddr, pfn;
76*db03a1ceSFan Gong 	const struct hinic3_wq *wq;
77*db03a1ceSFan Gong 
78*db03a1ceSFan Gong 	cmdqs = hwdev->cmdqs;
79*db03a1ceSFan Gong 	wq = &cmdqs->cmdq[cmdq_id].wq;
80*db03a1ceSFan Gong 	pfn = CMDQ_PFN(hinic3_wq_get_first_wqe_page_addr(wq));
81*db03a1ceSFan Gong 
82*db03a1ceSFan Gong 	ctxt_info->curr_wqe_page_pfn =
83*db03a1ceSFan Gong 		cpu_to_le64(CMDQ_CTXT_SET(1, HW_BUSY_BIT) |
84*db03a1ceSFan Gong 			    CMDQ_CTXT_SET(1, CEQ_EN)	|
85*db03a1ceSFan Gong 			    CMDQ_CTXT_SET(1, CEQ_ARM)	|
86*db03a1ceSFan Gong 			    CMDQ_CTXT_SET(0, EQ_ID) |
87*db03a1ceSFan Gong 			    CMDQ_CTXT_SET(pfn, CURR_WQE_PAGE_PFN));
88*db03a1ceSFan Gong 
89*db03a1ceSFan Gong 	if (!hinic3_wq_is_0_level_cla(wq)) {
90*db03a1ceSFan Gong 		cmdq_first_block_paddr = cmdqs->wq_block_paddr;
91*db03a1ceSFan Gong 		pfn = CMDQ_PFN(cmdq_first_block_paddr);
92*db03a1ceSFan Gong 	}
93*db03a1ceSFan Gong 
94*db03a1ceSFan Gong 	ctxt_info->wq_block_pfn = cpu_to_le64(CMDQ_CTXT_SET(wq->cons_idx, CI) |
95*db03a1ceSFan Gong 					      CMDQ_CTXT_SET(pfn, WQ_BLOCK_PFN));
96*db03a1ceSFan Gong }
97*db03a1ceSFan Gong 
98*db03a1ceSFan Gong static int init_cmdq(struct hinic3_cmdq *cmdq, struct hinic3_hwdev *hwdev,
99*db03a1ceSFan Gong 		     enum hinic3_cmdq_type q_type)
100*db03a1ceSFan Gong {
101*db03a1ceSFan Gong 	int err;
102*db03a1ceSFan Gong 
103*db03a1ceSFan Gong 	cmdq->cmdq_type = q_type;
104*db03a1ceSFan Gong 	cmdq->wrapped = 1;
105*db03a1ceSFan Gong 	cmdq->hwdev = hwdev;
106*db03a1ceSFan Gong 
107*db03a1ceSFan Gong 	spin_lock_init(&cmdq->cmdq_lock);
108*db03a1ceSFan Gong 
109*db03a1ceSFan Gong 	cmdq->cmd_infos = kcalloc(cmdq->wq.q_depth, sizeof(*cmdq->cmd_infos),
110*db03a1ceSFan Gong 				  GFP_KERNEL);
111*db03a1ceSFan Gong 	if (!cmdq->cmd_infos) {
112*db03a1ceSFan Gong 		err = -ENOMEM;
113*db03a1ceSFan Gong 		return err;
114*db03a1ceSFan Gong 	}
115*db03a1ceSFan Gong 
116*db03a1ceSFan Gong 	return 0;
117*db03a1ceSFan Gong }
118*db03a1ceSFan Gong 
119*db03a1ceSFan Gong static int hinic3_set_cmdq_ctxt(struct hinic3_hwdev *hwdev, u8 cmdq_id)
120*db03a1ceSFan Gong {
121*db03a1ceSFan Gong 	struct comm_cmd_set_cmdq_ctxt cmdq_ctxt = {};
122*db03a1ceSFan Gong 	struct mgmt_msg_params msg_params = {};
123*db03a1ceSFan Gong 	int err;
124*db03a1ceSFan Gong 
125*db03a1ceSFan Gong 	cmdq_init_queue_ctxt(hwdev, cmdq_id, &cmdq_ctxt.ctxt);
126*db03a1ceSFan Gong 	cmdq_ctxt.func_id = hinic3_global_func_id(hwdev);
127*db03a1ceSFan Gong 	cmdq_ctxt.cmdq_id = cmdq_id;
128*db03a1ceSFan Gong 
129*db03a1ceSFan Gong 	mgmt_msg_params_init_default(&msg_params, &cmdq_ctxt,
130*db03a1ceSFan Gong 				     sizeof(cmdq_ctxt));
131*db03a1ceSFan Gong 
132*db03a1ceSFan Gong 	err = hinic3_send_mbox_to_mgmt(hwdev, MGMT_MOD_COMM,
133*db03a1ceSFan Gong 				       COMM_CMD_SET_CMDQ_CTXT, &msg_params);
134*db03a1ceSFan Gong 	if (err || cmdq_ctxt.head.status) {
135*db03a1ceSFan Gong 		dev_err(hwdev->dev, "Failed to set cmdq ctxt, err: %d, status: 0x%x\n",
136*db03a1ceSFan Gong 			err, cmdq_ctxt.head.status);
137*db03a1ceSFan Gong 		return -EFAULT;
138*db03a1ceSFan Gong 	}
139*db03a1ceSFan Gong 
140*db03a1ceSFan Gong 	return 0;
141*db03a1ceSFan Gong }
142*db03a1ceSFan Gong 
143*db03a1ceSFan Gong static int hinic3_set_cmdq_ctxts(struct hinic3_hwdev *hwdev)
144*db03a1ceSFan Gong {
145*db03a1ceSFan Gong 	struct hinic3_cmdqs *cmdqs = hwdev->cmdqs;
146*db03a1ceSFan Gong 	u8 cmdq_type;
147*db03a1ceSFan Gong 	int err;
148*db03a1ceSFan Gong 
149*db03a1ceSFan Gong 	for (cmdq_type = 0; cmdq_type < cmdqs->cmdq_num; cmdq_type++) {
150*db03a1ceSFan Gong 		err = hinic3_set_cmdq_ctxt(hwdev, cmdq_type);
151*db03a1ceSFan Gong 		if (err)
152*db03a1ceSFan Gong 			return err;
153*db03a1ceSFan Gong 	}
154*db03a1ceSFan Gong 
155*db03a1ceSFan Gong 	cmdqs->status |= HINIC3_CMDQ_ENABLE;
156*db03a1ceSFan Gong 	cmdqs->disable_flag = 0;
157*db03a1ceSFan Gong 
158*db03a1ceSFan Gong 	return 0;
159*db03a1ceSFan Gong }
160*db03a1ceSFan Gong 
161*db03a1ceSFan Gong static int create_cmdq_wq(struct hinic3_hwdev *hwdev,
162*db03a1ceSFan Gong 			  struct hinic3_cmdqs *cmdqs)
163*db03a1ceSFan Gong {
164*db03a1ceSFan Gong 	u8 cmdq_type;
165*db03a1ceSFan Gong 	int err;
166*db03a1ceSFan Gong 
167*db03a1ceSFan Gong 	for (cmdq_type = 0; cmdq_type < cmdqs->cmdq_num; cmdq_type++) {
168*db03a1ceSFan Gong 		err = hinic3_wq_create(hwdev, &cmdqs->cmdq[cmdq_type].wq,
169*db03a1ceSFan Gong 				       CMDQ_DEPTH, CMDQ_WQEBB_SIZE);
170*db03a1ceSFan Gong 		if (err) {
171*db03a1ceSFan Gong 			dev_err(hwdev->dev, "Failed to create cmdq wq\n");
172*db03a1ceSFan Gong 			goto err_destroy_wq;
173*db03a1ceSFan Gong 		}
174*db03a1ceSFan Gong 	}
175*db03a1ceSFan Gong 
176*db03a1ceSFan Gong 	/* 1-level Chip Logical Address (CLA) must put all
177*db03a1ceSFan Gong 	 * cmdq's wq page addr in one wq block
178*db03a1ceSFan Gong 	 */
179*db03a1ceSFan Gong 	if (!hinic3_wq_is_0_level_cla(&cmdqs->cmdq[HINIC3_CMDQ_SYNC].wq)) {
180*db03a1ceSFan Gong 		if (cmdqs->cmdq[HINIC3_CMDQ_SYNC].wq.qpages.num_pages >
181*db03a1ceSFan Gong 		    CMDQ_WQ_CLA_SIZE / sizeof(u64)) {
182*db03a1ceSFan Gong 			err = -EINVAL;
183*db03a1ceSFan Gong 			dev_err(hwdev->dev,
184*db03a1ceSFan Gong 				"Cmdq number of wq pages exceeds limit: %lu\n",
185*db03a1ceSFan Gong 				CMDQ_WQ_CLA_SIZE / sizeof(u64));
186*db03a1ceSFan Gong 			goto err_destroy_wq;
187*db03a1ceSFan Gong 		}
188*db03a1ceSFan Gong 
189*db03a1ceSFan Gong 		cmdqs->wq_block_vaddr =
190*db03a1ceSFan Gong 			dma_alloc_coherent(hwdev->dev, HINIC3_MIN_PAGE_SIZE,
191*db03a1ceSFan Gong 					   &cmdqs->wq_block_paddr, GFP_KERNEL);
192*db03a1ceSFan Gong 		if (!cmdqs->wq_block_vaddr) {
193*db03a1ceSFan Gong 			err = -ENOMEM;
194*db03a1ceSFan Gong 			goto err_destroy_wq;
195*db03a1ceSFan Gong 		}
196*db03a1ceSFan Gong 
197*db03a1ceSFan Gong 		for (cmdq_type = 0; cmdq_type < cmdqs->cmdq_num; cmdq_type++)
198*db03a1ceSFan Gong 			memcpy((u8 *)cmdqs->wq_block_vaddr +
199*db03a1ceSFan Gong 			       CMDQ_WQ_CLA_SIZE * cmdq_type,
200*db03a1ceSFan Gong 			       cmdqs->cmdq[cmdq_type].wq.wq_block_vaddr,
201*db03a1ceSFan Gong 			       cmdqs->cmdq[cmdq_type].wq.qpages.num_pages *
202*db03a1ceSFan Gong 			       sizeof(__be64));
203*db03a1ceSFan Gong 	}
204*db03a1ceSFan Gong 
205*db03a1ceSFan Gong 	return 0;
206*db03a1ceSFan Gong 
207*db03a1ceSFan Gong err_destroy_wq:
208*db03a1ceSFan Gong 	while (cmdq_type > 0) {
209*db03a1ceSFan Gong 		cmdq_type--;
210*db03a1ceSFan Gong 		hinic3_wq_destroy(hwdev, &cmdqs->cmdq[cmdq_type].wq);
211*db03a1ceSFan Gong 	}
212*db03a1ceSFan Gong 
213*db03a1ceSFan Gong 	return err;
214*db03a1ceSFan Gong }
215*db03a1ceSFan Gong 
216*db03a1ceSFan Gong static void destroy_cmdq_wq(struct hinic3_hwdev *hwdev,
217*db03a1ceSFan Gong 			    struct hinic3_cmdqs *cmdqs)
218*db03a1ceSFan Gong {
219*db03a1ceSFan Gong 	u8 cmdq_type;
220*db03a1ceSFan Gong 
221*db03a1ceSFan Gong 	if (cmdqs->wq_block_vaddr)
222*db03a1ceSFan Gong 		dma_free_coherent(hwdev->dev, HINIC3_MIN_PAGE_SIZE,
223*db03a1ceSFan Gong 				  cmdqs->wq_block_vaddr, cmdqs->wq_block_paddr);
224*db03a1ceSFan Gong 
225*db03a1ceSFan Gong 	for (cmdq_type = 0; cmdq_type < cmdqs->cmdq_num; cmdq_type++)
226*db03a1ceSFan Gong 		hinic3_wq_destroy(hwdev, &cmdqs->cmdq[cmdq_type].wq);
227*db03a1ceSFan Gong }
228*db03a1ceSFan Gong 
229*db03a1ceSFan Gong static int init_cmdqs(struct hinic3_hwdev *hwdev)
230*db03a1ceSFan Gong {
231*db03a1ceSFan Gong 	struct hinic3_cmdqs *cmdqs;
232*db03a1ceSFan Gong 
233*db03a1ceSFan Gong 	cmdqs = kzalloc(sizeof(*cmdqs), GFP_KERNEL);
234*db03a1ceSFan Gong 	if (!cmdqs)
235*db03a1ceSFan Gong 		return -ENOMEM;
236*db03a1ceSFan Gong 
237*db03a1ceSFan Gong 	hwdev->cmdqs = cmdqs;
238*db03a1ceSFan Gong 	cmdqs->hwdev = hwdev;
239*db03a1ceSFan Gong 	cmdqs->cmdq_num = hwdev->max_cmdq;
240*db03a1ceSFan Gong 
241*db03a1ceSFan Gong 	cmdqs->cmd_buf_pool = dma_pool_create("hinic3_cmdq", hwdev->dev,
242*db03a1ceSFan Gong 					      CMDQ_BUF_SIZE, CMDQ_BUF_SIZE, 0);
243*db03a1ceSFan Gong 	if (!cmdqs->cmd_buf_pool) {
244*db03a1ceSFan Gong 		dev_err(hwdev->dev, "Failed to create cmdq buffer pool\n");
245*db03a1ceSFan Gong 		kfree(cmdqs);
246*db03a1ceSFan Gong 		return -ENOMEM;
247*db03a1ceSFan Gong 	}
248*db03a1ceSFan Gong 
249*db03a1ceSFan Gong 	return 0;
250*db03a1ceSFan Gong }
251*db03a1ceSFan Gong 
252*db03a1ceSFan Gong static void cmdq_flush_sync_cmd(struct hinic3_cmdq_cmd_info *cmd_info)
253*db03a1ceSFan Gong {
254*db03a1ceSFan Gong 	if (cmd_info->cmd_type != HINIC3_CMD_TYPE_DIRECT_RESP)
255*db03a1ceSFan Gong 		return;
256*db03a1ceSFan Gong 
257*db03a1ceSFan Gong 	cmd_info->cmd_type = HINIC3_CMD_TYPE_FORCE_STOP;
258*db03a1ceSFan Gong 
259*db03a1ceSFan Gong 	if (cmd_info->cmpt_code &&
260*db03a1ceSFan Gong 	    *cmd_info->cmpt_code == CMDQ_SEND_CMPT_CODE)
261*db03a1ceSFan Gong 		*cmd_info->cmpt_code = CMDQ_FORCE_STOP_CMPT_CODE;
262*db03a1ceSFan Gong 
263*db03a1ceSFan Gong 	if (cmd_info->done) {
264*db03a1ceSFan Gong 		complete(cmd_info->done);
265*db03a1ceSFan Gong 		cmd_info->done = NULL;
266*db03a1ceSFan Gong 		cmd_info->cmpt_code = NULL;
267*db03a1ceSFan Gong 		cmd_info->direct_resp = NULL;
268*db03a1ceSFan Gong 		cmd_info->errcode = NULL;
269*db03a1ceSFan Gong 	}
270*db03a1ceSFan Gong }
271*db03a1ceSFan Gong 
272*db03a1ceSFan Gong static void hinic3_cmdq_flush_cmd(struct hinic3_cmdq *cmdq)
273*db03a1ceSFan Gong {
274*db03a1ceSFan Gong 	struct hinic3_cmdq_cmd_info *cmd_info;
275*db03a1ceSFan Gong 	u16 ci;
276*db03a1ceSFan Gong 
277*db03a1ceSFan Gong 	spin_lock_bh(&cmdq->cmdq_lock);
278*db03a1ceSFan Gong 	while (cmdq_read_wqe(&cmdq->wq, &ci)) {
279*db03a1ceSFan Gong 		hinic3_wq_put_wqebbs(&cmdq->wq, CMDQ_WQE_NUM_WQEBBS);
280*db03a1ceSFan Gong 		cmd_info = &cmdq->cmd_infos[ci];
281*db03a1ceSFan Gong 		if (cmd_info->cmd_type == HINIC3_CMD_TYPE_DIRECT_RESP)
282*db03a1ceSFan Gong 			cmdq_flush_sync_cmd(cmd_info);
283*db03a1ceSFan Gong 	}
284*db03a1ceSFan Gong 	spin_unlock_bh(&cmdq->cmdq_lock);
285*db03a1ceSFan Gong }
286*db03a1ceSFan Gong 
287*db03a1ceSFan Gong void hinic3_cmdq_flush_sync_cmd(struct hinic3_hwdev *hwdev)
288*db03a1ceSFan Gong {
289*db03a1ceSFan Gong 	struct hinic3_cmdq *cmdq;
290*db03a1ceSFan Gong 	u16 wqe_cnt, wqe_idx, i;
291*db03a1ceSFan Gong 	struct hinic3_wq *wq;
292*db03a1ceSFan Gong 
293*db03a1ceSFan Gong 	cmdq = &hwdev->cmdqs->cmdq[HINIC3_CMDQ_SYNC];
294*db03a1ceSFan Gong 	spin_lock_bh(&cmdq->cmdq_lock);
295*db03a1ceSFan Gong 	wq = &cmdq->wq;
296*db03a1ceSFan Gong 	wqe_cnt = hinic3_wq_get_used(wq);
297*db03a1ceSFan Gong 	for (i = 0; i < wqe_cnt; i++) {
298*db03a1ceSFan Gong 		wqe_idx = (wq->cons_idx + i) & wq->idx_mask;
299*db03a1ceSFan Gong 		cmdq_flush_sync_cmd(cmdq->cmd_infos + wqe_idx);
300*db03a1ceSFan Gong 	}
301*db03a1ceSFan Gong 	spin_unlock_bh(&cmdq->cmdq_lock);
302*db03a1ceSFan Gong }
303*db03a1ceSFan Gong 
304*db03a1ceSFan Gong static void hinic3_cmdq_reset_all_cmd_buf(struct hinic3_cmdq *cmdq)
305*db03a1ceSFan Gong {
306*db03a1ceSFan Gong 	u16 i;
307*db03a1ceSFan Gong 
308*db03a1ceSFan Gong 	for (i = 0; i < cmdq->wq.q_depth; i++)
309*db03a1ceSFan Gong 		cmdq_clear_cmd_buf(&cmdq->cmd_infos[i], cmdq->hwdev);
310*db03a1ceSFan Gong }
311*db03a1ceSFan Gong 
312*db03a1ceSFan Gong int hinic3_reinit_cmdq_ctxts(struct hinic3_hwdev *hwdev)
313*db03a1ceSFan Gong {
314*db03a1ceSFan Gong 	struct hinic3_cmdqs *cmdqs = hwdev->cmdqs;
315*db03a1ceSFan Gong 	u8 cmdq_type;
316*db03a1ceSFan Gong 
317*db03a1ceSFan Gong 	for (cmdq_type = 0; cmdq_type < cmdqs->cmdq_num; cmdq_type++) {
318*db03a1ceSFan Gong 		hinic3_cmdq_flush_cmd(&cmdqs->cmdq[cmdq_type]);
319*db03a1ceSFan Gong 		hinic3_cmdq_reset_all_cmd_buf(&cmdqs->cmdq[cmdq_type]);
320*db03a1ceSFan Gong 		cmdqs->cmdq[cmdq_type].wrapped = 1;
321*db03a1ceSFan Gong 		hinic3_wq_reset(&cmdqs->cmdq[cmdq_type].wq);
322*db03a1ceSFan Gong 	}
323*db03a1ceSFan Gong 
324*db03a1ceSFan Gong 	return hinic3_set_cmdq_ctxts(hwdev);
325*db03a1ceSFan Gong }
326*db03a1ceSFan Gong 
327*db03a1ceSFan Gong int hinic3_cmdqs_init(struct hinic3_hwdev *hwdev)
328*db03a1ceSFan Gong {
329*db03a1ceSFan Gong 	struct hinic3_cmdqs *cmdqs;
330*db03a1ceSFan Gong 	void __iomem *db_base;
331*db03a1ceSFan Gong 	u8 cmdq_type;
332*db03a1ceSFan Gong 	int err;
333*db03a1ceSFan Gong 
334*db03a1ceSFan Gong 	err = init_cmdqs(hwdev);
335*db03a1ceSFan Gong 	if (err)
336*db03a1ceSFan Gong 		goto err_out;
337*db03a1ceSFan Gong 
338*db03a1ceSFan Gong 	cmdqs = hwdev->cmdqs;
339*db03a1ceSFan Gong 	err = create_cmdq_wq(hwdev, cmdqs);
340*db03a1ceSFan Gong 	if (err)
341*db03a1ceSFan Gong 		goto err_free_cmdqs;
342*db03a1ceSFan Gong 
343*db03a1ceSFan Gong 	err = hinic3_alloc_db_addr(hwdev, &db_base, NULL);
344*db03a1ceSFan Gong 	if (err) {
345*db03a1ceSFan Gong 		dev_err(hwdev->dev, "Failed to allocate doorbell address\n");
346*db03a1ceSFan Gong 		goto err_destroy_cmdq_wq;
347*db03a1ceSFan Gong 	}
348*db03a1ceSFan Gong 	cmdqs->cmdqs_db_base = db_base;
349*db03a1ceSFan Gong 
350*db03a1ceSFan Gong 	for (cmdq_type = 0; cmdq_type < cmdqs->cmdq_num; cmdq_type++) {
351*db03a1ceSFan Gong 		err = init_cmdq(&cmdqs->cmdq[cmdq_type], hwdev, cmdq_type);
352*db03a1ceSFan Gong 		if (err) {
353*db03a1ceSFan Gong 			dev_err(hwdev->dev,
354*db03a1ceSFan Gong 				"Failed to initialize cmdq type : %d\n",
355*db03a1ceSFan Gong 				cmdq_type);
356*db03a1ceSFan Gong 			goto err_free_cmd_infos;
357*db03a1ceSFan Gong 		}
358*db03a1ceSFan Gong 	}
359*db03a1ceSFan Gong 
360*db03a1ceSFan Gong 	err = hinic3_set_cmdq_ctxts(hwdev);
361*db03a1ceSFan Gong 	if (err)
362*db03a1ceSFan Gong 		goto err_free_cmd_infos;
363*db03a1ceSFan Gong 
364*db03a1ceSFan Gong 	return 0;
365*db03a1ceSFan Gong 
366*db03a1ceSFan Gong err_free_cmd_infos:
367*db03a1ceSFan Gong 	while (cmdq_type > 0) {
368*db03a1ceSFan Gong 		cmdq_type--;
369*db03a1ceSFan Gong 		kfree(cmdqs->cmdq[cmdq_type].cmd_infos);
370*db03a1ceSFan Gong 	}
371*db03a1ceSFan Gong 
372*db03a1ceSFan Gong 	hinic3_free_db_addr(hwdev, cmdqs->cmdqs_db_base);
373*db03a1ceSFan Gong 
374*db03a1ceSFan Gong err_destroy_cmdq_wq:
375*db03a1ceSFan Gong 	destroy_cmdq_wq(hwdev, cmdqs);
376*db03a1ceSFan Gong 
377*db03a1ceSFan Gong err_free_cmdqs:
378*db03a1ceSFan Gong 	dma_pool_destroy(cmdqs->cmd_buf_pool);
379*db03a1ceSFan Gong 	kfree(cmdqs);
380*db03a1ceSFan Gong 
381*db03a1ceSFan Gong err_out:
382*db03a1ceSFan Gong 	return err;
383*db03a1ceSFan Gong }
384*db03a1ceSFan Gong 
385*db03a1ceSFan Gong void hinic3_cmdqs_free(struct hinic3_hwdev *hwdev)
386*db03a1ceSFan Gong {
387*db03a1ceSFan Gong 	struct hinic3_cmdqs *cmdqs = hwdev->cmdqs;
388*db03a1ceSFan Gong 	u8 cmdq_type;
389*db03a1ceSFan Gong 
390*db03a1ceSFan Gong 	cmdqs->status &= ~HINIC3_CMDQ_ENABLE;
391*db03a1ceSFan Gong 
392*db03a1ceSFan Gong 	for (cmdq_type = 0; cmdq_type < cmdqs->cmdq_num; cmdq_type++) {
393*db03a1ceSFan Gong 		hinic3_cmdq_flush_cmd(&cmdqs->cmdq[cmdq_type]);
394*db03a1ceSFan Gong 		hinic3_cmdq_reset_all_cmd_buf(&cmdqs->cmdq[cmdq_type]);
395*db03a1ceSFan Gong 		kfree(cmdqs->cmdq[cmdq_type].cmd_infos);
396*db03a1ceSFan Gong 	}
397*db03a1ceSFan Gong 
398*db03a1ceSFan Gong 	hinic3_free_db_addr(hwdev, cmdqs->cmdqs_db_base);
399*db03a1ceSFan Gong 	destroy_cmdq_wq(hwdev, cmdqs);
400*db03a1ceSFan Gong 	dma_pool_destroy(cmdqs->cmd_buf_pool);
401*db03a1ceSFan Gong 	kfree(cmdqs);
402*db03a1ceSFan Gong }
403*db03a1ceSFan Gong 
404*db03a1ceSFan Gong bool hinic3_cmdq_idle(struct hinic3_cmdq *cmdq)
405*db03a1ceSFan Gong {
406*db03a1ceSFan Gong 	return hinic3_wq_get_used(&cmdq->wq) == 0;
407*db03a1ceSFan Gong }
408