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 "base/hinic3_compat.h"
6 : : #include "base/hinic3_nic_cfg.h"
7 : : #include "base/hinic3_hwdev.h"
8 : : #include "hinic3_nic_io.h"
9 : : #include "hinic3_ethdev.h"
10 : : #include "hinic3_tx.h"
11 : :
12 : : #define HINIC3_TX_TASK_WRAPPED 1
13 : : #define HINIC3_TX_BD_DESC_WRAPPED 2
14 : :
15 : : #define TX_MSS_DEFAULT 0x3E00
16 : : #define TX_MSS_MIN 0x50
17 : :
18 : : #define HINIC3_MAX_TX_FREE_BULK 64
19 : :
20 : : #define MAX_PAYLOAD_OFFSET 221
21 : :
22 : : #define HINIC3_TX_OUTER_CHECKSUM_FLAG_SET 1
23 : : #define HINIC3_TX_OUTER_CHECKSUM_FLAG_NO_SET 0
24 : :
25 : : #define HINIC3_TX_OFFLOAD_MASK \
26 : : (HINIC3_TX_CKSUM_OFFLOAD_MASK | HINIC3_PKT_TX_VLAN_PKT)
27 : :
28 : : #define HINIC3_TX_CKSUM_OFFLOAD_MASK \
29 : : (HINIC3_PKT_TX_IP_CKSUM | HINIC3_PKT_TX_TCP_CKSUM | \
30 : : HINIC3_PKT_TX_UDP_CKSUM | HINIC3_PKT_TX_SCTP_CKSUM | \
31 : : HINIC3_PKT_TX_OUTER_IP_CKSUM | HINIC3_PKT_TX_TCP_SEG)
32 : :
33 : : static inline uint16_t
34 : : hinic3_get_sq_free_wqebbs(struct hinic3_txq *sq)
35 : : {
36 : 0 : return ((sq->q_depth -
37 : 0 : (((sq->prod_idx - sq->cons_idx) + sq->q_depth) & sq->q_mask)) - 1);
38 : : }
39 : :
40 : : static inline void
41 : : hinic3_update_sq_local_ci(struct hinic3_txq *sq, uint16_t wqe_cnt)
42 : : {
43 : 0 : sq->cons_idx += wqe_cnt;
44 : : }
45 : :
46 : : static inline uint16_t
47 : : hinic3_get_sq_local_ci(struct hinic3_txq *sq)
48 : : {
49 : 0 : return MASKED_QUEUE_IDX(sq, sq->cons_idx);
50 : : }
51 : :
52 : : static inline uint16_t
53 : : hinic3_get_sq_hw_ci(struct hinic3_txq *sq)
54 : : {
55 : 0 : return MASKED_QUEUE_IDX(sq, hinic3_hw_cpu16(*sq->ci_vaddr_base));
56 : : }
57 : :
58 : : static void *
59 : : hinic3_get_sq_wqe(struct hinic3_txq *sq, struct hinic3_wqe_info *wqe_info)
60 : : {
61 : 0 : uint16_t cur_pi = MASKED_QUEUE_IDX(sq, sq->prod_idx);
62 : : uint32_t end_pi;
63 : :
64 : 0 : end_pi = cur_pi + wqe_info->wqebb_cnt;
65 : 0 : sq->prod_idx += wqe_info->wqebb_cnt;
66 : :
67 : 0 : wqe_info->owner = (uint8_t)(sq->owner);
68 : 0 : wqe_info->pi = cur_pi;
69 : 0 : wqe_info->wrapped = 0;
70 : :
71 [ # # ]: 0 : if (unlikely(end_pi >= sq->q_depth)) {
72 : 0 : sq->owner = !sq->owner;
73 : :
74 [ # # ]: 0 : if (likely(end_pi > sq->q_depth))
75 : 0 : wqe_info->wrapped = (uint8_t)(sq->q_depth - cur_pi);
76 : : }
77 : :
78 : 0 : return NIC_WQE_ADDR(sq, cur_pi);
79 : : }
80 : :
81 : : static inline void
82 : : hinic3_put_sq_wqe(struct hinic3_txq *sq, struct hinic3_wqe_info *wqe_info)
83 : : {
84 [ # # # # ]: 0 : if (wqe_info->owner != sq->owner)
85 : 0 : sq->owner = wqe_info->owner;
86 : :
87 : 0 : sq->prod_idx -= wqe_info->wqebb_cnt;
88 : : }
89 : :
90 : : /**
91 : : * Sets the WQE combination information in the transmit queue (SQ).
92 : : *
93 : : * @param[in] txq
94 : : * Point to send queue.
95 : : * @param[out] wqe_combo
96 : : * Point to wqe_combo of send queue(SQ).
97 : : * @param[in] wqe
98 : : * Point to wqe of send queue(SQ).
99 : : * @param[in] wqe_info
100 : : * Point to wqe_info of send queue(SQ).
101 : : */
102 : : static void
103 : 0 : hinic3_set_wqe_combo(struct hinic3_txq *txq,
104 : : struct hinic3_sq_wqe_combo *wqe_combo,
105 : : struct hinic3_sq_wqe *wqe,
106 : : struct hinic3_wqe_info *wqe_info)
107 : : {
108 : 0 : wqe_combo->hdr = &wqe->compact_wqe.wqe_desc;
109 : :
110 [ # # ]: 0 : if (wqe_info->offload) {
111 [ # # ]: 0 : if (wqe_info->wrapped == HINIC3_TX_TASK_WRAPPED) {
112 : 0 : wqe_combo->task = (struct hinic3_sq_task *)
113 : 0 : (void *)txq->sq_head_addr;
114 : 0 : wqe_combo->bds_head = (struct hinic3_sq_bufdesc *)
115 : 0 : (void *)(txq->sq_head_addr + txq->wqebb_size);
116 [ # # ]: 0 : } else if (wqe_info->wrapped == HINIC3_TX_BD_DESC_WRAPPED) {
117 : 0 : wqe_combo->task = &wqe->extend_wqe.task;
118 : 0 : wqe_combo->bds_head = (struct hinic3_sq_bufdesc *)
119 : 0 : (void *)(txq->sq_head_addr);
120 : : } else {
121 : 0 : wqe_combo->task = &wqe->extend_wqe.task;
122 : 0 : wqe_combo->bds_head = wqe->extend_wqe.buf_desc;
123 : : }
124 : :
125 : 0 : wqe_combo->wqe_type = SQ_WQE_EXTENDED_TYPE;
126 : 0 : wqe_combo->task_type = SQ_WQE_TASKSECT_16BYTES;
127 : :
128 : 0 : return;
129 : : }
130 : :
131 [ # # ]: 0 : if (wqe_info->wrapped == HINIC3_TX_TASK_WRAPPED) {
132 : 0 : wqe_combo->bds_head = (struct hinic3_sq_bufdesc *)
133 : 0 : (void *)(txq->sq_head_addr);
134 : : } else {
135 : 0 : wqe_combo->bds_head =
136 : 0 : (struct hinic3_sq_bufdesc *)(&wqe->extend_wqe.task);
137 : : }
138 : :
139 [ # # ]: 0 : if (wqe_info->wqebb_cnt > 1) {
140 : 0 : wqe_combo->wqe_type = SQ_WQE_EXTENDED_TYPE;
141 : 0 : wqe_combo->task_type = SQ_WQE_TASKSECT_46BITS;
142 : :
143 : : /* This section used as vlan insert, needs to clear. */
144 : 0 : wqe_combo->bds_head->rsvd = 0;
145 : : } else {
146 : 0 : wqe_combo->wqe_type = SQ_WQE_COMPACT_TYPE;
147 : : }
148 : : }
149 : :
150 : : int
151 : 0 : hinic3_start_all_sqs(struct rte_eth_dev *eth_dev)
152 : : {
153 : : struct hinic3_nic_dev *nic_dev = NULL;
154 : : struct hinic3_txq *txq = NULL;
155 : : int i;
156 : :
157 : 0 : nic_dev = HINIC3_ETH_DEV_TO_PRIVATE_NIC_DEV(eth_dev);
158 : :
159 [ # # ]: 0 : for (i = 0; i < nic_dev->num_sqs; i++) {
160 : 0 : txq = eth_dev->data->tx_queues[i];
161 [ # # ]: 0 : if (txq->tx_deferred_start)
162 : 0 : continue;
163 : 0 : HINIC3_SET_TXQ_STARTED(txq);
164 : 0 : eth_dev->data->tx_queue_state[i] = RTE_ETH_QUEUE_STATE_STARTED;
165 : : }
166 : :
167 : 0 : return 0;
168 : : }
169 : :
170 : : static inline void
171 : : hinic3_free_cpy_mbuf(struct hinic3_nic_dev *nic_dev __rte_unused,
172 : : struct rte_mbuf *cpy_skb)
173 : : {
174 : 0 : rte_pktmbuf_free(cpy_skb);
175 : : }
176 : :
177 : : /**
178 : : * Cleans up buffers (mbuf) in the send queue (txq) and returns these buffers to
179 : : * their memory pool.
180 : : *
181 : : * @param[in] txq
182 : : * Point to send queue.
183 : : * @param[in] free_cnt
184 : : * Number of mbufs to be released.
185 : : * @return
186 : : * Number of released mbufs.
187 : : */
188 : : static int
189 : 0 : hinic3_xmit_mbuf_cleanup(struct hinic3_txq *txq, uint32_t free_cnt)
190 : : {
191 : : struct hinic3_tx_info *tx_info = NULL;
192 : : struct rte_mbuf *mbuf = NULL;
193 : : struct rte_mbuf *mbuf_temp = NULL;
194 : : struct rte_mbuf *mbuf_free[HINIC3_MAX_TX_FREE_BULK];
195 : :
196 : : int nb_free = 0;
197 : : int wqebb_cnt = 0;
198 : : uint16_t hw_ci, sw_ci, sq_mask;
199 : : uint32_t i;
200 : :
201 : : hw_ci = hinic3_get_sq_hw_ci(txq);
202 : : sw_ci = hinic3_get_sq_local_ci(txq);
203 : : sq_mask = txq->q_mask;
204 : :
205 [ # # ]: 0 : for (i = 0; i < free_cnt; ++i) {
206 : 0 : tx_info = &txq->tx_info[sw_ci];
207 [ # # ]: 0 : if (hw_ci == sw_ci ||
208 [ # # ]: 0 : (((hw_ci - sw_ci) & sq_mask) < tx_info->wqebb_cnt))
209 : : break;
210 : : /*
211 : : * The cpy_mbuf is usually used in the arge-sized package
212 : : * scenario.
213 : : */
214 [ # # ]: 0 : if (unlikely(tx_info->cpy_mbuf != NULL)) {
215 : : hinic3_free_cpy_mbuf(txq->nic_dev, tx_info->cpy_mbuf);
216 : 0 : tx_info->cpy_mbuf = NULL;
217 : : }
218 : 0 : sw_ci = (sw_ci + tx_info->wqebb_cnt) & sq_mask;
219 : :
220 : 0 : wqebb_cnt += tx_info->wqebb_cnt;
221 : 0 : mbuf = tx_info->mbuf;
222 : :
223 [ # # ]: 0 : if (likely(mbuf->nb_segs == 1)) {
224 : : mbuf_temp = rte_pktmbuf_prefree_seg(mbuf);
225 : 0 : tx_info->mbuf = NULL;
226 [ # # ]: 0 : if (unlikely(mbuf_temp == NULL))
227 : 0 : continue;
228 : :
229 : 0 : mbuf_free[nb_free++] = mbuf_temp;
230 : : /*
231 : : * If the pools of different mbufs are different,
232 : : * release the mbufs of the same pool.
233 : : */
234 [ # # # # ]: 0 : if (unlikely(mbuf_temp->pool != mbuf_free[0]->pool ||
235 : : nb_free >= HINIC3_MAX_TX_FREE_BULK)) {
236 [ # # ]: 0 : rte_mempool_put_bulk(mbuf_free[0]->pool,
237 : : (void **)mbuf_free,
238 : : (nb_free - 1));
239 : : nb_free = 0;
240 : 0 : mbuf_free[nb_free++] = mbuf_temp;
241 : : }
242 : : } else {
243 : 0 : rte_pktmbuf_free(mbuf);
244 : 0 : tx_info->mbuf = NULL;
245 : : }
246 : : }
247 : :
248 [ # # ]: 0 : if (nb_free > 0)
249 [ # # ]: 0 : rte_mempool_put_bulk(mbuf_free[0]->pool, (void **)mbuf_free, nb_free);
250 : :
251 : 0 : hinic3_update_sq_local_ci(txq, wqebb_cnt);
252 : :
253 : 0 : return i;
254 : : }
255 : :
256 : : static inline void
257 : : hinic3_tx_free_mbuf_force(struct hinic3_txq *txq __rte_unused,
258 : : struct rte_mbuf *mbuf)
259 : : {
260 : 0 : rte_pktmbuf_free(mbuf);
261 : : }
262 : :
263 : : /**
264 : : * Release the mbuf and update the consumer index for sending queue.
265 : : *
266 : : * @param[in] txq
267 : : * Point to send queue.
268 : : */
269 : : void
270 : 0 : hinic3_free_txq_mbufs(struct hinic3_txq *txq)
271 : : {
272 : : struct hinic3_tx_info *tx_info = NULL;
273 : : uint16_t free_wqebbs;
274 : : uint16_t ci;
275 : :
276 : : free_wqebbs = hinic3_get_sq_free_wqebbs(txq) + 1;
277 : :
278 [ # # ]: 0 : while (free_wqebbs < txq->q_depth) {
279 : : ci = hinic3_get_sq_local_ci(txq);
280 : :
281 : 0 : tx_info = &txq->tx_info[ci];
282 [ # # ]: 0 : if (unlikely(tx_info->cpy_mbuf != NULL)) {
283 : : hinic3_free_cpy_mbuf(txq->nic_dev, tx_info->cpy_mbuf);
284 : 0 : tx_info->cpy_mbuf = NULL;
285 : : }
286 : 0 : hinic3_tx_free_mbuf_force(txq, tx_info->mbuf);
287 : 0 : hinic3_update_sq_local_ci(txq, tx_info->wqebb_cnt);
288 : :
289 : 0 : free_wqebbs = (uint16_t)(free_wqebbs + tx_info->wqebb_cnt);
290 : 0 : tx_info->mbuf = NULL;
291 : : }
292 : 0 : }
293 : :
294 : : void
295 : 0 : hinic3_free_all_txq_mbufs(struct hinic3_nic_dev *nic_dev)
296 : : {
297 : : uint16_t qid;
298 [ # # ]: 0 : for (qid = 0; qid < nic_dev->num_sqs; qid++)
299 : 0 : hinic3_free_txq_mbufs(nic_dev->txqs[qid]);
300 : 0 : }
301 : :
302 : : int
303 : 0 : hinic3_tx_done_cleanup(void *txq, uint32_t free_cnt)
304 : : {
305 : : struct hinic3_txq *tx_queue = txq;
306 [ # # ]: 0 : uint32_t try_free_cnt = !free_cnt ? tx_queue->q_depth : free_cnt;
307 : :
308 : 0 : return hinic3_xmit_mbuf_cleanup(tx_queue, try_free_cnt);
309 : : }
310 : :
311 : : /**
312 : : * Prepare the data packet to be sent and calculate the internal L3 offset.
313 : : *
314 : : * @param[in] mbuf
315 : : * Point to the mbuf to be processed.
316 : : * @param[out] inner_l3_offset
317 : : * Inner(IP Layer) L3 layer offset.
318 : : * @return
319 : : * 0 as success, -EINVAL as failure.
320 : : */
321 : : static int
322 : : hinic3_tx_offload_pkt_prepare(struct rte_mbuf *mbuf, uint16_t *inner_l3_offset)
323 : : {
324 : : uint64_t ol_flags = mbuf->ol_flags;
325 : :
326 : : /* Only support vxlan offload. */
327 : 0 : if ((ol_flags & HINIC3_PKT_TX_TUNNEL_MASK) &&
328 [ # # ]: 0 : (!(ol_flags & HINIC3_PKT_TX_TUNNEL_VXLAN)))
329 : : return -EINVAL;
330 : :
331 : : #ifdef RTE_LIBRTE_ETHDEV_DEBUG
332 : : if (rte_validate_tx_offload(mbuf) != 0)
333 : : return -EINVAL;
334 : : #endif
335 : : /* Support tunnel. */
336 [ # # ]: 0 : if ((ol_flags & HINIC3_PKT_TX_TUNNEL_MASK)) {
337 : 0 : if ((ol_flags & HINIC3_PKT_TX_OUTER_IP_CKSUM) ||
338 [ # # ]: 0 : (ol_flags & HINIC3_PKT_TX_OUTER_IPV6) ||
339 : : (ol_flags & HINIC3_PKT_TX_TCP_SEG)) {
340 : : /*
341 : : * For this senmatic, l2_len of mbuf means
342 : : * len(out_udp + vxlan + in_eth).
343 : : */
344 : 0 : *inner_l3_offset = mbuf->l2_len + mbuf->outer_l2_len +
345 : 0 : mbuf->outer_l3_len;
346 : : } else {
347 : : /*
348 : : * For this senmatic, l2_len of mbuf means
349 : : * len(out_eth + out_ip + out_udp + vxlan + in_eth).
350 : : */
351 : 0 : *inner_l3_offset = mbuf->l2_len;
352 : : }
353 : : } else {
354 : : /* For non-tunnel type pkts. */
355 : 0 : *inner_l3_offset = mbuf->l2_len;
356 : : }
357 : :
358 : : return 0;
359 : : }
360 : :
361 : : static inline void
362 : : hinic3_set_vlan_tx_offload(struct hinic3_sq_task *task, uint16_t vlan_tag,
363 : : uint8_t vlan_type)
364 : : {
365 : 0 : task->vlan_offload = SQ_TASK_INFO3_SET(vlan_tag, VLAN_TAG) |
366 : 0 : SQ_TASK_INFO3_SET(vlan_type, VLAN_TYPE) |
367 : : SQ_TASK_INFO3_SET(1U, VLAN_TAG_VALID);
368 : : }
369 : :
370 : : /**
371 : : * Set the corresponding offload information based on ol_flags of the mbuf.
372 : : *
373 : : * @param[in] mbuf
374 : : * Point to the mbuf for which offload needs to be set in the sending queue.
375 : : * @param[out] task
376 : : * Point to task of send queue(SQ).
377 : : * @param[out] wqe_info
378 : : * Point to wqe_info of send queue(SQ).
379 : : * @return
380 : : * 0 as success, -EINVAL as failure.
381 : : */
382 : : static int
383 : 0 : hinic3_set_tx_offload(struct rte_mbuf *mbuf, struct hinic3_sq_task *task,
384 : : struct hinic3_wqe_info *wqe_info)
385 : : {
386 : 0 : uint64_t ol_flags = mbuf->ol_flags;
387 : : uint16_t pld_offset = 0;
388 : : uint32_t queue_info = 0;
389 : : uint16_t vlan_tag;
390 : :
391 : 0 : task->pkt_info0 = 0;
392 : 0 : task->ip_identify = 0;
393 : 0 : task->pkt_info2 = 0;
394 : 0 : task->vlan_offload = 0;
395 : :
396 : : /* Vlan offload. */
397 [ # # ]: 0 : if (unlikely(ol_flags & HINIC3_PKT_TX_VLAN_PKT)) {
398 : 0 : vlan_tag = mbuf->vlan_tci;
399 : : hinic3_set_vlan_tx_offload(task, vlan_tag, HINIC3_TX_TPID0);
400 : : task->vlan_offload = hinic3_hw_be32(task->vlan_offload);
401 : : }
402 : : /* Cksum offload. */
403 [ # # ]: 0 : if (!(ol_flags & HINIC3_TX_CKSUM_OFFLOAD_MASK))
404 : : return 0;
405 : :
406 : : /* Tso offload. */
407 [ # # ]: 0 : if (ol_flags & HINIC3_PKT_TX_TCP_SEG) {
408 : 0 : pld_offset = wqe_info->payload_offset;
409 [ # # ]: 0 : if ((pld_offset >> 1) > MAX_PAYLOAD_OFFSET)
410 : : return -EINVAL;
411 : :
412 : : task->pkt_info0 |= SQ_TASK_INFO0_SET(1U, INNER_L4_EN);
413 : 0 : task->pkt_info0 |= SQ_TASK_INFO0_SET(1U, INNER_L3_EN);
414 : :
415 : : queue_info |= SQ_CTRL_QUEUE_INFO_SET(1U, TSO);
416 : 0 : queue_info |= SQ_CTRL_QUEUE_INFO_SET(pld_offset >> 1, PLDOFF);
417 : :
418 : : /* Set MSS value. */
419 : : queue_info = SQ_CTRL_QUEUE_INFO_CLEAR(queue_info, MSS);
420 : 0 : queue_info |= SQ_CTRL_QUEUE_INFO_SET(mbuf->tso_segsz, MSS);
421 : : } else {
422 [ # # ]: 0 : if (ol_flags & HINIC3_PKT_TX_IP_CKSUM)
423 : 0 : task->pkt_info0 |= SQ_TASK_INFO0_SET(1U, INNER_L3_EN);
424 : :
425 [ # # # ]: 0 : switch (ol_flags & HINIC3_PKT_TX_L4_MASK) {
426 : 0 : case HINIC3_PKT_TX_TCP_CKSUM:
427 : : case HINIC3_PKT_TX_UDP_CKSUM:
428 : : case HINIC3_PKT_TX_SCTP_CKSUM:
429 : 0 : task->pkt_info0 |= SQ_TASK_INFO0_SET(1U, INNER_L4_EN);
430 : 0 : break;
431 : :
432 : : case HINIC3_PKT_TX_L4_NO_CKSUM:
433 : : break;
434 : :
435 : 0 : default:
436 : 0 : PMD_DRV_LOG(INFO, "not support pkt type");
437 : 0 : return -EINVAL;
438 : : }
439 : : }
440 : :
441 : : /* For vxlan, also can support PKT_TX_TUNNEL_GRE, etc. */
442 [ # # # ]: 0 : switch (ol_flags & HINIC3_PKT_TX_TUNNEL_MASK) {
443 : 0 : case HINIC3_PKT_TX_TUNNEL_VXLAN:
444 : 0 : task->pkt_info0 |= SQ_TASK_INFO0_SET(1U, TUNNEL_FLAG);
445 : 0 : break;
446 : :
447 : : case 0:
448 : : break;
449 : :
450 : 0 : default:
451 : : /* For non UDP/GRE tunneling, drop the tunnel packet. */
452 : 0 : PMD_DRV_LOG(INFO, "not support tunnel pkt type");
453 : 0 : return -EINVAL;
454 : : }
455 : :
456 [ # # ]: 0 : if (ol_flags & HINIC3_PKT_TX_OUTER_IP_CKSUM)
457 : 0 : task->pkt_info0 |= SQ_TASK_INFO0_SET(1U, OUT_L3_EN);
458 : :
459 : : task->pkt_info0 = hinic3_hw_be32(task->pkt_info0);
460 : : task->pkt_info2 = hinic3_hw_be32(task->pkt_info2);
461 : 0 : wqe_info->queue_info = queue_info;
462 : :
463 : 0 : return 0;
464 : : }
465 : :
466 : : /**
467 : : * Check whether the number of segments in the mbuf is valid.
468 : : *
469 : : * @param[in] mbuf
470 : : * Point to the mbuf to be verified.
471 : : * @param[in] wqe_info
472 : : * Point to wqe_info of send queue(SQ).
473 : : * @return
474 : : * true as valid, false as invalid.
475 : : */
476 : : static bool
477 : 0 : hinic3_is_tso_sge_valid(struct rte_mbuf *mbuf, struct hinic3_wqe_info *wqe_info)
478 : : {
479 : : uint32_t total_len, limit_len, checked_len, left_len, adjust_mss;
480 : : uint32_t i, max_sges, left_sges, first_len;
481 : : struct rte_mbuf *mbuf_head, *mbuf_first;
482 : : struct rte_mbuf *mbuf_pre = mbuf;
483 : :
484 : 0 : left_sges = mbuf->nb_segs;
485 : : mbuf_head = mbuf;
486 : : mbuf_first = mbuf;
487 : :
488 : : /* Tso sge number validation. */
489 [ # # ]: 0 : if (unlikely(left_sges >= HINIC3_NONTSO_PKT_MAX_SGE)) {
490 : : checked_len = 0;
491 : : total_len = 0;
492 : : first_len = 0;
493 : 0 : adjust_mss = mbuf->tso_segsz >= TX_MSS_MIN ? mbuf->tso_segsz
494 : 0 : : TX_MSS_MIN;
495 : : max_sges = HINIC3_NONTSO_PKT_MAX_SGE - 1;
496 : 0 : limit_len = adjust_mss + wqe_info->payload_offset;
497 : :
498 [ # # ]: 0 : for (i = 0; (i < max_sges) && (total_len < limit_len); i++) {
499 : 0 : total_len += mbuf->data_len;
500 : : mbuf_pre = mbuf;
501 : 0 : mbuf = mbuf->next;
502 : : }
503 : :
504 : : /* Each continues 38 mbufs segmust do one check. */
505 [ # # ]: 0 : while (left_sges >= HINIC3_NONTSO_PKT_MAX_SGE) {
506 [ # # ]: 0 : if (total_len >= limit_len) {
507 : : /* Update the limit len. */
508 : : limit_len = adjust_mss;
509 : : /* Update checked len. */
510 : 0 : checked_len += first_len;
511 : : /* Record the first len. */
512 : 0 : first_len = mbuf_first->data_len;
513 : : /* First mbuf move to the next. */
514 : 0 : mbuf_first = mbuf_first->next;
515 : : /* Update total len. */
516 : 0 : total_len -= first_len;
517 : 0 : left_sges--;
518 : 0 : i--;
519 : 0 : for (;
520 [ # # ]: 0 : (i < max_sges) && (total_len < limit_len);
521 : 0 : i++) {
522 : 0 : total_len += mbuf->data_len;
523 : : mbuf_pre = mbuf;
524 : 0 : mbuf = mbuf->next;
525 : : }
526 : : } else {
527 : : /* Try to copy if not valid. */
528 : 0 : checked_len += (total_len - mbuf_pre->data_len);
529 : :
530 : 0 : left_len = mbuf_head->pkt_len - checked_len;
531 [ # # ]: 0 : if (left_len > HINIC3_COPY_MBUF_SIZE)
532 : : return false;
533 : 0 : wqe_info->sge_cnt = (uint16_t)(mbuf_head->nb_segs +
534 : : i - left_sges);
535 : 0 : wqe_info->cpy_mbuf_cnt = 1;
536 : :
537 : 0 : return true;
538 : : }
539 : : } /**< End of while. */
540 : : }
541 : :
542 : 0 : wqe_info->sge_cnt = mbuf_head->nb_segs;
543 : :
544 : 0 : return true;
545 : : }
546 : :
547 : : /**
548 : : * Checks and processes transport offload information for data packets.
549 : : *
550 : : * @param[in] mbuf
551 : : * Point to the mbuf to send.
552 : : * @param[in] wqe_info
553 : : * Point to wqe_info of send queue(SQ).
554 : : * @return
555 : : * 0 as success, -EINVAL as failure.
556 : : */
557 : : static int
558 : 0 : hinic3_get_tx_offload(struct rte_mbuf *mbuf, struct hinic3_wqe_info *wqe_info)
559 : : {
560 : 0 : uint64_t ol_flags = mbuf->ol_flags;
561 : : uint16_t i, total_len, inner_l3_offset = 0;
562 : : int err;
563 : : struct rte_mbuf *mbuf_pkt = NULL;
564 : :
565 : 0 : wqe_info->sge_cnt = mbuf->nb_segs;
566 : : /* Check if the packet set available offload flags. */
567 [ # # ]: 0 : if (!(ol_flags & HINIC3_TX_OFFLOAD_MASK)) {
568 : 0 : wqe_info->offload = 0;
569 : 0 : return 0;
570 : : }
571 : :
572 [ # # ]: 0 : wqe_info->offload = 1;
573 : : err = hinic3_tx_offload_pkt_prepare(mbuf, &inner_l3_offset);
574 : : if (err)
575 : : return err;
576 : :
577 : : /* Non tso mbuf only check sge num. */
578 [ # # ]: 0 : if (likely(!(mbuf->ol_flags & HINIC3_PKT_TX_TCP_SEG))) {
579 [ # # ]: 0 : if (unlikely(mbuf->pkt_len > MAX_SINGLE_SGE_SIZE))
580 : : /* Non tso packet len must less than 64KB. */
581 : : return -EINVAL;
582 : :
583 [ # # ]: 0 : if (likely(HINIC3_NONTSO_SEG_NUM_VALID(mbuf->nb_segs)))
584 : : /* Valid non-tso mbuf. */
585 : : return 0;
586 : :
587 : : /*
588 : : * The number of non-tso packet fragments must be less than 38,
589 : : * and mbuf segs greater than 38 must be copied to other
590 : : * buffers.
591 : : */
592 : : total_len = 0;
593 : : mbuf_pkt = mbuf;
594 [ # # ]: 0 : for (i = 0; i < (HINIC3_NONTSO_PKT_MAX_SGE - 1); i++) {
595 : 0 : total_len += mbuf_pkt->data_len;
596 : 0 : mbuf_pkt = mbuf_pkt->next;
597 : : }
598 : :
599 : : /* Default support copy total 4k mbuf segs. */
600 [ # # ]: 0 : if ((uint32_t)(total_len + (uint16_t)HINIC3_COPY_MBUF_SIZE) <
601 : : mbuf->pkt_len)
602 : : return -EINVAL;
603 : :
604 : 0 : wqe_info->sge_cnt = HINIC3_NONTSO_PKT_MAX_SGE;
605 : 0 : wqe_info->cpy_mbuf_cnt = 1;
606 : :
607 : 0 : return 0;
608 : : }
609 : :
610 : : /* Tso mbuf. */
611 : 0 : wqe_info->payload_offset =
612 : 0 : inner_l3_offset + mbuf->l3_len + mbuf->l4_len;
613 : :
614 : : /* Too many mbuf segs. */
615 [ # # ]: 0 : if (unlikely(HINIC3_TSO_SEG_NUM_INVALID(mbuf->nb_segs)))
616 : : return -EINVAL;
617 : :
618 : : /* Check whether can cover all tso mbuf segs or not. */
619 [ # # ]: 0 : if (unlikely(!hinic3_is_tso_sge_valid(mbuf, wqe_info)))
620 : 0 : return -EINVAL;
621 : :
622 : : return 0;
623 : : }
624 : :
625 : : static inline void
626 : : hinic3_set_buf_desc(struct hinic3_sq_bufdesc *buf_descs, rte_iova_t addr,
627 : : uint32_t len)
628 : : {
629 : 0 : buf_descs->hi_addr = hinic3_hw_be32(upper_32_bits(addr));
630 : 0 : buf_descs->lo_addr = hinic3_hw_be32(lower_32_bits(addr));
631 : 0 : buf_descs->len = hinic3_hw_be32(len);
632 : 0 : }
633 : :
634 : : static inline struct rte_mbuf *
635 : : hinic3_alloc_cpy_mbuf(struct hinic3_nic_dev *nic_dev)
636 : : {
637 : 0 : return rte_pktmbuf_alloc(nic_dev->cpy_mpool);
638 : : }
639 : :
640 : : /**
641 : : * Copy packets in the send queue(SQ).
642 : : *
643 : : * @param[in] nic_dev
644 : : * Point to nic device.
645 : : * @param[in] mbuf
646 : : * Point to the source mbuf.
647 : : * @param[in] seg_cnt
648 : : * Number of mbuf segments to be copied.
649 : : * @result
650 : : * The address of the copied mbuf.
651 : : */
652 : : static void *
653 : 0 : hinic3_copy_tx_mbuf(struct hinic3_nic_dev *nic_dev, struct rte_mbuf *mbuf,
654 : : uint16_t sge_cnt)
655 : : {
656 : : struct rte_mbuf *dst_mbuf;
657 : : uint32_t offset = 0;
658 : : uint16_t i;
659 : :
660 [ # # ]: 0 : if (unlikely(!nic_dev->cpy_mpool))
661 : : return NULL;
662 : :
663 : : dst_mbuf = hinic3_alloc_cpy_mbuf(nic_dev);
664 [ # # ]: 0 : if (unlikely(!dst_mbuf))
665 : : return NULL;
666 : :
667 : 0 : dst_mbuf->data_off = 0;
668 : 0 : dst_mbuf->data_len = 0;
669 [ # # ]: 0 : for (i = 0; i < sge_cnt; i++) {
670 : 0 : memcpy((uint8_t *)dst_mbuf->buf_addr + offset,
671 : 0 : (uint8_t *)mbuf->buf_addr + mbuf->data_off,
672 : 0 : mbuf->data_len);
673 : 0 : dst_mbuf->data_len += mbuf->data_len;
674 : 0 : offset += mbuf->data_len;
675 : 0 : mbuf = mbuf->next;
676 : : }
677 : 0 : dst_mbuf->pkt_len = dst_mbuf->data_len;
678 : :
679 : 0 : return dst_mbuf;
680 : : }
681 : :
682 : : /**
683 : : * Map the TX mbuf to the DMA address space and set related information for
684 : : * subsequent DMA transmission.
685 : : *
686 : : * @param[in] txq
687 : : * Point to send queue.
688 : : * @param[in] mbuf
689 : : * Point to the tx mbuf.
690 : : * @param[out] wqe_combo
691 : : * Point to send queue wqe_combo.
692 : : * @param[in] wqe_info
693 : : * Point to wqe_info of send queue(SQ).
694 : : * @result
695 : : * 0 as success, -EINVAL as failure.
696 : : */
697 : : static int
698 : 0 : hinic3_mbuf_dma_map_sge(struct hinic3_txq *txq, struct rte_mbuf *mbuf,
699 : : struct hinic3_sq_wqe_combo *wqe_combo,
700 : : struct hinic3_wqe_info *wqe_info)
701 : : {
702 : 0 : struct hinic3_sq_wqe_desc *wqe_desc = wqe_combo->hdr;
703 : 0 : struct hinic3_sq_bufdesc *buf_desc = wqe_combo->bds_head;
704 : :
705 : 0 : uint16_t nb_segs = wqe_info->sge_cnt - wqe_info->cpy_mbuf_cnt;
706 : 0 : uint16_t real_segs = mbuf->nb_segs;
707 : : rte_iova_t dma_addr;
708 : : uint32_t i;
709 : :
710 [ # # ]: 0 : for (i = 0; i < nb_segs; i++) {
711 [ # # ]: 0 : if (unlikely(mbuf == NULL)) {
712 : 0 : txq->txq_stats.mbuf_null++;
713 : 0 : return -EINVAL;
714 : : }
715 : :
716 [ # # ]: 0 : if (unlikely(mbuf->data_len == 0)) {
717 : 0 : txq->txq_stats.sge_len0++;
718 : 0 : return -EINVAL;
719 : : }
720 : :
721 : : dma_addr = rte_mbuf_data_iova(mbuf);
722 [ # # ]: 0 : if (i == 0) {
723 [ # # # # ]: 0 : if (wqe_combo->wqe_type == SQ_WQE_COMPACT_TYPE &&
724 : : mbuf->data_len > COMPACT_WQE_MAX_CTRL_LEN) {
725 : 0 : txq->txq_stats.sge_len_too_large++;
726 : 0 : return -EINVAL;
727 : : }
728 : :
729 : 0 : wqe_desc->hi_addr =
730 : 0 : hinic3_hw_be32(upper_32_bits(dma_addr));
731 : 0 : wqe_desc->lo_addr =
732 : 0 : hinic3_hw_be32(lower_32_bits(dma_addr));
733 : 0 : wqe_desc->ctrl_len = mbuf->data_len;
734 : : } else {
735 : : /*
736 : : * Parts of wqe is in sq bottom while parts
737 : : * of wqe is in sq head.
738 : : */
739 [ # # # # ]: 0 : if (unlikely(wqe_info->wrapped &&
740 : : (uint64_t)buf_desc == txq->sq_bot_sge_addr))
741 : 0 : buf_desc = (struct hinic3_sq_bufdesc *)
742 : 0 : (void *)txq->sq_head_addr;
743 : :
744 : 0 : hinic3_set_buf_desc(buf_desc, dma_addr, mbuf->data_len);
745 : 0 : buf_desc++;
746 : : }
747 : 0 : mbuf = mbuf->next;
748 : : }
749 : :
750 : : /* For now: support over 38 sge, copy the last 2 mbuf. */
751 [ # # ]: 0 : if (unlikely(wqe_info->cpy_mbuf_cnt != 0)) {
752 : : /*
753 : : * Copy invalid mbuf segs to a valid buffer, lost performance.
754 : : */
755 : 0 : txq->txq_stats.cpy_pkts += 1;
756 : 0 : mbuf = hinic3_copy_tx_mbuf(txq->nic_dev, mbuf,
757 : 0 : real_segs - nb_segs);
758 [ # # ]: 0 : if (unlikely(!mbuf))
759 : : return -EINVAL;
760 : :
761 [ # # ]: 0 : txq->tx_info[wqe_info->pi].cpy_mbuf = mbuf;
762 : :
763 : : /* Deal with the last mbuf. */
764 : : dma_addr = rte_mbuf_data_iova(mbuf);
765 [ # # ]: 0 : if (unlikely(mbuf->data_len == 0)) {
766 : 0 : txq->txq_stats.sge_len0++;
767 : 0 : return -EINVAL;
768 : : }
769 : : /*
770 : : * Parts of wqe is in sq bottom while parts
771 : : * of wqe is in sq head.
772 : : */
773 [ # # ]: 0 : if (i == 0) {
774 : 0 : wqe_desc->hi_addr =
775 : 0 : hinic3_hw_be32(upper_32_bits(dma_addr));
776 : 0 : wqe_desc->lo_addr =
777 : 0 : hinic3_hw_be32(lower_32_bits(dma_addr));
778 : 0 : wqe_desc->ctrl_len = mbuf->data_len;
779 : : } else {
780 [ # # # # ]: 0 : if (unlikely(wqe_info->wrapped &&
781 : : ((uint64_t)buf_desc == txq->sq_bot_sge_addr)))
782 : 0 : buf_desc = (struct hinic3_sq_bufdesc *)
783 : 0 : txq->sq_head_addr;
784 : :
785 : 0 : hinic3_set_buf_desc(buf_desc, dma_addr, mbuf->data_len);
786 : : }
787 : : }
788 : :
789 : : return 0;
790 : : }
791 : :
792 : : /**
793 : : * Sets and configures fields in the transmit queue control descriptor based on
794 : : * the WQE type.
795 : : *
796 : : * @param[out] wqe_combo
797 : : * Point to wqe_combo of send queue.
798 : : * @param[in] wqe_info
799 : : * Point to wqe_info of send queue.
800 : : */
801 : : static void
802 : 0 : hinic3_prepare_sq_ctrl(struct hinic3_sq_wqe_combo *wqe_combo,
803 : : struct hinic3_wqe_info *wqe_info)
804 : : {
805 : 0 : struct hinic3_sq_wqe_desc *wqe_desc = wqe_combo->hdr;
806 : :
807 [ # # ]: 0 : if (wqe_combo->wqe_type == SQ_WQE_COMPACT_TYPE) {
808 : 0 : wqe_desc->ctrl_len |=
809 : : SQ_CTRL_SET(SQ_NORMAL_WQE, DATA_FORMAT) |
810 : 0 : SQ_CTRL_SET(wqe_combo->wqe_type, EXTENDED) |
811 : 0 : SQ_CTRL_SET(wqe_info->owner, OWNER);
812 : : wqe_desc->ctrl_len = hinic3_hw_be32(wqe_desc->ctrl_len);
813 : :
814 : : /* Compact wqe queue_info will transfer to ucode. */
815 : 0 : wqe_desc->queue_info = 0;
816 : :
817 : 0 : return;
818 : : }
819 : :
820 : 0 : wqe_desc->ctrl_len |= SQ_CTRL_SET(wqe_info->sge_cnt, BUFDESC_NUM) |
821 : 0 : SQ_CTRL_SET(wqe_combo->task_type, TASKSECT_LEN) |
822 : 0 : SQ_CTRL_SET(SQ_NORMAL_WQE, DATA_FORMAT) |
823 : 0 : SQ_CTRL_SET(wqe_combo->wqe_type, EXTENDED) |
824 : 0 : SQ_CTRL_SET(wqe_info->owner, OWNER);
825 : :
826 : : wqe_desc->ctrl_len = hinic3_hw_be32(wqe_desc->ctrl_len);
827 : :
828 : 0 : wqe_desc->queue_info = wqe_info->queue_info;
829 : 0 : wqe_desc->queue_info |= SQ_CTRL_QUEUE_INFO_SET(1U, UC);
830 : :
831 [ # # ]: 0 : if (!SQ_CTRL_QUEUE_INFO_GET(wqe_desc->queue_info, MSS)) {
832 : 0 : wqe_desc->queue_info |=
833 : : SQ_CTRL_QUEUE_INFO_SET(TX_MSS_DEFAULT, MSS);
834 [ # # ]: 0 : } else if (SQ_CTRL_QUEUE_INFO_GET(wqe_desc->queue_info, MSS) <
835 : : TX_MSS_MIN) {
836 : : /* Mss should not less than 80. */
837 : : wqe_desc->queue_info =
838 : 0 : SQ_CTRL_QUEUE_INFO_CLEAR(wqe_desc->queue_info, MSS);
839 : 0 : wqe_desc->queue_info |= SQ_CTRL_QUEUE_INFO_SET(TX_MSS_MIN, MSS);
840 : : }
841 : :
842 : : wqe_desc->queue_info = hinic3_hw_be32(wqe_desc->queue_info);
843 : : }
844 : :
845 : : /**
846 : : * It is responsible for sending data packets.
847 : : *
848 : : * @param[in] tx_queue
849 : : * Point to send queue.
850 : : * @param[in] tx_pkts
851 : : * Pointer to the array of data packets to be sent.
852 : : * @param[in] nb_pkts
853 : : * Number of sent packets.
854 : : * @return
855 : : * Number of actually sent packets.
856 : : */
857 : : uint16_t
858 : 0 : hinic3_xmit_pkts(void *tx_queue, struct rte_mbuf **tx_pkts, uint16_t nb_pkts)
859 : : {
860 : : struct hinic3_txq *txq = tx_queue;
861 : : struct hinic3_tx_info *tx_info = NULL;
862 : : struct rte_mbuf *mbuf_pkt = NULL;
863 : 0 : struct hinic3_sq_wqe_combo wqe_combo = {0};
864 : : struct hinic3_sq_wqe *sq_wqe = NULL;
865 : 0 : struct hinic3_wqe_info wqe_info = {0};
866 : :
867 : : uint32_t offload_err, free_cnt;
868 : : uint64_t tx_bytes = 0;
869 : : uint16_t free_wqebb_cnt, nb_tx;
870 : : int err;
871 : :
872 : : #ifdef HINIC3_XSTAT_PROF_TX
873 : : uint64_t t1, t2;
874 : : t1 = rte_get_tsc_cycles();
875 : : #endif
876 : :
877 [ # # ]: 0 : if (unlikely(!HINIC3_TXQ_IS_STARTED(txq)))
878 : : return 0;
879 : :
880 : 0 : free_cnt = txq->tx_free_thresh;
881 : : /* Reclaim tx mbuf before xmit new packets. */
882 [ # # ]: 0 : if (hinic3_get_sq_free_wqebbs(txq) < txq->tx_free_thresh)
883 : 0 : hinic3_xmit_mbuf_cleanup(txq, free_cnt);
884 : :
885 : : /* Tx loop routine. */
886 [ # # ]: 0 : for (nb_tx = 0; nb_tx < nb_pkts; nb_tx++) {
887 : 0 : mbuf_pkt = *tx_pkts++;
888 [ # # ]: 0 : if (unlikely(hinic3_get_tx_offload(mbuf_pkt, &wqe_info))) {
889 : 0 : txq->txq_stats.offload_errors++;
890 : 0 : break;
891 : : }
892 : :
893 [ # # ]: 0 : if (!wqe_info.offload)
894 : 0 : wqe_info.wqebb_cnt = wqe_info.sge_cnt;
895 : : else
896 : : /* Use extended sq wqe with normal TS. */
897 : 0 : wqe_info.wqebb_cnt = wqe_info.sge_cnt + 1;
898 : :
899 : : free_wqebb_cnt = hinic3_get_sq_free_wqebbs(txq);
900 [ # # ]: 0 : if (unlikely(wqe_info.wqebb_cnt > free_wqebb_cnt)) {
901 : : /* Reclaim again. */
902 : 0 : hinic3_xmit_mbuf_cleanup(txq, free_cnt);
903 : : free_wqebb_cnt = hinic3_get_sq_free_wqebbs(txq);
904 [ # # ]: 0 : if (unlikely(wqe_info.wqebb_cnt > free_wqebb_cnt)) {
905 : 0 : txq->txq_stats.tx_busy += (nb_pkts - nb_tx);
906 : 0 : break;
907 : : }
908 : : }
909 : :
910 : : /* Get sq wqe address from wqe_page. */
911 : : sq_wqe = hinic3_get_sq_wqe(txq, &wqe_info);
912 [ # # ]: 0 : if (unlikely(!sq_wqe)) {
913 : 0 : txq->txq_stats.tx_busy++;
914 : 0 : break;
915 : : }
916 : :
917 : : /* Task or bd section maybe wrapped for one wqe. */
918 : 0 : hinic3_set_wqe_combo(txq, &wqe_combo, sq_wqe, &wqe_info);
919 : :
920 : 0 : wqe_info.queue_info = 0;
921 : : /* Fill tx packet offload into qsf and task field. */
922 [ # # ]: 0 : if (wqe_info.offload) {
923 : 0 : offload_err = hinic3_set_tx_offload(mbuf_pkt,
924 : : wqe_combo.task,
925 : : &wqe_info);
926 [ # # ]: 0 : if (unlikely(offload_err)) {
927 : : hinic3_put_sq_wqe(txq, &wqe_info);
928 : 0 : txq->txq_stats.offload_errors++;
929 : 0 : break;
930 : : }
931 : : }
932 : :
933 : : /* Fill sq_wqe buf_desc and bd_desc. */
934 : 0 : err = hinic3_mbuf_dma_map_sge(txq, mbuf_pkt, &wqe_combo,
935 : : &wqe_info);
936 [ # # ]: 0 : if (err) {
937 : : hinic3_put_sq_wqe(txq, &wqe_info);
938 : 0 : txq->txq_stats.offload_errors++;
939 : 0 : break;
940 : : }
941 : :
942 : : /* Record tx info. */
943 : 0 : tx_info = &txq->tx_info[wqe_info.pi];
944 : 0 : tx_info->mbuf = mbuf_pkt;
945 : 0 : tx_info->wqebb_cnt = wqe_info.wqebb_cnt;
946 : :
947 : 0 : hinic3_prepare_sq_ctrl(&wqe_combo, &wqe_info);
948 : :
949 : 0 : tx_bytes += mbuf_pkt->pkt_len;
950 : : }
951 : :
952 : : /* Update txq stats. */
953 [ # # ]: 0 : if (nb_tx) {
954 : 0 : hinic3_write_db(txq->db_addr, txq->q_id, (int)(txq->cos),
955 : : SQ_CFLAG_DP,
956 : 0 : MASKED_QUEUE_IDX(txq, txq->prod_idx));
957 : 0 : txq->txq_stats.packets += nb_tx;
958 : 0 : txq->txq_stats.bytes += tx_bytes;
959 : : }
960 : 0 : txq->txq_stats.burst_pkts = nb_tx;
961 : :
962 : : #ifdef HINIC3_XSTAT_PROF_TX
963 : : t2 = rte_get_tsc_cycles();
964 : : txq->txq_stats.app_tsc = t1 - txq->prof_tx_end_tsc;
965 : : txq->prof_tx_end_tsc = t2;
966 : : txq->txq_stats.pmd_tsc = t2 - t1;
967 : : txq->txq_stats.burst_pkts = nb_tx;
968 : : #endif
969 : :
970 : 0 : return nb_tx;
971 : : }
972 : :
973 : : int
974 : 0 : hinic3_stop_sq(struct hinic3_txq *txq)
975 : : {
976 : 0 : struct hinic3_nic_dev *nic_dev = txq->nic_dev;
977 : : uint64_t timeout;
978 : : int err = -EFAULT;
979 : : int free_wqebbs;
980 : :
981 : 0 : timeout = msecs_to_cycles(HINIC3_FLUSH_QUEUE_TIMEOUT) + cycles;
982 : : do {
983 : 0 : hinic3_tx_done_cleanup(txq, 0);
984 : 0 : free_wqebbs = hinic3_get_sq_free_wqebbs(txq) + 1;
985 [ # # ]: 0 : if (free_wqebbs == txq->q_depth) {
986 : : err = 0;
987 : : break;
988 : : }
989 : :
990 : 0 : rte_delay_us(1);
991 [ # # ]: 0 : } while (time_before(cycles, timeout));
992 : :
993 [ # # ]: 0 : if (err) {
994 : 0 : PMD_DRV_LOG(WARNING, "%s Wait sq empty timeout", nic_dev->dev_name);
995 : 0 : PMD_DRV_LOG(WARNING,
996 : : "queue_idx: %u, sw_ci: %u, hw_ci: %u, sw_pi: %u, free_wqebbs: %u, q_depth:%u",
997 : : txq->q_id,
998 : : hinic3_get_sq_local_ci(txq),
999 : : hinic3_get_sq_hw_ci(txq),
1000 : : MASKED_QUEUE_IDX(txq, txq->prod_idx),
1001 : : free_wqebbs,
1002 : : txq->q_depth);
1003 : : }
1004 : :
1005 : 0 : return err;
1006 : : }
1007 : :
1008 : : /**
1009 : : * Stop all sending queues (SQs).
1010 : : *
1011 : : * @param[in] txq
1012 : : * Point to send queue.
1013 : : */
1014 : : void
1015 : 0 : hinic3_flush_txqs(struct hinic3_nic_dev *nic_dev)
1016 : : {
1017 : : uint16_t qid;
1018 : : int err;
1019 : :
1020 [ # # ]: 0 : for (qid = 0; qid < nic_dev->num_sqs; qid++) {
1021 : 0 : err = hinic3_stop_sq(nic_dev->txqs[qid]);
1022 [ # # ]: 0 : if (err)
1023 : 0 : PMD_DRV_LOG(ERR, "Stop sq%d failed", qid);
1024 : : }
1025 : 0 : }
|