Branch data Line data Source code
1 : : /* SPDX-License-Identifier: BSD-3-Clause
2 : : * Copyright(c) 2023 Intel Corporation
3 : : */
4 : :
5 : : #include <ethdev_driver.h>
6 : : #include <rte_net.h>
7 : : #include <rte_vect.h>
8 : :
9 : : #include "cpfl_ethdev.h"
10 : : #include "cpfl_rxtx.h"
11 : : #include "cpfl_rxtx_vec_common.h"
12 : :
13 : : static inline void
14 : 0 : cpfl_tx_hairpin_descq_reset(struct ci_tx_queue *txq)
15 : : {
16 : : uint32_t i, size;
17 : :
18 [ # # ]: 0 : if (!txq) {
19 : 0 : PMD_DRV_LOG(DEBUG, "Pointer to txq is NULL");
20 : 0 : return;
21 : : }
22 : :
23 : 0 : size = txq->nb_tx_desc * CPFL_P2P_DESC_LEN;
24 [ # # ]: 0 : for (i = 0; i < size; i++)
25 : 0 : ((volatile char *)txq->desc_ring)[i] = 0;
26 : : }
27 : :
28 : : static inline void
29 : 0 : cpfl_tx_hairpin_complq_reset(struct ci_tx_queue *cq)
30 : : {
31 : : uint32_t i, size;
32 : :
33 [ # # ]: 0 : if (!cq) {
34 : 0 : PMD_DRV_LOG(DEBUG, "Pointer to complq is NULL");
35 : 0 : return;
36 : : }
37 : :
38 : 0 : size = cq->nb_tx_desc * CPFL_P2P_DESC_LEN;
39 [ # # ]: 0 : for (i = 0; i < size; i++)
40 : 0 : ((volatile char *)cq->compl_ring)[i] = 0;
41 : : }
42 : :
43 : : static inline void
44 : : cpfl_rx_hairpin_descq_reset(struct idpf_rx_queue *rxq)
45 : : {
46 : : uint16_t len;
47 : : uint32_t i;
48 : :
49 : : if (!rxq)
50 : : return;
51 : :
52 : 0 : len = rxq->nb_rx_desc;
53 [ # # ]: 0 : for (i = 0; i < len * CPFL_P2P_DESC_LEN; i++)
54 : 0 : ((volatile char *)rxq->rx_ring)[i] = 0;
55 : : }
56 : :
57 : : static inline void
58 : : cpfl_rx_hairpin_bufq_reset(struct idpf_rx_queue *rxbq)
59 : : {
60 : : uint16_t len;
61 : : uint32_t i;
62 : :
63 : 0 : if (!rxbq)
64 : : return;
65 : :
66 : 0 : len = rxbq->nb_rx_desc;
67 [ # # ]: 0 : for (i = 0; i < len * CPFL_P2P_DESC_LEN; i++)
68 : 0 : ((volatile char *)rxbq->rx_ring)[i] = 0;
69 : :
70 : 0 : rxbq->bufq1 = NULL;
71 : 0 : rxbq->bufq2 = NULL;
72 : : }
73 : :
74 : : static uint64_t
75 : 0 : cpfl_rx_offload_convert(uint64_t offload)
76 : : {
77 : : uint64_t ol = 0;
78 : :
79 [ # # ]: 0 : if ((offload & RTE_ETH_RX_OFFLOAD_IPV4_CKSUM) != 0)
80 : : ol |= IDPF_RX_OFFLOAD_IPV4_CKSUM;
81 [ # # ]: 0 : if ((offload & RTE_ETH_RX_OFFLOAD_UDP_CKSUM) != 0)
82 : 0 : ol |= IDPF_RX_OFFLOAD_UDP_CKSUM;
83 [ # # ]: 0 : if ((offload & RTE_ETH_RX_OFFLOAD_TCP_CKSUM) != 0)
84 : 0 : ol |= IDPF_RX_OFFLOAD_TCP_CKSUM;
85 [ # # ]: 0 : if ((offload & RTE_ETH_RX_OFFLOAD_OUTER_IPV4_CKSUM) != 0)
86 : 0 : ol |= IDPF_RX_OFFLOAD_OUTER_IPV4_CKSUM;
87 [ # # ]: 0 : if ((offload & RTE_ETH_RX_OFFLOAD_TIMESTAMP) != 0)
88 : 0 : ol |= IDPF_RX_OFFLOAD_TIMESTAMP;
89 : :
90 : 0 : return ol;
91 : : }
92 : :
93 : : static uint64_t
94 : 0 : cpfl_tx_offload_convert(uint64_t offload)
95 : : {
96 : : uint64_t ol = 0;
97 : :
98 [ # # ]: 0 : if ((offload & RTE_ETH_TX_OFFLOAD_IPV4_CKSUM) != 0)
99 : : ol |= IDPF_TX_OFFLOAD_IPV4_CKSUM;
100 [ # # ]: 0 : if ((offload & RTE_ETH_TX_OFFLOAD_UDP_CKSUM) != 0)
101 : 0 : ol |= IDPF_TX_OFFLOAD_UDP_CKSUM;
102 [ # # ]: 0 : if ((offload & RTE_ETH_TX_OFFLOAD_TCP_CKSUM) != 0)
103 : 0 : ol |= IDPF_TX_OFFLOAD_TCP_CKSUM;
104 [ # # ]: 0 : if ((offload & RTE_ETH_TX_OFFLOAD_SCTP_CKSUM) != 0)
105 : 0 : ol |= IDPF_TX_OFFLOAD_SCTP_CKSUM;
106 [ # # ]: 0 : if ((offload & RTE_ETH_TX_OFFLOAD_MULTI_SEGS) != 0)
107 : 0 : ol |= IDPF_TX_OFFLOAD_MULTI_SEGS;
108 [ # # ]: 0 : if ((offload & RTE_ETH_TX_OFFLOAD_MBUF_FAST_FREE) != 0)
109 : 0 : ol |= IDPF_TX_OFFLOAD_MBUF_FAST_FREE;
110 : :
111 : 0 : return ol;
112 : : }
113 : :
114 : : static const struct idpf_rxq_ops def_rxq_ops = {
115 : : .release_mbufs = idpf_qc_rxq_mbufs_release,
116 : : };
117 : :
118 : : static const struct rte_memzone *
119 [ # # # # : 0 : cpfl_dma_zone_reserve(struct rte_eth_dev *dev, uint16_t queue_idx,
# ]
120 : : uint16_t len, uint16_t queue_type,
121 : : unsigned int socket_id, bool splitq)
122 : : {
123 : : char ring_name[RTE_MEMZONE_NAMESIZE];
124 : : const struct rte_memzone *mz;
125 : : uint32_t ring_size;
126 : :
127 : : memset(ring_name, 0, RTE_MEMZONE_NAMESIZE);
128 [ # # # # : 0 : switch (queue_type) {
# ]
129 : 0 : case VIRTCHNL2_QUEUE_TYPE_TX:
130 [ # # ]: 0 : if (splitq)
131 : 0 : ring_size = RTE_ALIGN(len * sizeof(struct idpf_flex_tx_sched_desc),
132 : : CPFL_DMA_MEM_ALIGN);
133 : : else
134 : 0 : ring_size = RTE_ALIGN(len * sizeof(struct idpf_base_tx_desc),
135 : : CPFL_DMA_MEM_ALIGN);
136 : : memcpy(ring_name, "cpfl Tx ring", sizeof("cpfl Tx ring"));
137 : : break;
138 : 0 : case VIRTCHNL2_QUEUE_TYPE_RX:
139 [ # # ]: 0 : if (splitq)
140 : 0 : ring_size = RTE_ALIGN(len * sizeof(struct virtchnl2_rx_flex_desc_adv_nic_3),
141 : : CPFL_DMA_MEM_ALIGN);
142 : : else
143 : 0 : ring_size = RTE_ALIGN(len * sizeof(struct virtchnl2_singleq_rx_buf_desc),
144 : : CPFL_DMA_MEM_ALIGN);
145 : : memcpy(ring_name, "cpfl Rx ring", sizeof("cpfl Rx ring"));
146 : : break;
147 : 0 : case VIRTCHNL2_QUEUE_TYPE_TX_COMPLETION:
148 : 0 : ring_size = RTE_ALIGN(len * sizeof(struct idpf_splitq_tx_compl_desc),
149 : : CPFL_DMA_MEM_ALIGN);
150 : : memcpy(ring_name, "cpfl Tx compl ring", sizeof("cpfl Tx compl ring"));
151 : : break;
152 : 0 : case VIRTCHNL2_QUEUE_TYPE_RX_BUFFER:
153 : 0 : ring_size = RTE_ALIGN(len * sizeof(struct virtchnl2_splitq_rx_buf_desc),
154 : : CPFL_DMA_MEM_ALIGN);
155 : : memcpy(ring_name, "cpfl Rx buf ring", sizeof("cpfl Rx buf ring"));
156 : : break;
157 : 0 : default:
158 : 0 : PMD_INIT_LOG(ERR, "Invalid queue type");
159 : 0 : return NULL;
160 : : }
161 : :
162 : 0 : mz = rte_eth_dma_zone_reserve(dev, ring_name, queue_idx,
163 : : ring_size, CPFL_RING_BASE_ALIGN,
164 : : socket_id);
165 [ # # ]: 0 : if (mz == NULL) {
166 : 0 : PMD_INIT_LOG(ERR, "Failed to reserve DMA memory for ring");
167 : 0 : return NULL;
168 : : }
169 : :
170 : : /* Zero all the descriptors in the ring. */
171 : 0 : memset(mz->addr, 0, ring_size);
172 : :
173 : 0 : return mz;
174 : : }
175 : :
176 : : static void
177 : : cpfl_dma_zone_release(const struct rte_memzone *mz)
178 : : {
179 : 0 : rte_memzone_free(mz);
180 : 0 : }
181 : :
182 : : static int
183 : 0 : cpfl_rx_split_bufq_setup(struct rte_eth_dev *dev, struct idpf_rx_queue *rxq,
184 : : uint16_t queue_idx, uint16_t rx_free_thresh,
185 : : uint16_t nb_desc, unsigned int socket_id,
186 : : struct rte_mempool *mp, uint8_t bufq_id)
187 : : {
188 : 0 : struct cpfl_vport *cpfl_vport = dev->data->dev_private;
189 : : struct idpf_vport *vport = &cpfl_vport->base;
190 : 0 : struct idpf_adapter *base = vport->adapter;
191 : : struct idpf_hw *hw = &base->hw;
192 : : const struct rte_memzone *mz;
193 : : struct idpf_rx_queue *bufq;
194 : : uint16_t len;
195 : : int ret;
196 : :
197 : 0 : bufq = rte_zmalloc_socket("cpfl bufq",
198 : : sizeof(struct idpf_rx_queue),
199 : : RTE_CACHE_LINE_SIZE,
200 : : socket_id);
201 [ # # ]: 0 : if (bufq == NULL) {
202 : 0 : PMD_INIT_LOG(ERR, "Failed to allocate memory for rx buffer queue.");
203 : : ret = -ENOMEM;
204 : 0 : goto err_bufq1_alloc;
205 : : }
206 : :
207 : 0 : bufq->mp = mp;
208 : 0 : bufq->nb_rx_desc = nb_desc;
209 : 0 : bufq->rx_free_thresh = rx_free_thresh;
210 : 0 : bufq->queue_id = vport->chunks_info.rx_buf_start_qid + queue_idx;
211 : 0 : bufq->port_id = dev->data->port_id;
212 : 0 : bufq->rx_hdr_len = 0;
213 [ # # ]: 0 : bufq->adapter = base;
214 : :
215 : 0 : len = rte_pktmbuf_data_room_size(bufq->mp) - RTE_PKTMBUF_HEADROOM;
216 : 0 : bufq->rx_buf_len = RTE_ALIGN_FLOOR(len, (1 << IDPF_RLAN_CTX_DBUF_S));
217 : 0 : bufq->rx_buf_len = RTE_MIN(bufq->rx_buf_len, IDPF_RX_MAX_DATA_BUF_SIZE);
218 : :
219 : : /* Allocate a little more to support bulk allocate. */
220 : 0 : len = nb_desc + IDPF_RX_MAX_BURST;
221 : :
222 : 0 : mz = cpfl_dma_zone_reserve(dev, queue_idx, len,
223 : : VIRTCHNL2_QUEUE_TYPE_RX_BUFFER,
224 : : socket_id, true);
225 [ # # ]: 0 : if (mz == NULL) {
226 : : ret = -ENOMEM;
227 : 0 : goto err_mz_reserve;
228 : : }
229 : :
230 : 0 : bufq->rx_ring_phys_addr = mz->iova;
231 : 0 : bufq->rx_ring = mz->addr;
232 : 0 : bufq->mz = mz;
233 : :
234 : 0 : bufq->sw_ring =
235 : 0 : rte_zmalloc_socket("cpfl rx bufq sw ring",
236 : : sizeof(struct rte_mbuf *) * len,
237 : : RTE_CACHE_LINE_SIZE,
238 : : socket_id);
239 [ # # ]: 0 : if (bufq->sw_ring == NULL) {
240 : 0 : PMD_INIT_LOG(ERR, "Failed to allocate memory for SW ring");
241 : : ret = -ENOMEM;
242 : 0 : goto err_sw_ring_alloc;
243 : : }
244 : :
245 : 0 : idpf_qc_split_rx_bufq_reset(bufq);
246 : 0 : bufq->qrx_tail = hw->hw_addr + (vport->chunks_info.rx_buf_qtail_start +
247 : 0 : queue_idx * vport->chunks_info.rx_buf_qtail_spacing);
248 : 0 : bufq->idpf_ops = &def_rxq_ops;
249 : 0 : bufq->q_set = true;
250 : :
251 [ # # ]: 0 : if (bufq_id == IDPF_RX_SPLIT_BUFQ1_ID) {
252 : 0 : rxq->bufq1 = bufq;
253 [ # # ]: 0 : } else if (bufq_id == IDPF_RX_SPLIT_BUFQ2_ID) {
254 : 0 : rxq->bufq2 = bufq;
255 : : } else {
256 : 0 : PMD_INIT_LOG(ERR, "Invalid buffer queue index.");
257 : : ret = -EINVAL;
258 : 0 : goto err_bufq_id;
259 : : }
260 : :
261 : : return 0;
262 : :
263 : : err_bufq_id:
264 : 0 : rte_free(bufq->sw_ring);
265 : 0 : err_sw_ring_alloc:
266 : : cpfl_dma_zone_release(mz);
267 : 0 : err_mz_reserve:
268 : 0 : rte_free(bufq);
269 : : err_bufq1_alloc:
270 : : return ret;
271 : : }
272 : :
273 : : static void
274 : 0 : cpfl_rx_split_bufq_release(struct idpf_rx_queue *bufq)
275 : : {
276 : 0 : rte_free(bufq->sw_ring);
277 : 0 : cpfl_dma_zone_release(bufq->mz);
278 : 0 : rte_free(bufq);
279 : 0 : }
280 : :
281 : : static void
282 : 0 : cpfl_rx_queue_release(void *rxq)
283 : : {
284 : : struct cpfl_rx_queue *cpfl_rxq = rxq;
285 : : struct idpf_rx_queue *q = NULL;
286 : :
287 [ # # ]: 0 : if (cpfl_rxq == NULL)
288 : : return;
289 : :
290 : 0 : q = &cpfl_rxq->base;
291 : :
292 : : /* Split queue */
293 [ # # ]: 0 : if (!q->adapter->is_rx_singleq) {
294 : : /* the mz is shared between Tx/Rx hairpin, let Rx_release
295 : : * free the buf, q->bufq1->mz and q->mz.
296 : : */
297 [ # # # # ]: 0 : if (!cpfl_rxq->hairpin_info.hairpin_q && q->bufq2)
298 : 0 : cpfl_rx_split_bufq_release(q->bufq2);
299 : :
300 [ # # ]: 0 : if (q->bufq1)
301 : 0 : cpfl_rx_split_bufq_release(q->bufq1);
302 : :
303 : 0 : rte_memzone_free(q->mz);
304 : 0 : rte_free(cpfl_rxq);
305 : 0 : return;
306 : : }
307 : :
308 : : /* Single queue */
309 : 0 : q->idpf_ops->release_mbufs(q);
310 : 0 : rte_free(q->sw_ring);
311 : 0 : rte_memzone_free(q->mz);
312 : 0 : rte_free(cpfl_rxq);
313 : : }
314 : :
315 : : static void
316 : 0 : cpfl_tx_queue_release(void *txq)
317 : : {
318 : : struct cpfl_tx_queue *cpfl_txq = txq;
319 : : struct ci_tx_queue *q = NULL;
320 : :
321 [ # # ]: 0 : if (cpfl_txq == NULL)
322 : : return;
323 : :
324 : 0 : q = &cpfl_txq->base;
325 : :
326 [ # # ]: 0 : if (q->complq) {
327 : 0 : rte_memzone_free(q->complq->mz);
328 : 0 : rte_free(q->complq);
329 : : }
330 : :
331 : 0 : ci_txq_release_all_mbufs(q, q->vector_tx);
332 : 0 : rte_free(q->sw_ring);
333 : 0 : rte_memzone_free(q->mz);
334 : 0 : rte_free(cpfl_txq);
335 : : }
336 : :
337 : : int
338 : 0 : cpfl_rx_queue_setup(struct rte_eth_dev *dev, uint16_t queue_idx,
339 : : uint16_t nb_desc, unsigned int socket_id,
340 : : const struct rte_eth_rxconf *rx_conf,
341 : : struct rte_mempool *mp)
342 : : {
343 : 0 : struct cpfl_vport *cpfl_vport = dev->data->dev_private;
344 : : struct idpf_vport *vport = &cpfl_vport->base;
345 : 0 : struct idpf_adapter *base = vport->adapter;
346 : : struct idpf_hw *hw = &base->hw;
347 : : struct cpfl_rx_queue *cpfl_rxq;
348 : : const struct rte_memzone *mz;
349 : : struct idpf_rx_queue *rxq;
350 : : uint16_t rx_free_thresh;
351 : : uint64_t offloads;
352 : : bool is_splitq;
353 : : uint16_t len;
354 : : int ret;
355 : :
356 : 0 : offloads = rx_conf->offloads | dev->data->dev_conf.rxmode.offloads;
357 : :
358 : : /* Check free threshold */
359 [ # # ]: 0 : rx_free_thresh = (rx_conf->rx_free_thresh == 0) ?
360 : : CPFL_DEFAULT_RX_FREE_THRESH :
361 : : rx_conf->rx_free_thresh;
362 [ # # ]: 0 : if (idpf_qc_rx_thresh_check(nb_desc, rx_free_thresh) != 0)
363 : : return -EINVAL;
364 : :
365 : : /* Free memory if needed */
366 [ # # ]: 0 : if (dev->data->rx_queues[queue_idx] != NULL) {
367 : 0 : cpfl_rx_queue_release(dev->data->rx_queues[queue_idx]);
368 : 0 : dev->data->rx_queues[queue_idx] = NULL;
369 : : }
370 : :
371 : : /* Setup Rx queue */
372 : 0 : cpfl_rxq = rte_zmalloc_socket("cpfl rxq",
373 : : sizeof(struct cpfl_rx_queue),
374 : : RTE_CACHE_LINE_SIZE,
375 : : socket_id);
376 [ # # ]: 0 : if (cpfl_rxq == NULL) {
377 : 0 : PMD_INIT_LOG(ERR, "Failed to allocate memory for rx queue data structure");
378 : : ret = -ENOMEM;
379 : 0 : goto err_rxq_alloc;
380 : : }
381 : :
382 : 0 : rxq = &cpfl_rxq->base;
383 : :
384 : 0 : is_splitq = !!(vport->rxq_model == VIRTCHNL2_QUEUE_MODEL_SPLIT);
385 : :
386 : 0 : rxq->mp = mp;
387 : 0 : rxq->nb_rx_desc = nb_desc;
388 : 0 : rxq->rx_free_thresh = rx_free_thresh;
389 : 0 : rxq->queue_id = vport->chunks_info.rx_start_qid + queue_idx;
390 : 0 : rxq->port_id = dev->data->port_id;
391 : 0 : rxq->rx_deferred_start = rx_conf->rx_deferred_start;
392 : 0 : rxq->rx_hdr_len = 0;
393 : 0 : rxq->adapter = base;
394 [ # # ]: 0 : rxq->offloads = cpfl_rx_offload_convert(offloads);
395 : :
396 : 0 : len = rte_pktmbuf_data_room_size(rxq->mp) - RTE_PKTMBUF_HEADROOM;
397 : 0 : rxq->rx_buf_len = len;
398 : :
399 : : /* Allocate a little more to support bulk allocate. */
400 : 0 : len = nb_desc + IDPF_RX_MAX_BURST;
401 : 0 : mz = cpfl_dma_zone_reserve(dev, queue_idx, len, VIRTCHNL2_QUEUE_TYPE_RX,
402 : : socket_id, is_splitq);
403 [ # # ]: 0 : if (mz == NULL) {
404 : : ret = -ENOMEM;
405 : 0 : goto err_mz_reserve;
406 : : }
407 : 0 : rxq->rx_ring_phys_addr = mz->iova;
408 : 0 : rxq->rx_ring = mz->addr;
409 : 0 : rxq->mz = mz;
410 : :
411 [ # # ]: 0 : if (!is_splitq) {
412 : 0 : rxq->sw_ring = rte_zmalloc_socket("cpfl rxq sw ring",
413 : : sizeof(struct rte_mbuf *) * len,
414 : : RTE_CACHE_LINE_SIZE,
415 : : socket_id);
416 [ # # ]: 0 : if (rxq->sw_ring == NULL) {
417 : 0 : PMD_INIT_LOG(ERR, "Failed to allocate memory for SW ring");
418 : : ret = -ENOMEM;
419 : 0 : goto err_sw_ring_alloc;
420 : : }
421 : :
422 : 0 : idpf_qc_single_rx_queue_reset(rxq);
423 : 0 : rxq->qrx_tail = hw->hw_addr + (vport->chunks_info.rx_qtail_start +
424 : 0 : queue_idx * vport->chunks_info.rx_qtail_spacing);
425 : 0 : rxq->idpf_ops = &def_rxq_ops;
426 : : } else {
427 : 0 : idpf_qc_split_rx_descq_reset(rxq);
428 : :
429 : : /* Setup Rx buffer queues */
430 : 0 : ret = cpfl_rx_split_bufq_setup(dev, rxq, 2 * queue_idx,
431 : : rx_free_thresh, nb_desc,
432 : : socket_id, mp, 1);
433 [ # # ]: 0 : if (ret != 0) {
434 : 0 : PMD_INIT_LOG(ERR, "Failed to setup buffer queue 1");
435 : : ret = -EINVAL;
436 : 0 : goto err_bufq1_setup;
437 : : }
438 : :
439 : 0 : ret = cpfl_rx_split_bufq_setup(dev, rxq, 2 * queue_idx + 1,
440 : : rx_free_thresh, nb_desc,
441 : : socket_id, mp, 2);
442 [ # # ]: 0 : if (ret != 0) {
443 : 0 : PMD_INIT_LOG(ERR, "Failed to setup buffer queue 2");
444 : : ret = -EINVAL;
445 : 0 : goto err_bufq2_setup;
446 : : }
447 : : }
448 : :
449 : 0 : cpfl_vport->nb_data_rxq++;
450 : 0 : rxq->q_set = true;
451 : 0 : dev->data->rx_queues[queue_idx] = cpfl_rxq;
452 : :
453 : 0 : return 0;
454 : :
455 : : err_bufq2_setup:
456 : 0 : cpfl_rx_split_bufq_release(rxq->bufq1);
457 : 0 : err_bufq1_setup:
458 : 0 : err_sw_ring_alloc:
459 : : cpfl_dma_zone_release(mz);
460 : 0 : err_mz_reserve:
461 : 0 : rte_free(rxq);
462 : : err_rxq_alloc:
463 : : return ret;
464 : : }
465 : :
466 : : static int
467 : 0 : cpfl_tx_complq_setup(struct rte_eth_dev *dev, struct ci_tx_queue *txq,
468 : : uint16_t queue_idx, uint16_t nb_desc,
469 : : unsigned int socket_id)
470 : : {
471 : 0 : struct cpfl_vport *cpfl_vport = dev->data->dev_private;
472 : : struct idpf_vport *vport = &cpfl_vport->base;
473 : : const struct rte_memzone *mz;
474 : : struct ci_tx_queue *cq;
475 : : int ret;
476 : :
477 : 0 : cq = rte_zmalloc_socket("cpfl splitq cq",
478 : : sizeof(*cq),
479 : : RTE_CACHE_LINE_SIZE,
480 : : socket_id);
481 [ # # ]: 0 : if (cq == NULL) {
482 : 0 : PMD_INIT_LOG(ERR, "Failed to allocate memory for Tx compl queue");
483 : : ret = -ENOMEM;
484 : 0 : goto err_cq_alloc;
485 : : }
486 : :
487 : 0 : cq->nb_tx_desc = nb_desc;
488 : 0 : cq->queue_id = vport->chunks_info.tx_compl_start_qid + queue_idx;
489 : 0 : cq->port_id = dev->data->port_id;
490 : 0 : cq->txqs = dev->data->tx_queues;
491 : 0 : cq->tx_start_qid = vport->chunks_info.tx_start_qid;
492 : :
493 : 0 : mz = cpfl_dma_zone_reserve(dev, queue_idx, nb_desc,
494 : : VIRTCHNL2_QUEUE_TYPE_TX_COMPLETION,
495 : : socket_id, true);
496 [ # # ]: 0 : if (mz == NULL) {
497 : : ret = -ENOMEM;
498 : 0 : goto err_mz_reserve;
499 : : }
500 : 0 : cq->tx_ring_dma = mz->iova;
501 : 0 : cq->compl_ring = mz->addr;
502 : 0 : cq->mz = mz;
503 : 0 : idpf_qc_split_tx_complq_reset(cq);
504 : :
505 : 0 : txq->complq = cq;
506 : :
507 : 0 : return 0;
508 : :
509 : : err_mz_reserve:
510 : 0 : rte_free(cq);
511 : : err_cq_alloc:
512 : : return ret;
513 : : }
514 : :
515 : : int
516 : 0 : cpfl_tx_queue_setup(struct rte_eth_dev *dev, uint16_t queue_idx,
517 : : uint16_t nb_desc, unsigned int socket_id,
518 : : const struct rte_eth_txconf *tx_conf)
519 : : {
520 : 0 : struct cpfl_vport *cpfl_vport = dev->data->dev_private;
521 : : struct idpf_vport *vport = &cpfl_vport->base;
522 : 0 : struct idpf_adapter *base = vport->adapter;
523 : : uint16_t tx_rs_thresh, tx_free_thresh;
524 : : struct cpfl_tx_queue *cpfl_txq;
525 : : struct idpf_hw *hw = &base->hw;
526 : : const struct rte_memzone *mz;
527 : : struct ci_tx_queue *txq;
528 : : uint64_t offloads;
529 : : uint16_t len;
530 : : bool is_splitq;
531 : : int ret;
532 : :
533 : 0 : offloads = tx_conf->offloads | dev->data->dev_conf.txmode.offloads;
534 : :
535 [ # # ]: 0 : tx_rs_thresh = (uint16_t)((tx_conf->tx_rs_thresh > 0) ?
536 : : tx_conf->tx_rs_thresh : CPFL_DEFAULT_TX_RS_THRESH);
537 [ # # ]: 0 : tx_free_thresh = (uint16_t)((tx_conf->tx_free_thresh > 0) ?
538 : : tx_conf->tx_free_thresh : CPFL_DEFAULT_TX_FREE_THRESH);
539 [ # # ]: 0 : if (idpf_qc_tx_thresh_check(nb_desc, tx_rs_thresh, tx_free_thresh) != 0)
540 : : return -EINVAL;
541 : :
542 : : /* Free memory if needed. */
543 [ # # ]: 0 : if (dev->data->tx_queues[queue_idx] != NULL) {
544 : 0 : cpfl_tx_queue_release(dev->data->tx_queues[queue_idx]);
545 : 0 : dev->data->tx_queues[queue_idx] = NULL;
546 : : }
547 : :
548 : : /* Allocate the TX queue data structure. */
549 : 0 : cpfl_txq = rte_zmalloc_socket("cpfl txq",
550 : : sizeof(struct cpfl_tx_queue),
551 : : RTE_CACHE_LINE_SIZE,
552 : : socket_id);
553 [ # # ]: 0 : if (cpfl_txq == NULL) {
554 : 0 : PMD_INIT_LOG(ERR, "Failed to allocate memory for tx queue structure");
555 : : ret = -ENOMEM;
556 : 0 : goto err_txq_alloc;
557 : : }
558 : :
559 : 0 : txq = &cpfl_txq->base;
560 : :
561 : 0 : is_splitq = !!(vport->txq_model == VIRTCHNL2_QUEUE_MODEL_SPLIT);
562 : :
563 : 0 : txq->nb_tx_desc = nb_desc;
564 : 0 : txq->tx_rs_thresh = tx_rs_thresh;
565 : 0 : txq->tx_free_thresh = tx_free_thresh;
566 : 0 : txq->queue_id = vport->chunks_info.tx_start_qid + queue_idx;
567 : 0 : txq->port_id = dev->data->port_id;
568 : 0 : txq->offloads = cpfl_tx_offload_convert(offloads);
569 : 0 : txq->tx_deferred_start = tx_conf->tx_deferred_start;
570 : :
571 [ # # ]: 0 : if (is_splitq)
572 : 0 : len = 2 * nb_desc;
573 : : else
574 : : len = nb_desc;
575 : 0 : txq->sw_nb_desc = len;
576 : :
577 : : /* Allocate TX hardware ring descriptors. */
578 : 0 : mz = cpfl_dma_zone_reserve(dev, queue_idx, nb_desc, VIRTCHNL2_QUEUE_TYPE_TX,
579 : : socket_id, is_splitq);
580 [ # # ]: 0 : if (mz == NULL) {
581 : : ret = -ENOMEM;
582 : 0 : goto err_mz_reserve;
583 : : }
584 : 0 : txq->tx_ring_dma = mz->iova;
585 : 0 : txq->mz = mz;
586 : :
587 : 0 : txq->sw_ring = rte_zmalloc_socket("cpfl tx sw ring",
588 : : sizeof(struct ci_tx_entry) * len,
589 : : RTE_CACHE_LINE_SIZE, socket_id);
590 [ # # ]: 0 : if (txq->sw_ring == NULL) {
591 : 0 : PMD_INIT_LOG(ERR, "Failed to allocate memory for SW TX ring");
592 : : ret = -ENOMEM;
593 : 0 : goto err_sw_ring_alloc;
594 : : }
595 : :
596 [ # # ]: 0 : if (!is_splitq) {
597 : 0 : txq->idpf_tx_ring = mz->addr;
598 : 0 : idpf_qc_single_tx_queue_reset(txq);
599 : : } else {
600 : 0 : txq->desc_ring = mz->addr;
601 : 0 : idpf_qc_split_tx_descq_reset(txq);
602 : :
603 : : /* Setup tx completion queue if split model */
604 : 0 : ret = cpfl_tx_complq_setup(dev, txq, queue_idx,
605 : : 2 * nb_desc, socket_id);
606 [ # # ]: 0 : if (ret != 0)
607 : 0 : goto err_complq_setup;
608 : : }
609 : :
610 : 0 : txq->qtx_tail = hw->hw_addr + (vport->chunks_info.tx_qtail_start +
611 : 0 : queue_idx * vport->chunks_info.tx_qtail_spacing);
612 : 0 : cpfl_vport->nb_data_txq++;
613 : 0 : txq->q_set = true;
614 : 0 : dev->data->tx_queues[queue_idx] = cpfl_txq;
615 : :
616 : 0 : return 0;
617 : :
618 : : err_complq_setup:
619 : 0 : err_sw_ring_alloc:
620 : : cpfl_dma_zone_release(mz);
621 : 0 : err_mz_reserve:
622 : 0 : rte_free(txq);
623 : : err_txq_alloc:
624 : : return ret;
625 : : }
626 : :
627 : : static int
628 : 0 : cpfl_rx_hairpin_bufq_setup(struct rte_eth_dev *dev, struct idpf_rx_queue *bufq,
629 : : uint16_t logic_qid, uint16_t nb_desc)
630 : : {
631 : 0 : struct cpfl_vport *cpfl_vport =
632 : 0 : (struct cpfl_vport *)dev->data->dev_private;
633 : : struct idpf_vport *vport = &cpfl_vport->base;
634 : 0 : struct idpf_adapter *adapter = vport->adapter;
635 : : struct rte_mempool *mp;
636 : : char pool_name[RTE_MEMPOOL_NAMESIZE];
637 : :
638 : 0 : mp = cpfl_vport->p2p_mp;
639 [ # # ]: 0 : if (!mp) {
640 : 0 : snprintf(pool_name, RTE_MEMPOOL_NAMESIZE, "p2p_mb_pool_%u",
641 : 0 : dev->data->port_id);
642 : 0 : mp = rte_pktmbuf_pool_create(pool_name, CPFL_P2P_NB_MBUF * CPFL_MAX_P2P_NB_QUEUES,
643 : : CPFL_P2P_CACHE_SIZE, 0, CPFL_P2P_MBUF_SIZE,
644 : 0 : dev->device->numa_node);
645 [ # # ]: 0 : if (!mp) {
646 : 0 : PMD_INIT_LOG(ERR, "Failed to allocate mbuf pool for p2p");
647 : 0 : return -ENOMEM;
648 : : }
649 : 0 : cpfl_vport->p2p_mp = mp;
650 : : }
651 : :
652 : 0 : bufq->mp = mp;
653 : 0 : bufq->nb_rx_desc = nb_desc;
654 : 0 : bufq->queue_id = cpfl_hw_qid_get(cpfl_vport->p2p_q_chunks_info->rx_buf_start_qid,
655 : : logic_qid);
656 : 0 : bufq->port_id = dev->data->port_id;
657 : 0 : bufq->adapter = adapter;
658 : 0 : bufq->rx_buf_len = CPFL_P2P_MBUF_SIZE - RTE_PKTMBUF_HEADROOM;
659 : :
660 : 0 : bufq->q_set = true;
661 : 0 : bufq->idpf_ops = &def_rxq_ops;
662 : :
663 : 0 : return 0;
664 : : }
665 : :
666 : : int
667 : 0 : cpfl_rx_hairpin_queue_setup(struct rte_eth_dev *dev, uint16_t queue_idx,
668 : : uint16_t nb_desc,
669 : : const struct rte_eth_hairpin_conf *conf)
670 : : {
671 : 0 : struct cpfl_vport *cpfl_vport = (struct cpfl_vport *)dev->data->dev_private;
672 : : struct idpf_vport *vport = &cpfl_vport->base;
673 : 0 : struct idpf_adapter *adapter_base = vport->adapter;
674 : 0 : uint16_t logic_qid = cpfl_vport->nb_p2p_rxq;
675 : : struct cpfl_rxq_hairpin_info *hairpin_info;
676 : : struct cpfl_rx_queue *cpfl_rxq;
677 : : struct idpf_rx_queue *bufq1 = NULL;
678 : : struct idpf_rx_queue *rxq;
679 : : uint16_t peer_port, peer_q;
680 : : uint16_t qid;
681 : : int ret;
682 : :
683 [ # # ]: 0 : if (vport->rxq_model == VIRTCHNL2_QUEUE_MODEL_SINGLE) {
684 : 0 : PMD_INIT_LOG(ERR, "Only spilt queue model supports hairpin queue.");
685 : 0 : return -EINVAL;
686 : : }
687 : :
688 [ # # ]: 0 : if (conf->peer_count != 1) {
689 : 0 : PMD_INIT_LOG(ERR, "Can't support Rx hairpin queue peer count %d", conf->peer_count);
690 : 0 : return -EINVAL;
691 : : }
692 : :
693 : 0 : peer_port = conf->peers[0].port;
694 : 0 : peer_q = conf->peers[0].queue;
695 : :
696 [ # # ]: 0 : if (nb_desc % CPFL_ALIGN_RING_DESC != 0 ||
697 [ # # ]: 0 : nb_desc > CPFL_MAX_RING_DESC ||
698 : : nb_desc < CPFL_MIN_RING_DESC) {
699 : 0 : PMD_INIT_LOG(ERR, "Number (%u) of receive descriptors is invalid", nb_desc);
700 : 0 : return -EINVAL;
701 : : }
702 : :
703 : : /* Free memory if needed */
704 [ # # ]: 0 : if (dev->data->rx_queues[queue_idx]) {
705 : 0 : cpfl_rx_queue_release(dev->data->rx_queues[queue_idx]);
706 : 0 : dev->data->rx_queues[queue_idx] = NULL;
707 : : }
708 : :
709 : : /* Setup Rx description queue */
710 : 0 : cpfl_rxq = rte_zmalloc_socket("cpfl hairpin rxq",
711 : : sizeof(struct cpfl_rx_queue),
712 : : RTE_CACHE_LINE_SIZE,
713 : : SOCKET_ID_ANY);
714 [ # # ]: 0 : if (!cpfl_rxq) {
715 : 0 : PMD_INIT_LOG(ERR, "Failed to allocate memory for rx queue data structure");
716 : 0 : return -ENOMEM;
717 : : }
718 : :
719 : : rxq = &cpfl_rxq->base;
720 : : hairpin_info = &cpfl_rxq->hairpin_info;
721 : 0 : rxq->nb_rx_desc = nb_desc * 2;
722 [ # # ]: 0 : rxq->queue_id = cpfl_hw_qid_get(cpfl_vport->p2p_q_chunks_info->rx_start_qid, logic_qid);
723 : 0 : rxq->port_id = dev->data->port_id;
724 : 0 : rxq->adapter = adapter_base;
725 : 0 : rxq->rx_buf_len = CPFL_P2P_MBUF_SIZE - RTE_PKTMBUF_HEADROOM;
726 : 0 : hairpin_info->hairpin_q = true;
727 : 0 : hairpin_info->peer_txp = peer_port;
728 : 0 : hairpin_info->peer_txq_id = peer_q;
729 : :
730 [ # # ]: 0 : if (conf->manual_bind != 0)
731 : 0 : cpfl_vport->p2p_manual_bind = true;
732 : : else
733 : 0 : cpfl_vport->p2p_manual_bind = false;
734 : :
735 [ # # ]: 0 : if (cpfl_vport->p2p_rx_bufq == NULL) {
736 : 0 : bufq1 = rte_zmalloc_socket("hairpin rx bufq1",
737 : : sizeof(struct idpf_rx_queue),
738 : : RTE_CACHE_LINE_SIZE,
739 : : SOCKET_ID_ANY);
740 [ # # ]: 0 : if (!bufq1) {
741 : 0 : PMD_INIT_LOG(ERR, "Failed to allocate memory for hairpin Rx buffer queue 1.");
742 : : ret = -ENOMEM;
743 : 0 : goto err_alloc_bufq1;
744 : : }
745 : 0 : qid = 2 * logic_qid;
746 : 0 : ret = cpfl_rx_hairpin_bufq_setup(dev, bufq1, qid, nb_desc);
747 [ # # ]: 0 : if (ret) {
748 : 0 : PMD_INIT_LOG(ERR, "Failed to setup hairpin Rx buffer queue 1");
749 : : ret = -EINVAL;
750 : 0 : goto err_setup_bufq1;
751 : : }
752 : 0 : cpfl_vport->p2p_rx_bufq = bufq1;
753 : : }
754 : :
755 : 0 : rxq->bufq1 = cpfl_vport->p2p_rx_bufq;
756 : 0 : rxq->bufq2 = NULL;
757 : :
758 : 0 : cpfl_vport->nb_p2p_rxq++;
759 : 0 : rxq->q_set = true;
760 : 0 : dev->data->rx_queues[queue_idx] = cpfl_rxq;
761 : :
762 : 0 : return 0;
763 : :
764 : : err_setup_bufq1:
765 : 0 : rte_mempool_free(cpfl_vport->p2p_mp);
766 : 0 : rte_free(bufq1);
767 : 0 : err_alloc_bufq1:
768 : 0 : rte_free(cpfl_rxq);
769 : :
770 : 0 : return ret;
771 : : }
772 : :
773 : : int
774 : 0 : cpfl_tx_hairpin_queue_setup(struct rte_eth_dev *dev, uint16_t queue_idx,
775 : : uint16_t nb_desc,
776 : : const struct rte_eth_hairpin_conf *conf)
777 : : {
778 : 0 : struct cpfl_vport *cpfl_vport =
779 : 0 : (struct cpfl_vport *)dev->data->dev_private;
780 : :
781 : : struct idpf_vport *vport = &cpfl_vport->base;
782 : 0 : struct idpf_adapter *adapter_base = vport->adapter;
783 : 0 : uint16_t logic_qid = cpfl_vport->nb_p2p_txq;
784 : : struct cpfl_txq_hairpin_info *hairpin_info;
785 : : struct idpf_hw *hw = &adapter_base->hw;
786 : : struct cpfl_tx_queue *cpfl_txq;
787 : : struct ci_tx_queue *txq, *cq;
788 : : const struct rte_memzone *mz;
789 : : uint32_t ring_size;
790 : : uint16_t peer_port, peer_q;
791 : : int ret;
792 : :
793 [ # # ]: 0 : if (vport->txq_model == VIRTCHNL2_QUEUE_MODEL_SINGLE) {
794 : 0 : PMD_INIT_LOG(ERR, "Only spilt queue model supports hairpin queue.");
795 : 0 : return -EINVAL;
796 : : }
797 : :
798 [ # # ]: 0 : if (conf->peer_count != 1) {
799 : 0 : PMD_INIT_LOG(ERR, "Can't support Tx hairpin queue peer count %d", conf->peer_count);
800 : 0 : return -EINVAL;
801 : : }
802 : :
803 : 0 : peer_port = conf->peers[0].port;
804 : 0 : peer_q = conf->peers[0].queue;
805 : :
806 [ # # ]: 0 : if (nb_desc % CPFL_ALIGN_RING_DESC != 0 ||
807 [ # # ]: 0 : nb_desc > CPFL_MAX_RING_DESC ||
808 : : nb_desc < CPFL_MIN_RING_DESC) {
809 : 0 : PMD_INIT_LOG(ERR, "Number (%u) of transmit descriptors is invalid",
810 : : nb_desc);
811 : 0 : return -EINVAL;
812 : : }
813 : :
814 : : /* Free memory if needed. */
815 [ # # ]: 0 : if (dev->data->tx_queues[queue_idx]) {
816 : 0 : cpfl_tx_queue_release(dev->data->tx_queues[queue_idx]);
817 : 0 : dev->data->tx_queues[queue_idx] = NULL;
818 : : }
819 : :
820 : : /* Allocate the TX queue data structure. */
821 : 0 : cpfl_txq = rte_zmalloc_socket("cpfl hairpin txq",
822 : : sizeof(struct cpfl_tx_queue),
823 : : RTE_CACHE_LINE_SIZE,
824 : : SOCKET_ID_ANY);
825 [ # # ]: 0 : if (!cpfl_txq) {
826 : 0 : PMD_INIT_LOG(ERR, "Failed to allocate memory for tx queue structure");
827 : 0 : return -ENOMEM;
828 : : }
829 : :
830 : 0 : txq = &cpfl_txq->base;
831 : : hairpin_info = &cpfl_txq->hairpin_info;
832 : : /* Txq ring length should be 2 times of Tx completion queue size. */
833 : 0 : txq->nb_tx_desc = nb_desc * 2;
834 [ # # ]: 0 : txq->queue_id = cpfl_hw_qid_get(cpfl_vport->p2p_q_chunks_info->tx_start_qid, logic_qid);
835 : 0 : txq->port_id = dev->data->port_id;
836 : 0 : hairpin_info->hairpin_q = true;
837 : 0 : hairpin_info->peer_rxp = peer_port;
838 : 0 : hairpin_info->peer_rxq_id = peer_q;
839 : :
840 [ # # ]: 0 : if (conf->manual_bind != 0)
841 : 0 : cpfl_vport->p2p_manual_bind = true;
842 : : else
843 : 0 : cpfl_vport->p2p_manual_bind = false;
844 : :
845 : : /* Always Tx hairpin queue allocates Tx HW ring */
846 : 0 : ring_size = RTE_ALIGN(txq->nb_tx_desc * CPFL_P2P_DESC_LEN,
847 : : CPFL_DMA_MEM_ALIGN);
848 : 0 : mz = rte_eth_dma_zone_reserve(dev, "hairpin_tx_ring", logic_qid,
849 : 0 : ring_size + CPFL_P2P_RING_BUF,
850 : : CPFL_RING_BASE_ALIGN,
851 : 0 : dev->device->numa_node);
852 [ # # ]: 0 : if (!mz) {
853 : 0 : PMD_INIT_LOG(ERR, "Failed to reserve DMA memory for TX");
854 : : ret = -ENOMEM;
855 : 0 : goto err_txq_mz_rsv;
856 : : }
857 : :
858 : 0 : txq->tx_ring_dma = mz->iova;
859 : 0 : txq->desc_ring = mz->addr;
860 : 0 : txq->mz = mz;
861 : :
862 : 0 : cpfl_tx_hairpin_descq_reset(txq);
863 : 0 : txq->qtx_tail = hw->hw_addr +
864 : 0 : cpfl_hw_qtail_get(cpfl_vport->p2p_q_chunks_info->tx_qtail_start,
865 [ # # ]: 0 : logic_qid, cpfl_vport->p2p_q_chunks_info->tx_qtail_spacing);
866 [ # # ]: 0 : if (cpfl_vport->p2p_tx_complq == NULL) {
867 : 0 : cq = rte_zmalloc_socket("cpfl hairpin cq",
868 : : sizeof(struct ci_tx_queue),
869 : : RTE_CACHE_LINE_SIZE,
870 : 0 : dev->device->numa_node);
871 [ # # ]: 0 : if (!cq) {
872 : 0 : PMD_INIT_LOG(ERR, "Failed to allocate memory for tx queue structure");
873 : : ret = -ENOMEM;
874 : 0 : goto err_cq_alloc;
875 : : }
876 : :
877 : 0 : cq->nb_tx_desc = nb_desc;
878 : 0 : cq->queue_id = cpfl_hw_qid_get(cpfl_vport->p2p_q_chunks_info->tx_compl_start_qid,
879 : : 0);
880 : 0 : cq->port_id = dev->data->port_id;
881 : :
882 : : /* Tx completion queue always allocates the HW ring */
883 : 0 : ring_size = RTE_ALIGN(cq->nb_tx_desc * CPFL_P2P_DESC_LEN,
884 : : CPFL_DMA_MEM_ALIGN);
885 : 0 : mz = rte_eth_dma_zone_reserve(dev, "hairpin_tx_compl_ring", logic_qid,
886 : 0 : ring_size + CPFL_P2P_RING_BUF,
887 : : CPFL_RING_BASE_ALIGN,
888 : 0 : dev->device->numa_node);
889 [ # # ]: 0 : if (!mz) {
890 : 0 : PMD_INIT_LOG(ERR, "Failed to reserve DMA memory for TX completion queue");
891 : : ret = -ENOMEM;
892 : 0 : goto err_cq_mz_rsv;
893 : : }
894 : 0 : cq->tx_ring_dma = mz->iova;
895 : 0 : cq->compl_ring = mz->addr;
896 : 0 : cq->mz = mz;
897 : :
898 : 0 : cpfl_tx_hairpin_complq_reset(cq);
899 : 0 : cpfl_vport->p2p_tx_complq = cq;
900 : : }
901 : :
902 : 0 : txq->complq = cpfl_vport->p2p_tx_complq;
903 : :
904 : 0 : cpfl_vport->nb_p2p_txq++;
905 : 0 : txq->q_set = true;
906 : 0 : dev->data->tx_queues[queue_idx] = cpfl_txq;
907 : :
908 : 0 : return 0;
909 : :
910 : : err_cq_mz_rsv:
911 : 0 : rte_free(cq);
912 : 0 : err_cq_alloc:
913 : : cpfl_dma_zone_release(mz);
914 : 0 : err_txq_mz_rsv:
915 : 0 : rte_free(cpfl_txq);
916 : 0 : return ret;
917 : : }
918 : :
919 : : int
920 : 0 : cpfl_hairpin_rx_bufq_config(struct cpfl_vport *cpfl_vport)
921 : : {
922 : 0 : struct idpf_rx_queue *rx_bufq = cpfl_vport->p2p_rx_bufq;
923 : : struct virtchnl2_rxq_info rxq_info;
924 : :
925 : : memset(&rxq_info, 0, sizeof(rxq_info));
926 : :
927 : 0 : rxq_info.type = VIRTCHNL2_QUEUE_TYPE_RX_BUFFER;
928 : 0 : rxq_info.queue_id = rx_bufq->queue_id;
929 : 0 : rxq_info.ring_len = rx_bufq->nb_rx_desc;
930 : 0 : rxq_info.dma_ring_addr = rx_bufq->rx_ring_phys_addr;
931 : 0 : rxq_info.desc_ids = VIRTCHNL2_RXDID_2_FLEX_SPLITQ_M;
932 : 0 : rxq_info.rx_buffer_low_watermark = CPFL_RXBUF_LOW_WATERMARK;
933 : 0 : rxq_info.model = VIRTCHNL2_QUEUE_MODEL_SPLIT;
934 : 0 : rxq_info.data_buffer_size = rx_bufq->rx_buf_len;
935 : 0 : rxq_info.buffer_notif_stride = CPFL_RX_BUF_STRIDE;
936 : :
937 : 0 : return idpf_vc_rxq_config_by_info(&cpfl_vport->base, &rxq_info, 1);
938 : : }
939 : :
940 : : int
941 : 0 : cpfl_hairpin_rxq_config(struct idpf_vport *vport, struct cpfl_rx_queue *cpfl_rxq)
942 : : {
943 : : struct virtchnl2_rxq_info rxq_info;
944 : : struct idpf_rx_queue *rxq = &cpfl_rxq->base;
945 : :
946 : : memset(&rxq_info, 0, sizeof(rxq_info));
947 : :
948 : 0 : rxq_info.type = VIRTCHNL2_QUEUE_TYPE_RX;
949 : 0 : rxq_info.queue_id = rxq->queue_id;
950 : 0 : rxq_info.ring_len = rxq->nb_rx_desc;
951 : 0 : rxq_info.dma_ring_addr = rxq->rx_ring_phys_addr;
952 : 0 : rxq_info.rx_bufq1_id = rxq->bufq1->queue_id;
953 : 0 : rxq_info.max_pkt_size = vport->max_pkt_len;
954 : 0 : rxq_info.desc_ids = VIRTCHNL2_RXDID_2_FLEX_SPLITQ_M;
955 : 0 : rxq_info.qflags |= VIRTCHNL2_RX_DESC_SIZE_16BYTE;
956 : :
957 : 0 : rxq_info.data_buffer_size = rxq->rx_buf_len;
958 : 0 : rxq_info.model = VIRTCHNL2_QUEUE_MODEL_SPLIT;
959 : 0 : rxq_info.rx_buffer_low_watermark = CPFL_RXBUF_LOW_WATERMARK;
960 : :
961 : 0 : PMD_DRV_LOG(NOTICE, "hairpin: vport %u, Rxq id 0x%x",
962 : : vport->vport_id, rxq_info.queue_id);
963 : :
964 : 0 : return idpf_vc_rxq_config_by_info(vport, &rxq_info, 1);
965 : : }
966 : :
967 : : int
968 : 0 : cpfl_hairpin_tx_complq_config(struct cpfl_vport *cpfl_vport)
969 : : {
970 : 0 : struct ci_tx_queue *tx_complq = cpfl_vport->p2p_tx_complq;
971 : : struct virtchnl2_txq_info txq_info;
972 : :
973 : : memset(&txq_info, 0, sizeof(txq_info));
974 : :
975 : 0 : txq_info.dma_ring_addr = tx_complq->tx_ring_dma;
976 : 0 : txq_info.type = VIRTCHNL2_QUEUE_TYPE_TX_COMPLETION;
977 : 0 : txq_info.queue_id = tx_complq->queue_id;
978 : 0 : txq_info.ring_len = tx_complq->nb_tx_desc;
979 : 0 : txq_info.peer_rx_queue_id = cpfl_vport->p2p_rx_bufq->queue_id;
980 : 0 : txq_info.model = VIRTCHNL2_QUEUE_MODEL_SPLIT;
981 : 0 : txq_info.sched_mode = VIRTCHNL2_TXQ_SCHED_MODE_FLOW;
982 : :
983 : 0 : return idpf_vc_txq_config_by_info(&cpfl_vport->base, &txq_info, 1);
984 : : }
985 : :
986 : : int
987 : 0 : cpfl_hairpin_txq_config(struct idpf_vport *vport, struct cpfl_tx_queue *cpfl_txq)
988 : : {
989 : : struct ci_tx_queue *txq = &cpfl_txq->base;
990 : : struct virtchnl2_txq_info txq_info;
991 : :
992 : : memset(&txq_info, 0, sizeof(txq_info));
993 : :
994 : 0 : txq_info.dma_ring_addr = txq->tx_ring_dma;
995 : : txq_info.type = VIRTCHNL2_QUEUE_TYPE_TX;
996 : 0 : txq_info.queue_id = txq->queue_id;
997 : 0 : txq_info.ring_len = txq->nb_tx_desc;
998 : 0 : txq_info.tx_compl_queue_id = txq->complq->queue_id;
999 : 0 : txq_info.relative_queue_id = txq->queue_id;
1000 : 0 : txq_info.peer_rx_queue_id = cpfl_txq->hairpin_info.peer_rxq_id;
1001 : 0 : txq_info.model = VIRTCHNL2_QUEUE_MODEL_SPLIT;
1002 : 0 : txq_info.sched_mode = VIRTCHNL2_TXQ_SCHED_MODE_FLOW;
1003 : :
1004 : 0 : return idpf_vc_txq_config_by_info(vport, &txq_info, 1);
1005 : : }
1006 : :
1007 : : int
1008 : 0 : cpfl_switch_hairpin_complq(struct cpfl_vport *cpfl_vport, bool on)
1009 : : {
1010 : 0 : struct idpf_vport *vport = &cpfl_vport->base;
1011 : : uint32_t type;
1012 : : int err, queue_id;
1013 : :
1014 : : type = VIRTCHNL2_QUEUE_TYPE_TX_COMPLETION;
1015 : 0 : queue_id = cpfl_vport->p2p_tx_complq->queue_id;
1016 : 0 : err = idpf_vc_ena_dis_one_queue(vport, queue_id, type, on);
1017 : :
1018 : 0 : return err;
1019 : : }
1020 : :
1021 : : int
1022 : 0 : cpfl_switch_hairpin_bufq(struct cpfl_vport *cpfl_vport, bool on)
1023 : : {
1024 : 0 : struct idpf_vport *vport = &cpfl_vport->base;
1025 : : uint32_t type;
1026 : : int err, queue_id;
1027 : :
1028 : : type = VIRTCHNL2_QUEUE_TYPE_RX_BUFFER;
1029 : 0 : queue_id = cpfl_vport->p2p_rx_bufq->queue_id;
1030 : 0 : err = idpf_vc_ena_dis_one_queue(vport, queue_id, type, on);
1031 : :
1032 : 0 : return err;
1033 : : }
1034 : :
1035 : : int
1036 : 0 : cpfl_switch_hairpin_rxtx_queue(struct cpfl_vport *cpfl_vport, uint16_t logic_qid,
1037 : : bool rx, bool on)
1038 : : {
1039 : 0 : struct idpf_vport *vport = &cpfl_vport->base;
1040 : : uint32_t type;
1041 : : int err, queue_id;
1042 : :
1043 : 0 : type = rx ? VIRTCHNL2_QUEUE_TYPE_RX : VIRTCHNL2_QUEUE_TYPE_TX;
1044 : :
1045 [ # # ]: 0 : if (type == VIRTCHNL2_QUEUE_TYPE_RX)
1046 : 0 : queue_id = cpfl_hw_qid_get(cpfl_vport->p2p_q_chunks_info->rx_start_qid, logic_qid);
1047 : : else
1048 : 0 : queue_id = cpfl_hw_qid_get(cpfl_vport->p2p_q_chunks_info->tx_start_qid, logic_qid);
1049 : 0 : err = idpf_vc_ena_dis_one_queue(vport, queue_id, type, on);
1050 : : if (err)
1051 : : return err;
1052 : :
1053 : : return err;
1054 : : }
1055 : :
1056 : : static int
1057 : 0 : cpfl_alloc_split_p2p_rxq_mbufs(struct idpf_rx_queue *rxq)
1058 : : {
1059 : : volatile struct virtchnl2_p2p_rx_buf_desc *rxd;
1060 : : struct rte_mbuf *mbuf = NULL;
1061 : : uint64_t dma_addr;
1062 : : uint16_t i;
1063 : :
1064 [ # # ]: 0 : for (i = 0; i < rxq->nb_rx_desc; i++) {
1065 : 0 : mbuf = rte_mbuf_raw_alloc(rxq->mp);
1066 [ # # ]: 0 : if (unlikely(!mbuf)) {
1067 : 0 : PMD_DRV_LOG(ERR, "Failed to allocate mbuf for RX");
1068 : 0 : return -ENOMEM;
1069 : : }
1070 : :
1071 : : rte_mbuf_refcnt_set(mbuf, 1);
1072 : 0 : mbuf->next = NULL;
1073 : 0 : mbuf->data_off = RTE_PKTMBUF_HEADROOM;
1074 : 0 : mbuf->nb_segs = 1;
1075 : 0 : mbuf->port = rxq->port_id;
1076 : : dma_addr = rte_cpu_to_le_64(rte_mbuf_data_iova_default(mbuf));
1077 : :
1078 : 0 : rxd = &((volatile struct virtchnl2_p2p_rx_buf_desc *)(rxq->rx_ring))[i];
1079 : 0 : rxd->reserve0 = 0;
1080 : 0 : rxd->pkt_addr = dma_addr;
1081 : : }
1082 : :
1083 : 0 : rxq->nb_rx_hold = 0;
1084 : : /* The value written in the RX buffer queue tail register, must be a multiple of 8.*/
1085 : 0 : rxq->rx_tail = rxq->nb_rx_desc - CPFL_HAIRPIN_Q_TAIL_AUX_VALUE;
1086 : :
1087 : 0 : return 0;
1088 : : }
1089 : :
1090 : : int
1091 : 0 : cpfl_rx_queue_init(struct rte_eth_dev *dev, uint16_t rx_queue_id)
1092 : : {
1093 : : struct cpfl_rx_queue *cpfl_rxq;
1094 : : struct idpf_rx_queue *rxq;
1095 : : uint16_t max_pkt_len;
1096 : : uint32_t frame_size;
1097 : : int err;
1098 : :
1099 [ # # ]: 0 : if (rx_queue_id >= dev->data->nb_rx_queues)
1100 : : return -EINVAL;
1101 : :
1102 : 0 : cpfl_rxq = dev->data->rx_queues[rx_queue_id];
1103 : 0 : rxq = &cpfl_rxq->base;
1104 : :
1105 [ # # # # ]: 0 : if (rxq == NULL || !rxq->q_set) {
1106 : 0 : PMD_DRV_LOG(ERR, "RX queue %u not available or setup",
1107 : : rx_queue_id);
1108 : 0 : return -EINVAL;
1109 : : }
1110 : :
1111 : 0 : frame_size = dev->data->mtu + CPFL_ETH_OVERHEAD;
1112 : :
1113 : 0 : max_pkt_len =
1114 : 0 : RTE_MIN((uint32_t)CPFL_SUPPORT_CHAIN_NUM * rxq->rx_buf_len,
1115 : : frame_size);
1116 : :
1117 : 0 : rxq->max_pkt_len = max_pkt_len;
1118 [ # # # # ]: 0 : if ((dev->data->dev_conf.rxmode.offloads & RTE_ETH_RX_OFFLOAD_SCATTER) ||
1119 : : frame_size > rxq->rx_buf_len)
1120 : 0 : dev->data->scattered_rx = 1;
1121 : :
1122 : 0 : err = idpf_qc_ts_mbuf_register(rxq);
1123 [ # # ]: 0 : if (err != 0) {
1124 : 0 : PMD_DRV_LOG(ERR, "fail to register timestamp mbuf %u",
1125 : : rx_queue_id);
1126 : 0 : return -EIO;
1127 : : }
1128 : :
1129 [ # # ]: 0 : if (rxq->adapter->is_rx_singleq) {
1130 : : /* Single queue */
1131 : 0 : err = idpf_qc_single_rxq_mbufs_alloc(rxq);
1132 [ # # ]: 0 : if (err != 0) {
1133 : 0 : PMD_DRV_LOG(ERR, "Failed to allocate RX queue mbuf");
1134 : 0 : return err;
1135 : : }
1136 : :
1137 : : rte_wmb();
1138 : :
1139 : : /* Init the RX tail register. */
1140 : 0 : IDPF_PCI_REG_WRITE(rxq->qrx_tail, rxq->nb_rx_desc - 1);
1141 : : } else {
1142 : : /* Split queue */
1143 [ # # ]: 0 : if (cpfl_rxq->hairpin_info.hairpin_q) {
1144 : 0 : err = cpfl_alloc_split_p2p_rxq_mbufs(rxq->bufq1);
1145 [ # # ]: 0 : if (err != 0) {
1146 : 0 : PMD_DRV_LOG(ERR, "Failed to allocate p2p RX buffer queue mbuf");
1147 : 0 : return err;
1148 : : }
1149 : : } else {
1150 : 0 : err = idpf_qc_split_rxq_mbufs_alloc(rxq->bufq1);
1151 [ # # ]: 0 : if (err != 0) {
1152 : 0 : PMD_DRV_LOG(ERR, "Failed to allocate RX buffer queue mbuf");
1153 : 0 : return err;
1154 : : }
1155 : 0 : err = idpf_qc_split_rxq_mbufs_alloc(rxq->bufq2);
1156 [ # # ]: 0 : if (err != 0) {
1157 : 0 : PMD_DRV_LOG(ERR, "Failed to allocate RX buffer queue mbuf");
1158 : 0 : return err;
1159 : : }
1160 : : }
1161 : :
1162 : : rte_wmb();
1163 : :
1164 : : /* Init the RX tail register. */
1165 : 0 : IDPF_PCI_REG_WRITE(rxq->bufq1->qrx_tail, rxq->bufq1->rx_tail);
1166 [ # # ]: 0 : if (rxq->bufq2)
1167 : 0 : IDPF_PCI_REG_WRITE(rxq->bufq2->qrx_tail, rxq->bufq2->rx_tail);
1168 : : }
1169 : :
1170 : : return err;
1171 : : }
1172 : :
1173 : : int
1174 : 0 : cpfl_rx_queue_start(struct rte_eth_dev *dev, uint16_t rx_queue_id)
1175 : : {
1176 : 0 : struct cpfl_vport *cpfl_vport = dev->data->dev_private;
1177 : 0 : struct idpf_vport *vport = &cpfl_vport->base;
1178 : 0 : struct cpfl_rx_queue *cpfl_rxq = dev->data->rx_queues[rx_queue_id];
1179 : 0 : struct idpf_rx_queue *rxq = &cpfl_rxq->base;
1180 : : int err = 0;
1181 : :
1182 : 0 : err = idpf_vc_rxq_config(vport, rxq);
1183 [ # # ]: 0 : if (err != 0) {
1184 : 0 : PMD_DRV_LOG(ERR, "Fail to configure Rx queue %u", rx_queue_id);
1185 : 0 : return err;
1186 : : }
1187 : :
1188 : 0 : err = cpfl_rx_queue_init(dev, rx_queue_id);
1189 [ # # ]: 0 : if (err != 0) {
1190 : 0 : PMD_DRV_LOG(ERR, "Failed to init RX queue %u",
1191 : : rx_queue_id);
1192 : 0 : return err;
1193 : : }
1194 : :
1195 : : /* Ready to switch the queue on */
1196 : 0 : err = idpf_vc_queue_switch(vport, rx_queue_id, true, true,
1197 : : VIRTCHNL2_QUEUE_TYPE_RX);
1198 [ # # ]: 0 : if (err != 0) {
1199 : 0 : PMD_DRV_LOG(ERR, "Failed to switch RX queue %u on",
1200 : : rx_queue_id);
1201 : : } else {
1202 : 0 : rxq->q_started = true;
1203 : 0 : dev->data->rx_queue_state[rx_queue_id] =
1204 : : RTE_ETH_QUEUE_STATE_STARTED;
1205 : : }
1206 : :
1207 : : return err;
1208 : : }
1209 : :
1210 : : int
1211 : 0 : cpfl_tx_queue_init(struct rte_eth_dev *dev, uint16_t tx_queue_id)
1212 : : {
1213 : : struct cpfl_tx_queue *cpfl_txq;
1214 : :
1215 [ # # ]: 0 : if (tx_queue_id >= dev->data->nb_tx_queues)
1216 : : return -EINVAL;
1217 : :
1218 : 0 : cpfl_txq = dev->data->tx_queues[tx_queue_id];
1219 : :
1220 : : /* Init the RX tail register. */
1221 : 0 : IDPF_PCI_REG_WRITE(cpfl_txq->base.qtx_tail, 0);
1222 : :
1223 : 0 : return 0;
1224 : : }
1225 : :
1226 : : int
1227 : 0 : cpfl_tx_queue_start(struct rte_eth_dev *dev, uint16_t tx_queue_id)
1228 : : {
1229 : 0 : struct cpfl_vport *cpfl_vport = dev->data->dev_private;
1230 : 0 : struct idpf_vport *vport = &cpfl_vport->base;
1231 : 0 : struct cpfl_tx_queue *cpfl_txq =
1232 : 0 : dev->data->tx_queues[tx_queue_id];
1233 : : int err = 0;
1234 : :
1235 : 0 : err = idpf_vc_txq_config(vport, &cpfl_txq->base);
1236 [ # # ]: 0 : if (err != 0) {
1237 : 0 : PMD_DRV_LOG(ERR, "Fail to configure Tx queue %u", tx_queue_id);
1238 : 0 : return err;
1239 : : }
1240 : :
1241 : 0 : err = cpfl_tx_queue_init(dev, tx_queue_id);
1242 [ # # ]: 0 : if (err != 0) {
1243 : 0 : PMD_DRV_LOG(ERR, "Failed to init TX queue %u",
1244 : : tx_queue_id);
1245 : 0 : return err;
1246 : : }
1247 : :
1248 : : /* Ready to switch the queue on */
1249 : 0 : err = idpf_vc_queue_switch(vport, tx_queue_id, false, true,
1250 : : VIRTCHNL2_QUEUE_TYPE_TX);
1251 [ # # ]: 0 : if (err != 0) {
1252 : 0 : PMD_DRV_LOG(ERR, "Failed to switch TX queue %u on",
1253 : : tx_queue_id);
1254 : : } else {
1255 : 0 : dev->data->tx_queue_state[tx_queue_id] =
1256 : : RTE_ETH_QUEUE_STATE_STARTED;
1257 : : }
1258 : :
1259 : : return err;
1260 : : }
1261 : :
1262 : : int
1263 : 0 : cpfl_rx_queue_stop(struct rte_eth_dev *dev, uint16_t rx_queue_id)
1264 : : {
1265 : 0 : struct cpfl_vport *cpfl_vport = dev->data->dev_private;
1266 : 0 : struct idpf_vport *vport = &cpfl_vport->base;
1267 : : struct cpfl_rx_queue *cpfl_rxq;
1268 : : struct idpf_rx_queue *rxq;
1269 : : int err;
1270 : :
1271 [ # # ]: 0 : if (rx_queue_id >= dev->data->nb_rx_queues)
1272 : : return -EINVAL;
1273 : :
1274 : 0 : cpfl_rxq = dev->data->rx_queues[rx_queue_id];
1275 [ # # ]: 0 : if (cpfl_rxq->hairpin_info.hairpin_q)
1276 : 0 : err = cpfl_switch_hairpin_rxtx_queue(cpfl_vport,
1277 : 0 : rx_queue_id - cpfl_vport->nb_data_txq,
1278 : : true, false);
1279 : : else
1280 : 0 : err = idpf_vc_queue_switch(vport, rx_queue_id, true, false,
1281 : : VIRTCHNL2_QUEUE_TYPE_RX);
1282 [ # # ]: 0 : if (err != 0) {
1283 : 0 : PMD_DRV_LOG(ERR, "Failed to switch RX queue %u off",
1284 : : rx_queue_id);
1285 : 0 : return err;
1286 : : }
1287 : :
1288 : 0 : rxq = &cpfl_rxq->base;
1289 : 0 : rxq->q_started = false;
1290 [ # # ]: 0 : if (vport->rxq_model == VIRTCHNL2_QUEUE_MODEL_SINGLE) {
1291 : 0 : rxq->idpf_ops->release_mbufs(rxq);
1292 : 0 : idpf_qc_single_rx_queue_reset(rxq);
1293 : : } else {
1294 : 0 : rxq->bufq1->idpf_ops->release_mbufs(rxq->bufq1);
1295 [ # # ]: 0 : if (rxq->bufq2)
1296 : 0 : rxq->bufq2->idpf_ops->release_mbufs(rxq->bufq2);
1297 [ # # ]: 0 : if (cpfl_rxq->hairpin_info.hairpin_q) {
1298 : : cpfl_rx_hairpin_descq_reset(rxq);
1299 [ # # ]: 0 : cpfl_rx_hairpin_bufq_reset(rxq->bufq1);
1300 : : } else {
1301 : 0 : idpf_qc_split_rx_queue_reset(rxq);
1302 : : }
1303 : : }
1304 [ # # ]: 0 : if (!cpfl_rxq->hairpin_info.hairpin_q)
1305 : 0 : dev->data->rx_queue_state[rx_queue_id] = RTE_ETH_QUEUE_STATE_STOPPED;
1306 : :
1307 : : return 0;
1308 : : }
1309 : :
1310 : : int
1311 : 0 : cpfl_tx_queue_stop(struct rte_eth_dev *dev, uint16_t tx_queue_id)
1312 : : {
1313 : 0 : struct cpfl_vport *cpfl_vport = dev->data->dev_private;
1314 : 0 : struct idpf_vport *vport = &cpfl_vport->base;
1315 : : struct cpfl_tx_queue *cpfl_txq;
1316 : : struct ci_tx_queue *txq;
1317 : : int err;
1318 : :
1319 [ # # ]: 0 : if (tx_queue_id >= dev->data->nb_tx_queues)
1320 : : return -EINVAL;
1321 : :
1322 : 0 : cpfl_txq = dev->data->tx_queues[tx_queue_id];
1323 : :
1324 [ # # ]: 0 : if (cpfl_txq->hairpin_info.hairpin_q)
1325 : 0 : err = cpfl_switch_hairpin_rxtx_queue(cpfl_vport,
1326 : 0 : tx_queue_id - cpfl_vport->nb_data_txq,
1327 : : false, false);
1328 : : else
1329 : 0 : err = idpf_vc_queue_switch(vport, tx_queue_id, false, false,
1330 : : VIRTCHNL2_QUEUE_TYPE_TX);
1331 [ # # ]: 0 : if (err != 0) {
1332 : 0 : PMD_DRV_LOG(ERR, "Failed to switch TX queue %u off",
1333 : : tx_queue_id);
1334 : 0 : return err;
1335 : : }
1336 : :
1337 : 0 : txq = &cpfl_txq->base;
1338 : 0 : ci_txq_release_all_mbufs(txq, txq->vector_tx);
1339 [ # # ]: 0 : if (vport->txq_model == VIRTCHNL2_QUEUE_MODEL_SINGLE) {
1340 : 0 : idpf_qc_single_tx_queue_reset(txq);
1341 : : } else {
1342 [ # # ]: 0 : if (cpfl_txq->hairpin_info.hairpin_q) {
1343 : 0 : cpfl_tx_hairpin_descq_reset(txq);
1344 : 0 : cpfl_tx_hairpin_complq_reset(txq->complq);
1345 : : } else {
1346 : 0 : idpf_qc_split_tx_descq_reset(txq);
1347 : 0 : idpf_qc_split_tx_complq_reset(txq->complq);
1348 : : }
1349 : : }
1350 : :
1351 [ # # ]: 0 : if (!cpfl_txq->hairpin_info.hairpin_q)
1352 : 0 : dev->data->tx_queue_state[tx_queue_id] = RTE_ETH_QUEUE_STATE_STOPPED;
1353 : :
1354 : : return 0;
1355 : : }
1356 : :
1357 : : void
1358 : 0 : cpfl_dev_rx_queue_release(struct rte_eth_dev *dev, uint16_t qid)
1359 : : {
1360 : 0 : cpfl_rx_queue_release(dev->data->rx_queues[qid]);
1361 : 0 : }
1362 : :
1363 : : void
1364 : 0 : cpfl_dev_tx_queue_release(struct rte_eth_dev *dev, uint16_t qid)
1365 : : {
1366 : 0 : cpfl_tx_queue_release(dev->data->tx_queues[qid]);
1367 : 0 : }
1368 : :
1369 : : void
1370 : 0 : cpfl_stop_queues(struct rte_eth_dev *dev)
1371 : : {
1372 : 0 : struct cpfl_vport *cpfl_vport =
1373 : 0 : (struct cpfl_vport *)dev->data->dev_private;
1374 : : struct cpfl_rx_queue *cpfl_rxq;
1375 : : struct cpfl_tx_queue *cpfl_txq;
1376 : : int i;
1377 : :
1378 [ # # ]: 0 : if (cpfl_vport->p2p_tx_complq != NULL) {
1379 [ # # ]: 0 : if (cpfl_switch_hairpin_complq(cpfl_vport, false) != 0)
1380 : 0 : PMD_DRV_LOG(ERR, "Failed to stop hairpin Tx complq");
1381 : : }
1382 : :
1383 [ # # ]: 0 : if (cpfl_vport->p2p_rx_bufq != NULL) {
1384 [ # # ]: 0 : if (cpfl_switch_hairpin_bufq(cpfl_vport, false) != 0)
1385 : 0 : PMD_DRV_LOG(ERR, "Failed to stop hairpin Rx bufq");
1386 : : }
1387 : :
1388 [ # # ]: 0 : for (i = 0; i < dev->data->nb_rx_queues; i++) {
1389 : 0 : cpfl_rxq = dev->data->rx_queues[i];
1390 [ # # ]: 0 : if (cpfl_rxq == NULL)
1391 : 0 : continue;
1392 : :
1393 [ # # ]: 0 : if (cpfl_rx_queue_stop(dev, i) != 0)
1394 : 0 : PMD_DRV_LOG(WARNING, "Fail to stop Rx queue %d", i);
1395 : : }
1396 : :
1397 [ # # ]: 0 : for (i = 0; i < dev->data->nb_tx_queues; i++) {
1398 : 0 : cpfl_txq = dev->data->tx_queues[i];
1399 [ # # ]: 0 : if (cpfl_txq == NULL)
1400 : 0 : continue;
1401 : :
1402 [ # # ]: 0 : if (cpfl_tx_queue_stop(dev, i) != 0)
1403 : 0 : PMD_DRV_LOG(WARNING, "Fail to stop Tx queue %d", i);
1404 : : }
1405 : 0 : }
1406 : :
1407 : : void
1408 : 0 : cpfl_set_rx_function(struct rte_eth_dev *dev)
1409 : : {
1410 : 0 : struct cpfl_vport *cpfl_vport = dev->data->dev_private;
1411 : : struct idpf_vport *vport = &cpfl_vport->base;
1412 : : #ifdef RTE_ARCH_X86
1413 : : struct cpfl_rx_queue *cpfl_rxq;
1414 : : int i;
1415 : :
1416 [ # # # # ]: 0 : if (cpfl_rx_vec_dev_check_default(dev) == CPFL_VECTOR_PATH &&
1417 : 0 : rte_vect_get_max_simd_bitwidth() >= RTE_VECT_SIMD_128) {
1418 : 0 : vport->rx_vec_allowed = true;
1419 : :
1420 [ # # # # ]: 0 : if (rte_cpu_get_flag_enabled(RTE_CPUFLAG_AVX2) == 1 &&
1421 : 0 : rte_vect_get_max_simd_bitwidth() >= RTE_VECT_SIMD_256)
1422 : 0 : vport->rx_use_avx2 = true;
1423 : :
1424 [ # # ]: 0 : if (rte_vect_get_max_simd_bitwidth() >= RTE_VECT_SIMD_512)
1425 : : #ifdef CC_AVX512_SUPPORT
1426 [ # # # # ]: 0 : if (rte_cpu_get_flag_enabled(RTE_CPUFLAG_AVX512F) == 1 &&
1427 [ # # ]: 0 : rte_cpu_get_flag_enabled(RTE_CPUFLAG_AVX512BW) == 1 &&
1428 : 0 : rte_cpu_get_flag_enabled(RTE_CPUFLAG_AVX512DQ))
1429 : 0 : vport->rx_use_avx512 = true;
1430 : : #else
1431 : : PMD_DRV_LOG(NOTICE,
1432 : : "AVX512 is not supported in build env");
1433 : : #endif /* CC_AVX512_SUPPORT */
1434 : : } else {
1435 : 0 : vport->rx_vec_allowed = false;
1436 : : }
1437 : : #endif /* RTE_ARCH_X86 */
1438 : :
1439 : : #ifdef RTE_ARCH_X86
1440 [ # # ]: 0 : if (vport->rxq_model == VIRTCHNL2_QUEUE_MODEL_SPLIT) {
1441 [ # # ]: 0 : if (vport->rx_vec_allowed) {
1442 [ # # ]: 0 : for (i = 0; i < dev->data->nb_rx_queues; i++) {
1443 : 0 : cpfl_rxq = dev->data->rx_queues[i];
1444 [ # # ]: 0 : if (cpfl_rxq->hairpin_info.hairpin_q)
1445 : 0 : continue;
1446 : 0 : (void)idpf_qc_splitq_rx_vec_setup(&cpfl_rxq->base);
1447 : : }
1448 : : #ifdef CC_AVX512_SUPPORT
1449 [ # # ]: 0 : if (vport->rx_use_avx512) {
1450 : 0 : PMD_DRV_LOG(NOTICE,
1451 : : "Using Split AVX512 Vector Rx (port %d).",
1452 : : dev->data->port_id);
1453 : 0 : dev->rx_pkt_burst = idpf_dp_splitq_recv_pkts_avx512;
1454 : 0 : return;
1455 : : }
1456 : : #endif /* CC_AVX512_SUPPORT */
1457 : : }
1458 : 0 : PMD_DRV_LOG(NOTICE,
1459 : : "Using Split Scalar Rx (port %d).",
1460 : : dev->data->port_id);
1461 : 0 : dev->rx_pkt_burst = idpf_dp_splitq_recv_pkts;
1462 : : } else {
1463 [ # # ]: 0 : if (vport->rx_vec_allowed) {
1464 [ # # ]: 0 : for (i = 0; i < dev->data->nb_rx_queues; i++) {
1465 : 0 : cpfl_rxq = dev->data->rx_queues[i];
1466 : 0 : (void)idpf_qc_singleq_rx_vec_setup(&cpfl_rxq->base);
1467 : : }
1468 : : #ifdef CC_AVX512_SUPPORT
1469 [ # # ]: 0 : if (vport->rx_use_avx512) {
1470 : 0 : PMD_DRV_LOG(NOTICE,
1471 : : "Using Single AVX512 Vector Rx (port %d).",
1472 : : dev->data->port_id);
1473 : 0 : dev->rx_pkt_burst = idpf_dp_singleq_recv_pkts_avx512;
1474 : 0 : return;
1475 : : }
1476 : : #endif /* CC_AVX512_SUPPORT */
1477 [ # # ]: 0 : if (vport->rx_use_avx2) {
1478 : 0 : PMD_DRV_LOG(NOTICE,
1479 : : "Using Single AVX2 Vector Rx (port %d).",
1480 : : dev->data->port_id);
1481 : 0 : dev->rx_pkt_burst = idpf_dp_singleq_recv_pkts_avx2;
1482 : 0 : return;
1483 : : }
1484 : : }
1485 [ # # ]: 0 : if (dev->data->scattered_rx) {
1486 : 0 : PMD_DRV_LOG(NOTICE,
1487 : : "Using Single Scalar Scatterd Rx (port %d).",
1488 : : dev->data->port_id);
1489 : 0 : dev->rx_pkt_burst = idpf_dp_singleq_recv_scatter_pkts;
1490 : 0 : return;
1491 : : }
1492 : 0 : PMD_DRV_LOG(NOTICE,
1493 : : "Using Single Scalar Rx (port %d).",
1494 : : dev->data->port_id);
1495 : 0 : dev->rx_pkt_burst = idpf_dp_singleq_recv_pkts;
1496 : : }
1497 : : #else
1498 : : if (vport->rxq_model == VIRTCHNL2_QUEUE_MODEL_SPLIT) {
1499 : : PMD_DRV_LOG(NOTICE,
1500 : : "Using Split Scalar Rx (port %d).",
1501 : : dev->data->port_id);
1502 : : dev->rx_pkt_burst = idpf_dp_splitq_recv_pkts;
1503 : : } else {
1504 : : if (dev->data->scattered_rx) {
1505 : : PMD_DRV_LOG(NOTICE,
1506 : : "Using Single Scalar Scatterd Rx (port %d).",
1507 : : dev->data->port_id);
1508 : : dev->rx_pkt_burst = idpf_dp_singleq_recv_scatter_pkts;
1509 : : return;
1510 : : }
1511 : : PMD_DRV_LOG(NOTICE,
1512 : : "Using Single Scalar Rx (port %d).",
1513 : : dev->data->port_id);
1514 : : dev->rx_pkt_burst = idpf_dp_singleq_recv_pkts;
1515 : : }
1516 : : #endif /* RTE_ARCH_X86 */
1517 : : }
1518 : :
1519 : : void
1520 : 0 : cpfl_set_tx_function(struct rte_eth_dev *dev)
1521 : : {
1522 : 0 : struct cpfl_vport *cpfl_vport = dev->data->dev_private;
1523 : : struct idpf_vport *vport = &cpfl_vport->base;
1524 : : #ifdef RTE_ARCH_X86
1525 : : #ifdef CC_AVX512_SUPPORT
1526 : : struct cpfl_tx_queue *cpfl_txq;
1527 : : int i;
1528 : : #endif /* CC_AVX512_SUPPORT */
1529 : :
1530 [ # # # # ]: 0 : if (cpfl_tx_vec_dev_check_default(dev) == CPFL_VECTOR_PATH &&
1531 : 0 : rte_vect_get_max_simd_bitwidth() >= RTE_VECT_SIMD_128) {
1532 : 0 : vport->tx_vec_allowed = true;
1533 : :
1534 [ # # # # ]: 0 : if (rte_cpu_get_flag_enabled(RTE_CPUFLAG_AVX2) == 1 &&
1535 : 0 : rte_vect_get_max_simd_bitwidth() >= RTE_VECT_SIMD_256)
1536 : 0 : vport->tx_use_avx2 = true;
1537 : :
1538 [ # # ]: 0 : if (rte_vect_get_max_simd_bitwidth() >= RTE_VECT_SIMD_512)
1539 : : #ifdef CC_AVX512_SUPPORT
1540 : : {
1541 [ # # # # ]: 0 : if (rte_cpu_get_flag_enabled(RTE_CPUFLAG_AVX512F) == 1 &&
1542 : 0 : rte_cpu_get_flag_enabled(RTE_CPUFLAG_AVX512BW) == 1)
1543 : 0 : vport->tx_use_avx512 = true;
1544 [ # # ]: 0 : if (vport->tx_use_avx512) {
1545 [ # # ]: 0 : for (i = 0; i < dev->data->nb_tx_queues; i++) {
1546 : 0 : cpfl_txq = dev->data->tx_queues[i];
1547 : 0 : idpf_qc_tx_vec_avx512_setup(&cpfl_txq->base);
1548 : : }
1549 : : }
1550 : : }
1551 : : #else
1552 : : PMD_DRV_LOG(NOTICE,
1553 : : "AVX512 is not supported in build env");
1554 : : #endif /* CC_AVX512_SUPPORT */
1555 : : } else {
1556 : 0 : vport->tx_vec_allowed = false;
1557 : : }
1558 : : #endif /* RTE_ARCH_X86 */
1559 : :
1560 : : #ifdef RTE_ARCH_X86
1561 [ # # ]: 0 : if (vport->txq_model == VIRTCHNL2_QUEUE_MODEL_SPLIT) {
1562 [ # # ]: 0 : if (vport->tx_vec_allowed) {
1563 : : #ifdef CC_AVX512_SUPPORT
1564 [ # # ]: 0 : if (vport->tx_use_avx512) {
1565 : 0 : PMD_DRV_LOG(NOTICE,
1566 : : "Using Split AVX512 Vector Tx (port %d).",
1567 : : dev->data->port_id);
1568 : 0 : dev->tx_pkt_burst = idpf_dp_splitq_xmit_pkts_avx512;
1569 : 0 : dev->tx_pkt_prepare = idpf_dp_prep_pkts;
1570 : 0 : return;
1571 : : }
1572 : : #endif /* CC_AVX512_SUPPORT */
1573 : : }
1574 : 0 : PMD_DRV_LOG(NOTICE,
1575 : : "Using Split Scalar Tx (port %d).",
1576 : : dev->data->port_id);
1577 : 0 : dev->tx_pkt_burst = idpf_dp_splitq_xmit_pkts;
1578 : 0 : dev->tx_pkt_prepare = idpf_dp_prep_pkts;
1579 : : } else {
1580 [ # # ]: 0 : if (vport->tx_vec_allowed) {
1581 : : #ifdef CC_AVX512_SUPPORT
1582 [ # # ]: 0 : if (vport->tx_use_avx512) {
1583 [ # # ]: 0 : for (i = 0; i < dev->data->nb_tx_queues; i++) {
1584 : 0 : cpfl_txq = dev->data->tx_queues[i];
1585 [ # # ]: 0 : if (cpfl_txq == NULL)
1586 : 0 : continue;
1587 : 0 : idpf_qc_tx_vec_avx512_setup(&cpfl_txq->base);
1588 : : }
1589 : 0 : PMD_DRV_LOG(NOTICE,
1590 : : "Using Single AVX512 Vector Tx (port %d).",
1591 : : dev->data->port_id);
1592 : 0 : dev->tx_pkt_burst = idpf_dp_singleq_xmit_pkts_avx512;
1593 : 0 : dev->tx_pkt_prepare = idpf_dp_prep_pkts;
1594 : 0 : return;
1595 : : }
1596 : : #endif /* CC_AVX512_SUPPORT */
1597 [ # # ]: 0 : if (vport->tx_use_avx2) {
1598 : 0 : PMD_DRV_LOG(NOTICE,
1599 : : "Using Single AVX2 Vector Tx (port %d).",
1600 : : dev->data->port_id);
1601 : 0 : dev->tx_pkt_burst = idpf_dp_singleq_xmit_pkts_avx2;
1602 : 0 : dev->tx_pkt_prepare = idpf_dp_prep_pkts;
1603 : 0 : return;
1604 : : }
1605 : : }
1606 : 0 : PMD_DRV_LOG(NOTICE,
1607 : : "Using Single Scalar Tx (port %d).",
1608 : : dev->data->port_id);
1609 : 0 : dev->tx_pkt_burst = idpf_dp_singleq_xmit_pkts;
1610 : 0 : dev->tx_pkt_prepare = idpf_dp_prep_pkts;
1611 : : }
1612 : : #else
1613 : : if (vport->txq_model == VIRTCHNL2_QUEUE_MODEL_SPLIT) {
1614 : : PMD_DRV_LOG(NOTICE,
1615 : : "Using Split Scalar Tx (port %d).",
1616 : : dev->data->port_id);
1617 : : dev->tx_pkt_burst = idpf_dp_splitq_xmit_pkts;
1618 : : dev->tx_pkt_prepare = idpf_dp_prep_pkts;
1619 : : } else {
1620 : : PMD_DRV_LOG(NOTICE,
1621 : : "Using Single Scalar Tx (port %d).",
1622 : : dev->data->port_id);
1623 : : dev->tx_pkt_burst = idpf_dp_singleq_xmit_pkts;
1624 : : dev->tx_pkt_prepare = idpf_dp_prep_pkts;
1625 : : }
1626 : : #endif /* RTE_ARCH_X86 */
1627 : : }
|