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