Branch data Line data Source code
1 : : /* SPDX-License-Identifier: BSD-3-Clause
2 : : * Copyright(c) 2025 Huawei Technologies Co., Ltd
3 : : */
4 : :
5 : : #include "hinic3_compat.h"
6 : : #include "hinic3_cmd.h"
7 : : #include "hinic3_cmdq.h"
8 : : #include "hinic3_hwdev.h"
9 : : #include "hinic3_hwif.h"
10 : : #include "hinic3_mgmt.h"
11 : : #include "hinic3_wq.h"
12 : : #include "hinic3_nic_cfg.h"
13 : :
14 : : #define CMDQ_CMD_TIMEOUT 5000 /**< Millisecond. */
15 : :
16 : : #define UPPER_8_BITS(data) (((data) >> 8) & 0xFF)
17 : : #define LOWER_8_BITS(data) ((data) & 0xFF)
18 : :
19 : : #define CMDQ_DB_INFO_HI_PROD_IDX_SHIFT 0
20 : : #define CMDQ_DB_INFO_HI_PROD_IDX_MASK 0xFFU
21 : :
22 : : #define CMDQ_DB_INFO_SET(val, member) \
23 : : ((((uint32_t)(val)) & CMDQ_DB_INFO_##member##_MASK) \
24 : : << CMDQ_DB_INFO_##member##_SHIFT)
25 : : #define CMDQ_DB_INFO_UPPER_32(val) ((uint64_t)(val) << 32)
26 : :
27 : : #define CMDQ_DB_HEAD_QUEUE_TYPE_SHIFT 23
28 : : #define CMDQ_DB_HEAD_CMDQ_TYPE_SHIFT 24
29 : : #define CMDQ_DB_HEAD_SRC_TYPE_SHIFT 27
30 : : #define CMDQ_DB_HEAD_QUEUE_TYPE_MASK 0x1U
31 : : #define CMDQ_DB_HEAD_CMDQ_TYPE_MASK 0x7U
32 : : #define CMDQ_DB_HEAD_SRC_TYPE_MASK 0x1FU
33 : : #define CMDQ_DB_HEAD_SET(val, member) \
34 : : ((((uint32_t)(val)) & CMDQ_DB_HEAD_##member##_MASK) \
35 : : << CMDQ_DB_HEAD_##member##_SHIFT)
36 : :
37 : : #define CMDQ_CTRL_PI_SHIFT 0
38 : : #define CMDQ_CTRL_CMD_SHIFT 16
39 : : #define CMDQ_CTRL_MOD_SHIFT 24
40 : : #define CMDQ_CTRL_ACK_TYPE_SHIFT 29
41 : : #define CMDQ_CTRL_HW_BUSY_BIT_SHIFT 31
42 : :
43 : : #define CMDQ_CTRL_PI_MASK 0xFFFFU
44 : : #define CMDQ_CTRL_CMD_MASK 0xFFU
45 : : #define CMDQ_CTRL_MOD_MASK 0x1FU
46 : : #define CMDQ_CTRL_ACK_TYPE_MASK 0x3U
47 : : #define CMDQ_CTRL_HW_BUSY_BIT_MASK 0x1U
48 : :
49 : : #define CMDQ_CTRL_SET(val, member) \
50 : : (((uint32_t)(val) & CMDQ_CTRL_##member##_MASK) << CMDQ_CTRL_##member##_SHIFT)
51 : :
52 : : #define CMDQ_CTRL_GET(val, member) \
53 : : (((val) >> CMDQ_CTRL_##member##_SHIFT) & CMDQ_CTRL_##member##_MASK)
54 : :
55 : : #define CMDQ_WQE_HEADER_BUFDESC_LEN_SHIFT 0
56 : : #define CMDQ_WQE_HEADER_COMPLETE_FMT_SHIFT 15
57 : : #define CMDQ_WQE_HEADER_DATA_FMT_SHIFT 22
58 : : #define CMDQ_WQE_HEADER_COMPLETE_REQ_SHIFT 23
59 : : #define CMDQ_WQE_HEADER_COMPLETE_SECT_LEN_SHIFT 27
60 : : #define CMDQ_WQE_HEADER_CTRL_LEN_SHIFT 29
61 : : #define CMDQ_WQE_HEADER_HW_BUSY_BIT_SHIFT 31
62 : :
63 : : #define CMDQ_WQE_HEADER_BUFDESC_LEN_MASK 0xFFU
64 : : #define CMDQ_WQE_HEADER_COMPLETE_FMT_MASK 0x1U
65 : : #define CMDQ_WQE_HEADER_DATA_FMT_MASK 0x1U
66 : : #define CMDQ_WQE_HEADER_COMPLETE_REQ_MASK 0x1U
67 : : #define CMDQ_WQE_HEADER_COMPLETE_SECT_LEN_MASK 0x3U
68 : : #define CMDQ_WQE_HEADER_CTRL_LEN_MASK 0x3U
69 : : #define CMDQ_WQE_HEADER_HW_BUSY_BIT_MASK 0x1U
70 : :
71 : : #define CMDQ_WQE_HEADER_SET(val, member) \
72 : : (((uint32_t)(val) & CMDQ_WQE_HEADER_##member##_MASK) \
73 : : << CMDQ_WQE_HEADER_##member##_SHIFT)
74 : :
75 : : #define CMDQ_WQE_HEADER_GET(val, member) \
76 : : (((val) >> CMDQ_WQE_HEADER_##member##_SHIFT) & \
77 : : CMDQ_WQE_HEADER_##member##_MASK)
78 : :
79 : : #define CMDQ_CTXT_CURR_WQE_PAGE_PFN_SHIFT 0
80 : : #define CMDQ_CTXT_EQ_ID_SHIFT 53
81 : : #define CMDQ_CTXT_CEQ_ARM_SHIFT 61
82 : : #define CMDQ_CTXT_CEQ_EN_SHIFT 62
83 : : #define CMDQ_CTXT_HW_BUSY_BIT_SHIFT 63
84 : :
85 : : #define CMDQ_CTXT_CURR_WQE_PAGE_PFN_MASK 0xFFFFFFFFFFFFF
86 : : #define CMDQ_CTXT_EQ_ID_MASK 0xFF
87 : : #define CMDQ_CTXT_CEQ_ARM_MASK 0x1
88 : : #define CMDQ_CTXT_CEQ_EN_MASK 0x1
89 : : #define CMDQ_CTXT_HW_BUSY_BIT_MASK 0x1
90 : :
91 : : #define CMDQ_CTXT_PAGE_INFO_SET(val, member) \
92 : : (((uint64_t)(val) & CMDQ_CTXT_##member##_MASK) << CMDQ_CTXT_##member##_SHIFT)
93 : :
94 : : #define CMDQ_CTXT_WQ_BLOCK_PFN_SHIFT 0
95 : : #define CMDQ_CTXT_CI_SHIFT 52
96 : :
97 : : #define CMDQ_CTXT_WQ_BLOCK_PFN_MASK 0xFFFFFFFFFFFFF
98 : : #define CMDQ_CTXT_CI_MASK 0xFFF
99 : :
100 : : #define CMDQ_CTXT_BLOCK_INFO_SET(val, member) \
101 : : (((uint64_t)(val) & CMDQ_CTXT_##member##_MASK) << CMDQ_CTXT_##member##_SHIFT)
102 : :
103 : : #define SAVED_DATA_ARM_SHIFT 31
104 : :
105 : : #define SAVED_DATA_ARM_MASK 0x1U
106 : :
107 : : #define SAVED_DATA_SET(val, member) \
108 : : (((val) & SAVED_DATA_##member##_MASK) << SAVED_DATA_##member##_SHIFT)
109 : :
110 : : #define SAVED_DATA_CLEAR(val, member) \
111 : : ((val) & (~(SAVED_DATA_##member##_MASK << SAVED_DATA_##member##_SHIFT)))
112 : :
113 : : #define WQE_ERRCODE_VAL_SHIFT 0
114 : :
115 : : #define WQE_ERRCODE_VAL_MASK 0x7FFFFFFF
116 : :
117 : : #define WQE_ERRCODE_GET(val, member) \
118 : : (((val) >> WQE_ERRCODE_##member##_SHIFT) & WQE_ERRCODE_##member##_MASK)
119 : :
120 : : #define WQE_COMPLETED(ctrl_info) CMDQ_CTRL_GET(ctrl_info, HW_BUSY_BIT)
121 : :
122 : : #define WQE_HEADER(wqe) ((struct hinic3_cmdq_header *)(wqe))
123 : :
124 : : #define CMDQ_DB_PI_OFF(pi) (LOWER_8_BITS(pi) << 3)
125 : :
126 : : #define CMDQ_DB_ADDR(db_base, pi) ((db_base) + CMDQ_DB_PI_OFF(pi))
127 : :
128 : : #define CMDQ_PFN(addr, page_size) ((addr) >> (rte_log2_u32(page_size)))
129 : :
130 : : #define FIRST_DATA_TO_WRITE_LAST sizeof(uint64_t)
131 : :
132 : : #define WQE_LCMD_SIZE 64
133 : : #define WQE_SCMD_SIZE 64
134 : :
135 : : #define COMPLETE_LEN 3
136 : :
137 : : #define CMDQ_WQEBB_SIZE 64
138 : : #define CMDQ_WQEBB_SHIFT 6
139 : :
140 : : #define CMDQ_WQE_SIZE 64
141 : :
142 : : #define HINIC3_CMDQ_WQ_BUF_SIZE 4096
143 : :
144 : : #define WQE_NUM_WQEBBS(wqe_size, wq) \
145 : : ({ \
146 : : typeof(wq) __wq = (wq); \
147 : : (uint16_t)(RTE_ALIGN((uint32_t)(wqe_size), __wq->wqebb_size) / \
148 : : __wq->wqebb_size); \
149 : : })
150 : :
151 : : #define cmdq_to_cmdqs(cmdq) \
152 : : ({ \
153 : : typeof(cmdq) __cmdq = (cmdq); \
154 : : container_of(__cmdq - __cmdq->cmdq_type, struct hinic3_cmdqs, \
155 : : __cmdq[0]); \
156 : : })
157 : :
158 : : #define WAIT_CMDQ_ENABLE_TIMEOUT 300
159 : :
160 : : static int hinic3_cmdq_poll_msg(struct hinic3_cmdq *cmdq, uint32_t timeout);
161 : :
162 : : bool
163 : 0 : hinic3_cmdq_idle(struct hinic3_cmdq *cmdq)
164 : : {
165 : 0 : struct hinic3_wq *wq = cmdq->wq;
166 : :
167 : 0 : return rte_atomic_load_explicit(&wq->delta, rte_memory_order_seq_cst) ==
168 : 0 : wq->q_depth;
169 : : }
170 : :
171 : : struct hinic3_cmd_buf *
172 : 0 : hinic3_alloc_cmd_buf(struct hinic3_hwdev *hwdev)
173 : : {
174 : 0 : struct hinic3_cmdqs *cmdqs = hwdev->cmdqs;
175 : : struct hinic3_cmd_buf *cmd_buf;
176 : :
177 : 0 : cmd_buf = rte_zmalloc(NULL, sizeof(*cmd_buf), 0);
178 [ # # ]: 0 : if (!cmd_buf) {
179 : 0 : PMD_DRV_LOG(ERR, "Allocate cmd buffer failed");
180 : 0 : return NULL;
181 : : }
182 : :
183 : 0 : cmd_buf->mbuf = rte_pktmbuf_alloc(cmdqs->cmd_buf_pool);
184 [ # # ]: 0 : if (!cmd_buf->mbuf) {
185 : 0 : PMD_DRV_LOG(ERR, "Allocate cmd from the pool failed");
186 : 0 : goto alloc_pci_buf_err;
187 : : }
188 : :
189 : 0 : cmd_buf->dma_addr = rte_mbuf_data_iova(cmd_buf->mbuf);
190 : 0 : cmd_buf->buf = rte_pktmbuf_mtod(cmd_buf->mbuf, void *);
191 : :
192 : 0 : return cmd_buf;
193 : :
194 : : alloc_pci_buf_err:
195 : 0 : rte_free(cmd_buf);
196 : 0 : return NULL;
197 : : }
198 : :
199 : : void
200 : 0 : hinic3_free_cmd_buf(struct hinic3_cmd_buf *cmd_buf)
201 : : {
202 : 0 : rte_pktmbuf_free(cmd_buf->mbuf);
203 : 0 : rte_free(cmd_buf);
204 : 0 : }
205 : :
206 : : static uint32_t
207 : : cmdq_wqe_size(enum cmdq_wqe_type wqe_type)
208 : : {
209 : : uint32_t wqe_size = 0;
210 : :
211 : : switch (wqe_type) {
212 : : case WQE_LCMD_TYPE:
213 : : wqe_size = WQE_LCMD_SIZE;
214 : : break;
215 : : case WQE_SCMD_TYPE:
216 : : wqe_size = WQE_SCMD_SIZE;
217 : : break;
218 : : }
219 : :
220 : : return wqe_size;
221 : : }
222 : :
223 : : static uint32_t
224 : : cmdq_get_wqe_size(enum bufdesc_len len)
225 : : {
226 : : uint32_t wqe_size = 0;
227 : :
228 : 0 : switch (len) {
229 : : case BUFDESC_LCMD_LEN:
230 : : wqe_size = WQE_LCMD_SIZE;
231 : : break;
232 : : case BUFDESC_SCMD_LEN:
233 : : wqe_size = WQE_SCMD_SIZE;
234 : : break;
235 : 0 : default:
236 : 0 : PMD_DRV_LOG(ERR, "Invalid bufdesc_len");
237 : : break;
238 : : }
239 : :
240 : : return wqe_size;
241 : : }
242 : :
243 : : static void
244 : : cmdq_set_completion(struct hinic3_cmdq_completion *complete,
245 : : struct hinic3_cmd_buf *buf_out)
246 : : {
247 : : struct hinic3_sge_resp *sge_resp = &complete->sge_resp;
248 : :
249 : 0 : hinic3_set_sge(&sge_resp->sge, buf_out->dma_addr, HINIC3_CMDQ_BUF_SIZE);
250 : 0 : }
251 : :
252 : : static void
253 : : cmdq_set_lcmd_bufdesc(struct hinic3_cmdq_wqe_lcmd *wqe,
254 : : struct hinic3_cmd_buf *buf_in)
255 : : {
256 : 0 : hinic3_set_sge(&wqe->buf_desc.sge, buf_in->dma_addr, buf_in->size);
257 : : }
258 : :
259 : : static void
260 : 0 : cmdq_set_db(struct hinic3_cmdq *cmdq, enum hinic3_cmdq_type cmdq_type,
261 : : uint16_t prod_idx)
262 : : {
263 : 0 : uint64_t db = CMDQ_DB_INFO_SET(UPPER_8_BITS(prod_idx), HI_PROD_IDX);
264 : :
265 : 0 : db = CMDQ_DB_INFO_UPPER_32(db) |
266 : 0 : CMDQ_DB_HEAD_SET(HINIC3_DB_CMDQ_TYPE, QUEUE_TYPE) |
267 : 0 : CMDQ_DB_HEAD_SET(cmdq_type, CMDQ_TYPE) |
268 : : CMDQ_DB_HEAD_SET(HINIC3_DB_SRC_CMDQ_TYPE, SRC_TYPE);
269 : :
270 : : /**< Write all before the doorbell. */
271 : : rte_atomic_thread_fence(rte_memory_order_release);
272 : : /* Hardware will do endianness converting. */
273 : 0 : rte_write64(db, CMDQ_DB_ADDR(cmdq->db_base, prod_idx));
274 : 0 : }
275 : :
276 : : static void
277 : 0 : cmdq_wqe_fill(void *dst, void *src)
278 : : {
279 : 0 : memcpy((void *)((uint8_t *)dst + FIRST_DATA_TO_WRITE_LAST),
280 : 0 : (void *)((uint8_t *)src + FIRST_DATA_TO_WRITE_LAST),
281 : : CMDQ_WQE_SIZE - FIRST_DATA_TO_WRITE_LAST);
282 : :
283 : : /* The first 8 bytes should be written last. */
284 : : rte_atomic_thread_fence(rte_memory_order_release);
285 : :
286 : 0 : *(uint64_t *)dst = *(uint64_t *)src;
287 : 0 : }
288 : :
289 : : static void
290 : 0 : cmdq_prepare_wqe_ctrl(struct hinic3_cmdq_wqe *wqe, int wrapped,
291 : : enum hinic3_mod_type mod, uint8_t cmd, uint16_t prod_idx,
292 : : enum completion_format complete_format,
293 : : enum data_format local_data_format,
294 : : enum bufdesc_len buf_len)
295 : : {
296 : : struct hinic3_ctrl *ctrl = NULL;
297 : : enum ctrl_sect_len ctrl_len;
298 : : struct hinic3_cmdq_wqe_lcmd *wqe_lcmd = NULL;
299 : : struct hinic3_cmdq_wqe_scmd *wqe_scmd = NULL;
300 : 0 : uint32_t saved_data = WQE_HEADER(wqe)->saved_data;
301 : :
302 [ # # ]: 0 : if (local_data_format == DATA_SGE) {
303 : : wqe_lcmd = &wqe->wqe_lcmd;
304 : :
305 : 0 : wqe_lcmd->status.status_info = 0;
306 : 0 : ctrl = &wqe_lcmd->ctrl;
307 : : ctrl_len = CTRL_SECT_LEN;
308 : : } else {
309 : : wqe_scmd = &wqe->inline_wqe.wqe_scmd;
310 : :
311 : 0 : wqe_scmd->status.status_info = 0;
312 : 0 : ctrl = &wqe_scmd->ctrl;
313 : : ctrl_len = CTRL_DIRECT_SECT_LEN;
314 : : }
315 : :
316 : 0 : ctrl->ctrl_info = CMDQ_CTRL_SET(prod_idx, PI) |
317 : 0 : CMDQ_CTRL_SET(cmd, CMD) | CMDQ_CTRL_SET(mod, MOD) |
318 : : CMDQ_CTRL_SET(HINIC3_ACK_TYPE_CMDQ, ACK_TYPE);
319 : :
320 : 0 : WQE_HEADER(wqe)->header_info =
321 : 0 : CMDQ_WQE_HEADER_SET(buf_len, BUFDESC_LEN) |
322 : 0 : CMDQ_WQE_HEADER_SET(complete_format, COMPLETE_FMT) |
323 : 0 : CMDQ_WQE_HEADER_SET(local_data_format, DATA_FMT) |
324 : : CMDQ_WQE_HEADER_SET(CEQ_SET, COMPLETE_REQ) |
325 : 0 : CMDQ_WQE_HEADER_SET(COMPLETE_LEN, COMPLETE_SECT_LEN) |
326 : 0 : CMDQ_WQE_HEADER_SET(ctrl_len, CTRL_LEN) |
327 : 0 : CMDQ_WQE_HEADER_SET((uint32_t)wrapped, HW_BUSY_BIT);
328 : :
329 : 0 : saved_data &= SAVED_DATA_CLEAR(saved_data, ARM);
330 [ # # ]: 0 : if (cmd == CMDQ_SET_ARM_CMD && mod == HINIC3_MOD_COMM)
331 : 0 : WQE_HEADER(wqe)->saved_data = saved_data |
332 : : SAVED_DATA_SET(1, ARM);
333 : : else
334 : 0 : WQE_HEADER(wqe)->saved_data = saved_data;
335 : 0 : }
336 : :
337 : : static void
338 : 0 : cmdq_set_lcmd_wqe(struct hinic3_cmdq_wqe *wqe, enum cmdq_cmd_type cmd_type,
339 : : struct hinic3_cmd_buf *buf_in, struct hinic3_cmd_buf *buf_out,
340 : : int wrapped, enum hinic3_mod_type mod, uint8_t cmd, uint16_t prod_idx)
341 : : {
342 : : struct hinic3_cmdq_wqe_lcmd *wqe_lcmd = &wqe->wqe_lcmd;
343 : : enum completion_format complete_format = COMPLETE_DIRECT;
344 : :
345 [ # # # # ]: 0 : switch (cmd_type) {
346 : 0 : case SYNC_CMD_DIRECT_RESP:
347 : : complete_format = COMPLETE_DIRECT;
348 : 0 : wqe_lcmd->completion.direct_resp = 0;
349 : 0 : break;
350 : 0 : case SYNC_CMD_SGE_RESP:
351 [ # # ]: 0 : if (buf_out) {
352 : : complete_format = COMPLETE_SGE;
353 : : cmdq_set_completion(&wqe_lcmd->completion, buf_out);
354 : : }
355 : : break;
356 : 0 : case ASYNC_CMD:
357 : : complete_format = COMPLETE_DIRECT;
358 : 0 : wqe_lcmd->completion.direct_resp = 0;
359 : 0 : wqe_lcmd->buf_desc.saved_async_buf = (uint64_t)(buf_in);
360 : 0 : break;
361 : 0 : default:
362 : 0 : PMD_DRV_LOG(ERR, "Invalid cmdq_cmd_type");
363 : 0 : break;
364 : : }
365 : :
366 : 0 : cmdq_prepare_wqe_ctrl(wqe, wrapped, mod, cmd, prod_idx, complete_format,
367 : : DATA_SGE, BUFDESC_LCMD_LEN);
368 : :
369 : : cmdq_set_lcmd_bufdesc(wqe_lcmd, buf_in);
370 : 0 : }
371 : :
372 : : /**
373 : : * Prepare necessary context for command queue, send a synchronous command with
374 : : * a direct response to hardware. It waits for completion of command by polling
375 : : * command queue for a response.
376 : : *
377 : : * @param[in] cmdq
378 : : * The command queue object that represents the queue to send the command to.
379 : : * @param[in] mod
380 : : * The module type that the command belongs to.
381 : : * @param[in] cmd
382 : : * The command to be executed.
383 : : * @param[in] buf_in
384 : : * The input buffer containing the command parameters.
385 : : * @param[out] out_param
386 : : * A pointer to the location where the response data will be stored, if
387 : : * available.
388 : : * @param[in] timeout
389 : : * The timeout value (ms) to wait for the command completion. If zero, a default
390 : : * timeout will be used.
391 : : *
392 : : * @return
393 : : * 0 on success, non-zero on failure.
394 : : * - -EBUSY: The command queue is busy.
395 : : * - -ETIMEDOUT: The command did not complete within the specified timeout.
396 : : */
397 : : static int
398 : 0 : cmdq_sync_cmd_direct_resp(struct hinic3_cmdq *cmdq, enum hinic3_mod_type mod,
399 : : uint8_t cmd, struct hinic3_cmd_buf *buf_in,
400 : : uint64_t *out_param, uint32_t timeout)
401 : : {
402 : : struct hinic3_cmdq_wqe wqe;
403 : 0 : struct hinic3_wq *wq = cmdq->wq;
404 : : struct hinic3_cmdq_wqe *curr_wqe = NULL;
405 : : struct hinic3_cmdq_wqe_lcmd *wqe_lcmd = NULL;
406 : : uint16_t curr_prod_idx, next_prod_idx, num_wqebbs;
407 : : uint32_t timeo, wqe_size;
408 : : int wrapped, err;
409 : :
410 : : wqe_size = cmdq_wqe_size(WQE_LCMD_TYPE);
411 : 0 : num_wqebbs = WQE_NUM_WQEBBS(wqe_size, wq);
412 : :
413 : : /* ensure thread safety and maintain wrapped and doorbell index correct. */
414 : 0 : rte_spinlock_lock(&cmdq->cmdq_lock);
415 : :
416 : 0 : curr_wqe = hinic3_get_wqe(cmdq->wq, num_wqebbs, &curr_prod_idx);
417 [ # # ]: 0 : if (curr_wqe == NULL) {
418 : : err = -EBUSY;
419 : 0 : goto cmdq_unlock;
420 : : }
421 : :
422 : : memset(&wqe, 0, sizeof(wqe));
423 : 0 : wrapped = cmdq->wrapped;
424 : :
425 : 0 : next_prod_idx = curr_prod_idx + num_wqebbs;
426 [ # # ]: 0 : if (next_prod_idx >= wq->q_depth) {
427 : 0 : cmdq->wrapped = !cmdq->wrapped;
428 : 0 : next_prod_idx -= wq->q_depth;
429 : : }
430 : :
431 : 0 : cmdq_set_lcmd_wqe(&wqe, SYNC_CMD_DIRECT_RESP, buf_in, NULL, wrapped,
432 : : mod, cmd, curr_prod_idx);
433 : :
434 : :
435 : : hinic3_cpu_to_hw(&wqe, wqe_size);
436 : :
437 : : /* Cmdq wqe is not shadow, therefore wqe will be written to wq. */
438 : 0 : cmdq_wqe_fill(curr_wqe, &wqe);
439 : :
440 : 0 : cmdq->cmd_infos[curr_prod_idx].cmd_type = HINIC3_CMD_TYPE_DIRECT_RESP;
441 : :
442 : 0 : cmdq_set_db(cmdq, HINIC3_CMDQ_SYNC, next_prod_idx);
443 : :
444 [ # # ]: 0 : timeo = timeout ? timeout : CMDQ_CMD_TIMEOUT;
445 : 0 : err = hinic3_cmdq_poll_msg(cmdq, timeo);
446 [ # # ]: 0 : if (err) {
447 : 0 : PMD_DRV_LOG(ERR, "Cmdq poll msg ack failed, prod idx: 0x%x",
448 : : curr_prod_idx);
449 : : err = -ETIMEDOUT;
450 : 0 : goto cmdq_unlock;
451 : : }
452 : :
453 : 0 : rte_smp_rmb(); /*Ensure all cmdq return messages are completed*/
454 : :
455 [ # # ]: 0 : if (out_param) {
456 : : wqe_lcmd = &curr_wqe->wqe_lcmd;
457 [ # # ]: 0 : *out_param = rte_cpu_to_be_64(wqe_lcmd->completion.direct_resp);
458 : : }
459 : :
460 [ # # ]: 0 : if (cmdq->errcode[curr_prod_idx])
461 : : err = cmdq->errcode[curr_prod_idx];
462 : :
463 : 0 : cmdq_unlock:
464 : : rte_spinlock_unlock(&cmdq->cmdq_lock);
465 : :
466 : 0 : return err;
467 : : }
468 : :
469 : : /**
470 : : * Send a synchronous command with detailed response and wait for the
471 : : * completion.
472 : : *
473 : : * @param[in] cmdq
474 : : * The command queue object representing the queue to send the command to.
475 : : * @param[in] mod
476 : : * The module type that the command belongs to.
477 : : * @param[in] cmd
478 : : * The command to be executed.
479 : : * @param[in] buf_in
480 : : * The input buffer containing the parameters for the command.
481 : : * @param[out] buf_out
482 : : * The output buffer where the detailed response from the hardware will be
483 : : * stored.
484 : : * @param[in] timeout
485 : : * The timeout value (ms) to wait for the command completion. If zero, a default
486 : : * timeout will be used.
487 : : *
488 : : * @return
489 : : * 0 on success, non-zero on failure.
490 : : * - -EBUSY: The command queue is busy.
491 : : * - -ETIMEDOUT: The command did not complete within the specified timeout.
492 : : */
493 : : static int
494 : 0 : cmdq_sync_cmd_detail_resp(struct hinic3_cmdq *cmdq, enum hinic3_mod_type mod,
495 : : uint8_t cmd, struct hinic3_cmd_buf *buf_in,
496 : : struct hinic3_cmd_buf *buf_out, uint32_t timeout)
497 : : {
498 : : struct hinic3_cmdq_wqe wqe;
499 : 0 : struct hinic3_wq *wq = cmdq->wq;
500 : : struct hinic3_cmdq_wqe *curr_wqe = NULL;
501 : : uint16_t curr_prod_idx, next_prod_idx, num_wqebbs;
502 : : uint32_t timeo, wqe_size;
503 : : int wrapped, err;
504 : :
505 : : wqe_size = cmdq_wqe_size(WQE_LCMD_TYPE);
506 : 0 : num_wqebbs = WQE_NUM_WQEBBS(wqe_size, wq);
507 : :
508 : : /* ensure thread safety and maintain wrapped and doorbell index correct. */
509 : 0 : rte_spinlock_lock(&cmdq->cmdq_lock);
510 : :
511 : 0 : curr_wqe = hinic3_get_wqe(cmdq->wq, num_wqebbs, &curr_prod_idx);
512 [ # # ]: 0 : if (curr_wqe == NULL) {
513 : : err = -EBUSY;
514 : 0 : goto cmdq_unlock;
515 : : }
516 : :
517 : : memset(&wqe, 0, sizeof(wqe));
518 : 0 : wrapped = cmdq->wrapped;
519 : :
520 : 0 : next_prod_idx = curr_prod_idx + num_wqebbs;
521 [ # # ]: 0 : if (next_prod_idx >= wq->q_depth) {
522 : 0 : cmdq->wrapped = !cmdq->wrapped;
523 : 0 : next_prod_idx -= wq->q_depth;
524 : : }
525 : :
526 : 0 : cmdq_set_lcmd_wqe(&wqe, SYNC_CMD_SGE_RESP, buf_in, buf_out, wrapped,
527 : : mod, cmd, curr_prod_idx);
528 : :
529 : : hinic3_cpu_to_hw(&wqe, wqe_size);
530 : :
531 : : /* Cmdq wqe is not shadow, therefore wqe will be written to wq. */
532 : 0 : cmdq_wqe_fill(curr_wqe, &wqe);
533 : :
534 : 0 : cmdq->cmd_infos[curr_prod_idx].cmd_type = HINIC3_CMD_TYPE_SGE_RESP;
535 : :
536 : 0 : cmdq_set_db(cmdq, cmdq->cmdq_type, next_prod_idx);
537 : :
538 [ # # ]: 0 : timeo = timeout ? timeout : CMDQ_CMD_TIMEOUT;
539 : 0 : err = hinic3_cmdq_poll_msg(cmdq, timeo);
540 [ # # ]: 0 : if (err) {
541 : 0 : PMD_DRV_LOG(ERR, "Cmdq poll msg ack failed, prod idx: 0x%x",
542 : : curr_prod_idx);
543 : : err = -ETIMEDOUT;
544 : 0 : goto cmdq_unlock;
545 : : }
546 : :
547 : 0 : rte_smp_rmb(); /*Ensure all cmdq return messages are completed*/
548 : :
549 [ # # ]: 0 : if (cmdq->errcode[curr_prod_idx])
550 : : err = cmdq->errcode[curr_prod_idx];
551 : :
552 : 0 : cmdq_unlock:
553 : : rte_spinlock_unlock(&cmdq->cmdq_lock);
554 : :
555 : 0 : return err;
556 : : }
557 : :
558 : : static int
559 : 0 : cmdq_params_valid(struct hinic3_hwdev *hwdev, struct hinic3_cmd_buf *buf_in)
560 : : {
561 [ # # ]: 0 : if (!buf_in || !hwdev) {
562 : 0 : PMD_DRV_LOG(ERR, "Invalid CMDQ buffer or hwdev is NULL");
563 : 0 : return -EINVAL;
564 : : }
565 : :
566 [ # # ]: 0 : if (buf_in->size == 0 || buf_in->size > HINIC3_CMDQ_BUF_SIZE) {
567 : 0 : PMD_DRV_LOG(ERR, "Invalid CMDQ buffer size: 0x%x",
568 : : buf_in->size);
569 : 0 : return -EINVAL;
570 : : }
571 : :
572 : : return 0;
573 : : }
574 : :
575 : : static int
576 : 0 : wait_cmdqs_enable(struct hinic3_cmdqs *cmdqs)
577 : : {
578 : : uint64_t end;
579 : :
580 : 0 : end = cycles + msecs_to_cycles(WAIT_CMDQ_ENABLE_TIMEOUT);
581 : : do {
582 [ # # ]: 0 : if (cmdqs->status & HINIC3_CMDQ_ENABLE)
583 : : return 0;
584 [ # # ]: 0 : } while (time_before(cycles, end));
585 : :
586 : : return -EBUSY;
587 : : }
588 : :
589 : : int
590 : 0 : hinic3_cmdq_direct_resp(struct hinic3_hwdev *hwdev, enum hinic3_mod_type mod, uint8_t cmd,
591 : : struct hinic3_cmd_buf *buf_in, uint64_t *out_param, uint32_t timeout)
592 : : {
593 : 0 : struct hinic3_cmdqs *cmdqs = hwdev->cmdqs;
594 : : int err;
595 : :
596 : 0 : err = cmdq_params_valid(hwdev, buf_in);
597 [ # # ]: 0 : if (err) {
598 : 0 : PMD_DRV_LOG(ERR, "Invalid cmdq parameters");
599 : 0 : return err;
600 : : }
601 : :
602 : 0 : err = wait_cmdqs_enable(cmdqs);
603 [ # # ]: 0 : if (err) {
604 : 0 : PMD_DRV_LOG(ERR, "Cmdq is disabled");
605 : 0 : return err;
606 : : }
607 : :
608 : 0 : return cmdq_sync_cmd_direct_resp(&cmdqs->cmdq[HINIC3_CMDQ_SYNC], mod,
609 : : cmd, buf_in, out_param, timeout);
610 : : }
611 : :
612 : : int
613 : 0 : hinic3_cmdq_detail_resp(struct hinic3_hwdev *hwdev, enum hinic3_mod_type mod, uint8_t cmd,
614 : : struct hinic3_cmd_buf *buf_in, struct hinic3_cmd_buf *buf_out, uint32_t timeout)
615 : : {
616 : 0 : struct hinic3_cmdqs *cmdqs = hwdev->cmdqs;
617 : : int err;
618 : :
619 : 0 : err = cmdq_params_valid(hwdev, buf_in);
620 [ # # ]: 0 : if (err) {
621 : 0 : PMD_DRV_LOG(ERR, "Invalid cmdq parameters");
622 : 0 : return err;
623 : : }
624 : :
625 : 0 : err = wait_cmdqs_enable(cmdqs);
626 [ # # ]: 0 : if (err) {
627 : 0 : PMD_DRV_LOG(ERR, "Cmdq is disabled");
628 : 0 : return err;
629 : : }
630 : :
631 : 0 : return cmdq_sync_cmd_detail_resp(&cmdqs->cmdq[HINIC3_CMDQ_SYNC], mod,
632 : : cmd, buf_in, buf_out, timeout);
633 : : }
634 : :
635 : : static void
636 : : cmdq_update_errcode(struct hinic3_cmdq *cmdq, uint16_t prod_idx, int errcode)
637 : : {
638 : 0 : cmdq->errcode[prod_idx] = errcode;
639 : : }
640 : :
641 : : static void
642 : 0 : clear_wqe_complete_bit(struct hinic3_cmdq *cmdq, struct hinic3_cmdq_wqe *wqe)
643 : : {
644 : : struct hinic3_ctrl *ctrl = NULL;
645 : 0 : uint32_t header_info = hinic3_hw_cpu32(WQE_HEADER(wqe)->header_info);
646 : 0 : int buf_len = CMDQ_WQE_HEADER_GET(header_info, BUFDESC_LEN);
647 [ # # ]: 0 : uint32_t wqe_size = cmdq_get_wqe_size(buf_len);
648 : : uint16_t num_wqebbs;
649 : :
650 : : if (wqe_size == WQE_LCMD_SIZE)
651 : 0 : ctrl = &wqe->wqe_lcmd.ctrl;
652 : : else
653 : 0 : ctrl = &wqe->inline_wqe.wqe_scmd.ctrl;
654 : :
655 : : /* Clear HW busy bit. */
656 : 0 : ctrl->ctrl_info = 0;
657 : :
658 : : rte_atomic_thread_fence(rte_memory_order_release); /**< Verify wqe is cleared. */
659 : :
660 : 0 : num_wqebbs = WQE_NUM_WQEBBS(wqe_size, cmdq->wq);
661 : 0 : hinic3_put_wqe(cmdq->wq, num_wqebbs);
662 : 0 : }
663 : :
664 : : static void
665 : : cmdq_init_queue_ctxt(struct hinic3_cmdq *cmdq,
666 : : struct hinic3_cmdq_ctxt_info *ctxt_info)
667 : : {
668 : 0 : struct hinic3_wq *wq = cmdq->wq;
669 : : uint64_t wq_first_page_paddr, pfn;
670 : :
671 : 0 : uint16_t start_ci = (uint16_t)(wq->cons_idx);
672 : :
673 : : /* The data in the HW is in Big Endian Format. */
674 : 0 : wq_first_page_paddr = wq->queue_buf_paddr;
675 : :
676 : 0 : pfn = CMDQ_PFN(wq_first_page_paddr, RTE_PGSIZE_4K);
677 : 0 : ctxt_info->curr_wqe_page_pfn =
678 : : CMDQ_CTXT_PAGE_INFO_SET(1, HW_BUSY_BIT) |
679 : : CMDQ_CTXT_PAGE_INFO_SET(0, CEQ_EN) |
680 : : CMDQ_CTXT_PAGE_INFO_SET(0, CEQ_ARM) |
681 : 0 : CMDQ_CTXT_PAGE_INFO_SET(HINIC3_CEQ_ID_CMDQ, EQ_ID) |
682 : : CMDQ_CTXT_PAGE_INFO_SET(pfn, CURR_WQE_PAGE_PFN);
683 : :
684 : 0 : ctxt_info->wq_block_pfn = CMDQ_CTXT_BLOCK_INFO_SET(start_ci, CI) |
685 : : CMDQ_CTXT_BLOCK_INFO_SET(pfn, WQ_BLOCK_PFN);
686 : : }
687 : :
688 : : static int
689 : 0 : init_cmdq(struct hinic3_cmdq *cmdq, struct hinic3_hwdev *hwdev,
690 : : struct hinic3_wq *wq, enum hinic3_cmdq_type q_type)
691 : : {
692 : : int err = 0;
693 : : size_t errcode_size;
694 : : size_t cmd_infos_size;
695 : :
696 : 0 : cmdq->wq = wq;
697 : 0 : cmdq->cmdq_type = q_type;
698 : 0 : cmdq->wrapped = 1;
699 : :
700 : : rte_spinlock_init(&cmdq->cmdq_lock);
701 : :
702 : 0 : errcode_size = wq->q_depth * sizeof(*cmdq->errcode);
703 : 0 : cmdq->errcode = rte_zmalloc(NULL, errcode_size, 0);
704 [ # # ]: 0 : if (!cmdq->errcode) {
705 : 0 : PMD_DRV_LOG(ERR, "Allocate errcode for cmdq failed");
706 : 0 : return -ENOMEM;
707 : : }
708 : :
709 : 0 : cmd_infos_size = wq->q_depth * sizeof(*cmdq->cmd_infos);
710 : 0 : cmdq->cmd_infos = rte_zmalloc(NULL, cmd_infos_size, 0);
711 [ # # ]: 0 : if (!cmdq->cmd_infos) {
712 : 0 : PMD_DRV_LOG(ERR, "Allocate cmd info for cmdq failed");
713 : : err = -ENOMEM;
714 : 0 : goto cmd_infos_err;
715 : : }
716 : :
717 : 0 : cmdq->db_base = hwdev->cmdqs->cmdqs_db_base;
718 : :
719 : 0 : return 0;
720 : :
721 : : cmd_infos_err:
722 : 0 : rte_free(cmdq->errcode);
723 : :
724 : 0 : return err;
725 : : }
726 : :
727 : : static void
728 : : free_cmdq(struct hinic3_cmdq *cmdq)
729 : : {
730 : 0 : rte_free(cmdq->cmd_infos);
731 : 0 : rte_free(cmdq->errcode);
732 : : }
733 : :
734 : : static int
735 : 0 : hinic3_set_cmdq_ctxts(struct hinic3_hwdev *hwdev)
736 : : {
737 : 0 : struct hinic3_cmdqs *cmdqs = hwdev->cmdqs;
738 : : struct hinic3_cmd_cmdq_ctxt cmdq_ctxt;
739 : : enum hinic3_cmdq_type cmdq_type;
740 : 0 : uint16_t out_size = sizeof(cmdq_ctxt);
741 : : int err;
742 : :
743 [ # # ]: 0 : for (cmdq_type = HINIC3_CMDQ_SYNC; cmdq_type < HINIC3_MAX_CMDQ_TYPES; cmdq_type++) {
744 : : memset(&cmdq_ctxt, 0, sizeof(cmdq_ctxt));
745 : 0 : cmdq_ctxt.ctxt_info = cmdqs->cmdq[cmdq_type].cmdq_ctxt;
746 : 0 : cmdq_ctxt.func_idx = hinic3_global_func_id(hwdev);
747 : 0 : cmdq_ctxt.cmdq_id = cmdq_type;
748 : :
749 : 0 : err = hinic3_msg_to_mgmt_sync(hwdev, HINIC3_MOD_COMM,
750 : : HINIC3_MGMT_CMD_SET_CMDQ_CTXT,
751 : : &cmdq_ctxt, sizeof(cmdq_ctxt),
752 : : &cmdq_ctxt, &out_size);
753 : :
754 [ # # # # : 0 : if (err || !out_size || cmdq_ctxt.status) {
# # ]
755 : 0 : PMD_DRV_LOG(ERR,
756 : : "Set cmdq ctxt failed, err: %d, status: 0x%x, out_size: 0x%x",
757 : : err, cmdq_ctxt.status, out_size);
758 : 0 : return -EFAULT;
759 : : }
760 : : }
761 : :
762 : 0 : cmdqs->status |= HINIC3_CMDQ_ENABLE;
763 : :
764 : 0 : return 0;
765 : : }
766 : :
767 : : int
768 : 0 : hinic3_reinit_cmdq_ctxts(struct hinic3_hwdev *hwdev)
769 : : {
770 : 0 : struct hinic3_cmdqs *cmdqs = hwdev->cmdqs;
771 : : enum hinic3_cmdq_type cmdq_type;
772 : :
773 [ # # ]: 0 : for (cmdq_type = HINIC3_CMDQ_SYNC; cmdq_type < HINIC3_MAX_CMDQ_TYPES; cmdq_type++) {
774 : 0 : cmdqs->cmdq[cmdq_type].wrapped = 1;
775 : 0 : hinic3_wq_wqe_pg_clear(cmdqs->cmdq[cmdq_type].wq);
776 : : }
777 : :
778 : 0 : return hinic3_set_cmdq_ctxts(hwdev);
779 : : }
780 : :
781 : : static int
782 : 0 : hinic3_set_cmdqs(struct hinic3_hwdev *hwdev, struct hinic3_cmdqs *cmdqs)
783 : : {
784 : 0 : void *db_base = NULL;
785 : : enum hinic3_cmdq_type type, cmdq_type;
786 : : int err;
787 : :
788 : 0 : err = hinic3_alloc_db_addr(hwdev, &db_base, HINIC3_DB_TYPE_CMDQ);
789 [ # # ]: 0 : if (err) {
790 : 0 : PMD_DRV_LOG(ERR, "Failed to allocate doorbell address");
791 : 0 : goto alloc_db_err;
792 : : }
793 : :
794 : 0 : cmdqs->cmdqs_db_base = (uint8_t *)db_base;
795 : :
796 [ # # ]: 0 : for (cmdq_type = HINIC3_CMDQ_SYNC; cmdq_type < HINIC3_MAX_CMDQ_TYPES; cmdq_type++) {
797 : 0 : err = init_cmdq(&cmdqs->cmdq[cmdq_type], hwdev,
798 : 0 : &cmdqs->saved_wqs[cmdq_type], cmdq_type);
799 [ # # ]: 0 : if (err) {
800 : 0 : PMD_DRV_LOG(ERR, "Initialize cmdq failed");
801 : 0 : goto init_cmdq_err;
802 : : }
803 : :
804 : : cmdq_init_queue_ctxt(&cmdqs->cmdq[cmdq_type],
805 : : &cmdqs->cmdq[cmdq_type].cmdq_ctxt);
806 : : }
807 : :
808 : 0 : err = hinic3_set_cmdq_ctxts(hwdev);
809 [ # # ]: 0 : if (err)
810 : 0 : goto init_cmdq_err;
811 : :
812 : : return 0;
813 : :
814 : 0 : init_cmdq_err:
815 [ # # ]: 0 : for (type = HINIC3_CMDQ_SYNC; type < cmdq_type; type++)
816 : : free_cmdq(&cmdqs->cmdq[type]);
817 : :
818 : 0 : alloc_db_err:
819 : 0 : hinic3_cmdq_free(cmdqs->saved_wqs, HINIC3_MAX_CMDQ_TYPES);
820 : 0 : return -ENOMEM;
821 : : }
822 : :
823 : : int
824 : 0 : hinic3_init_cmdqs(struct hinic3_hwdev *hwdev)
825 : : {
826 : : struct hinic3_cmdqs *cmdqs = NULL;
827 : : size_t saved_wqs_size;
828 : : char cmdq_pool_name[RTE_MEMPOOL_NAMESIZE];
829 : : int err;
830 : :
831 : 0 : cmdqs = rte_zmalloc(NULL, sizeof(*cmdqs), 0);
832 [ # # ]: 0 : if (!cmdqs)
833 : : return -ENOMEM;
834 : :
835 : 0 : hwdev->cmdqs = cmdqs;
836 : 0 : cmdqs->hwdev = hwdev;
837 : :
838 : : saved_wqs_size = HINIC3_MAX_CMDQ_TYPES * sizeof(struct hinic3_wq);
839 : 0 : cmdqs->saved_wqs = rte_zmalloc(NULL, saved_wqs_size, 0);
840 [ # # ]: 0 : if (!cmdqs->saved_wqs) {
841 : 0 : PMD_DRV_LOG(ERR, "Allocate saved wqs failed");
842 : : err = -ENOMEM;
843 : 0 : goto alloc_wqs_err;
844 : : }
845 : :
846 : : memset(cmdq_pool_name, 0, RTE_MEMPOOL_NAMESIZE);
847 : 0 : snprintf(cmdq_pool_name, sizeof(cmdq_pool_name), "hinic3_cmdq_%u",
848 : 0 : hwdev->port_id);
849 : :
850 : 0 : cmdqs->cmd_buf_pool = rte_pktmbuf_pool_create(cmdq_pool_name,
851 : : HINIC3_CMDQ_DEPTH * HINIC3_MAX_CMDQ_TYPES, 0, 0,
852 : 0 : HINIC3_CMDQ_BUF_SIZE, (int)rte_socket_id());
853 [ # # ]: 0 : if (!cmdqs->cmd_buf_pool) {
854 : 0 : PMD_DRV_LOG(ERR, "Create cmdq buffer pool failed");
855 : : err = -ENOMEM;
856 : 0 : goto pool_create_err;
857 : : }
858 : :
859 : 0 : err = hinic3_cmdq_alloc(cmdqs->saved_wqs, hwdev, HINIC3_MAX_CMDQ_TYPES,
860 : : HINIC3_CMDQ_WQ_BUF_SIZE, CMDQ_WQEBB_SHIFT,
861 : : HINIC3_CMDQ_DEPTH);
862 [ # # ]: 0 : if (err) {
863 : 0 : PMD_DRV_LOG(ERR, "Allocate cmdq failed");
864 : 0 : goto cmdq_alloc_err;
865 : : }
866 : :
867 : 0 : err = hinic3_set_cmdqs(hwdev, cmdqs);
868 [ # # ]: 0 : if (err) {
869 : 0 : PMD_DRV_LOG(ERR, "set_cmdqs failed");
870 : 0 : goto cmdq_alloc_err;
871 : : }
872 : : return 0;
873 : :
874 : 0 : cmdq_alloc_err:
875 : 0 : rte_mempool_free(cmdqs->cmd_buf_pool);
876 : :
877 : 0 : pool_create_err:
878 : 0 : rte_free(cmdqs->saved_wqs);
879 : :
880 : 0 : alloc_wqs_err:
881 : 0 : rte_free(cmdqs);
882 : :
883 : 0 : return err;
884 : : }
885 : :
886 : : void
887 : 0 : hinic3_free_cmdqs(struct hinic3_hwdev *hwdev)
888 : : {
889 : 0 : struct hinic3_cmdqs *cmdqs = hwdev->cmdqs;
890 : : enum hinic3_cmdq_type cmdq_type = HINIC3_CMDQ_SYNC;
891 : :
892 : 0 : cmdqs->status &= ~HINIC3_CMDQ_ENABLE;
893 : :
894 [ # # ]: 0 : for (; cmdq_type < HINIC3_MAX_CMDQ_TYPES; cmdq_type++)
895 : : free_cmdq(&cmdqs->cmdq[cmdq_type]);
896 : :
897 : 0 : hinic3_cmdq_free(cmdqs->saved_wqs, HINIC3_MAX_CMDQ_TYPES);
898 : 0 : rte_mempool_free(cmdqs->cmd_buf_pool);
899 : 0 : rte_free(cmdqs->saved_wqs);
900 : 0 : rte_free(cmdqs);
901 : 0 : }
902 : :
903 : : static int
904 : 0 : hinic3_cmdq_poll_msg(struct hinic3_cmdq *cmdq, uint32_t timeout)
905 : : {
906 : : struct hinic3_cmdq_wqe *wqe = NULL;
907 : : struct hinic3_cmdq_wqe_lcmd *wqe_lcmd = NULL;
908 : : struct hinic3_ctrl *ctrl = NULL;
909 : : struct hinic3_cmdq_cmd_info *cmd_info = NULL;
910 : : uint32_t status_info, ctrl_info;
911 : : uint16_t ci;
912 : : int errcode;
913 : : uint64_t end;
914 : : int done = 0;
915 : : int err = 0;
916 : :
917 : 0 : wqe = hinic3_read_wqe(cmdq->wq, 1, &ci);
918 [ # # ]: 0 : if (!wqe) {
919 : 0 : PMD_DRV_LOG(ERR, "No outstanding cmdq msg");
920 : 0 : return -EINVAL;
921 : : }
922 : :
923 : 0 : cmd_info = &cmdq->cmd_infos[ci];
924 [ # # ]: 0 : if (cmd_info->cmd_type == HINIC3_CMD_TYPE_NONE) {
925 : 0 : PMD_DRV_LOG(ERR,
926 : : "Cmdq msg has not been filled and send to hw, or get TMO msg ack. cmdq ci: %u",
927 : : ci);
928 : 0 : return -EINVAL;
929 : : }
930 : :
931 : : /* Only arm bit is using scmd wqe, the wqe is lcmd. */
932 : : wqe_lcmd = &wqe->wqe_lcmd;
933 : : ctrl = &wqe_lcmd->ctrl;
934 : 0 : end = cycles + msecs_to_cycles(timeout);
935 : : do {
936 : 0 : ctrl_info = hinic3_hw_cpu32((ctrl)->ctrl_info);
937 [ # # ]: 0 : if (WQE_COMPLETED(ctrl_info)) {
938 : : done = 1;
939 : : break;
940 : : }
941 : :
942 : 0 : rte_delay_us(1);
943 [ # # ]: 0 : } while (time_before(cycles, end));
944 : :
945 [ # # ]: 0 : if (done) {
946 : 0 : status_info = hinic3_hw_cpu32(wqe_lcmd->status.status_info);
947 : 0 : errcode = WQE_ERRCODE_GET(status_info, VAL);
948 : 0 : cmdq_update_errcode(cmdq, ci, errcode);
949 : 0 : clear_wqe_complete_bit(cmdq, wqe);
950 : : err = 0;
951 : : } else {
952 : 0 : PMD_DRV_LOG(ERR, "Poll cmdq msg time out, ci: %u", ci);
953 : : err = -ETIMEDOUT;
954 : : }
955 : :
956 : : /* Set this cmd invalid. */
957 : 0 : cmd_info->cmd_type = HINIC3_CMD_TYPE_NONE;
958 : :
959 : 0 : return err;
960 : : }
|