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