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 ci_tx_queue *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 ci_tx_queue *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, *cq;
817 : : const struct rte_memzone *mz;
818 : : uint32_t ring_size;
819 : : uint16_t peer_port, peer_q;
820 : : int ret;
821 : :
822 [ # # ]: 0 : if (vport->txq_model == VIRTCHNL2_QUEUE_MODEL_SINGLE) {
823 : 0 : PMD_INIT_LOG(ERR, "Only spilt queue model supports hairpin queue.");
824 : 0 : return -EINVAL;
825 : : }
826 : :
827 [ # # ]: 0 : if (conf->peer_count != 1) {
828 : 0 : PMD_INIT_LOG(ERR, "Can't support Tx hairpin queue peer count %d", conf->peer_count);
829 : 0 : return -EINVAL;
830 : : }
831 : :
832 : 0 : peer_port = conf->peers[0].port;
833 : 0 : peer_q = conf->peers[0].queue;
834 : :
835 [ # # ]: 0 : if (nb_desc % CPFL_ALIGN_RING_DESC != 0 ||
836 [ # # ]: 0 : nb_desc > CPFL_MAX_RING_DESC ||
837 : : nb_desc < CPFL_MIN_RING_DESC) {
838 : 0 : PMD_INIT_LOG(ERR, "Number (%u) of transmit descriptors is invalid",
839 : : nb_desc);
840 : 0 : return -EINVAL;
841 : : }
842 : :
843 : : /* Free memory if needed. */
844 [ # # ]: 0 : if (dev->data->tx_queues[queue_idx]) {
845 : 0 : cpfl_tx_queue_release(dev->data->tx_queues[queue_idx]);
846 : 0 : dev->data->tx_queues[queue_idx] = NULL;
847 : : }
848 : :
849 : : /* Allocate the TX queue data structure. */
850 : 0 : cpfl_txq = rte_zmalloc_socket("cpfl hairpin txq",
851 : : sizeof(struct cpfl_tx_queue),
852 : : RTE_CACHE_LINE_SIZE,
853 : : SOCKET_ID_ANY);
854 [ # # ]: 0 : if (!cpfl_txq) {
855 : 0 : PMD_INIT_LOG(ERR, "Failed to allocate memory for tx queue structure");
856 : 0 : return -ENOMEM;
857 : : }
858 : :
859 : 0 : txq = &cpfl_txq->base;
860 : : hairpin_info = &cpfl_txq->hairpin_info;
861 : : /* Txq ring length should be 2 times of Tx completion queue size. */
862 : 0 : txq->nb_tx_desc = nb_desc * 2;
863 [ # # ]: 0 : txq->queue_id = cpfl_hw_qid_get(cpfl_vport->p2p_q_chunks_info->tx_start_qid, logic_qid);
864 : 0 : txq->port_id = dev->data->port_id;
865 : 0 : hairpin_info->hairpin_q = true;
866 : 0 : hairpin_info->peer_rxp = peer_port;
867 : 0 : hairpin_info->peer_rxq_id = peer_q;
868 : :
869 [ # # ]: 0 : if (conf->manual_bind != 0)
870 : 0 : cpfl_vport->p2p_manual_bind = true;
871 : : else
872 : 0 : cpfl_vport->p2p_manual_bind = false;
873 : :
874 : : /* Always Tx hairpin queue allocates Tx HW ring */
875 : 0 : ring_size = RTE_ALIGN(txq->nb_tx_desc * CPFL_P2P_DESC_LEN,
876 : : CPFL_DMA_MEM_ALIGN);
877 : 0 : mz = rte_eth_dma_zone_reserve(dev, "hairpin_tx_ring", logic_qid,
878 : 0 : ring_size + CPFL_P2P_RING_BUF,
879 : : CPFL_RING_BASE_ALIGN,
880 : 0 : dev->device->numa_node);
881 [ # # ]: 0 : if (!mz) {
882 : 0 : PMD_INIT_LOG(ERR, "Failed to reserve DMA memory for TX");
883 : : ret = -ENOMEM;
884 : 0 : goto err_txq_mz_rsv;
885 : : }
886 : :
887 : 0 : txq->tx_ring_dma = mz->iova;
888 : 0 : txq->desc_ring = mz->addr;
889 : 0 : txq->mz = mz;
890 : :
891 : 0 : cpfl_tx_hairpin_descq_reset(txq);
892 : 0 : txq->qtx_tail = hw->hw_addr +
893 : 0 : cpfl_hw_qtail_get(cpfl_vport->p2p_q_chunks_info->tx_qtail_start,
894 [ # # ]: 0 : logic_qid, cpfl_vport->p2p_q_chunks_info->tx_qtail_spacing);
895 [ # # ]: 0 : if (cpfl_vport->p2p_tx_complq == NULL) {
896 : 0 : cq = rte_zmalloc_socket("cpfl hairpin cq",
897 : : sizeof(struct ci_tx_queue),
898 : : RTE_CACHE_LINE_SIZE,
899 : 0 : dev->device->numa_node);
900 [ # # ]: 0 : if (!cq) {
901 : 0 : PMD_INIT_LOG(ERR, "Failed to allocate memory for tx queue structure");
902 : : ret = -ENOMEM;
903 : 0 : goto err_cq_alloc;
904 : : }
905 : :
906 : 0 : cq->nb_tx_desc = nb_desc;
907 : 0 : cq->queue_id = cpfl_hw_qid_get(cpfl_vport->p2p_q_chunks_info->tx_compl_start_qid,
908 : : 0);
909 : 0 : cq->port_id = dev->data->port_id;
910 : :
911 : : /* Tx completion queue always allocates the HW ring */
912 : 0 : ring_size = RTE_ALIGN(cq->nb_tx_desc * CPFL_P2P_DESC_LEN,
913 : : CPFL_DMA_MEM_ALIGN);
914 : 0 : mz = rte_eth_dma_zone_reserve(dev, "hairpin_tx_compl_ring", logic_qid,
915 : 0 : ring_size + CPFL_P2P_RING_BUF,
916 : : CPFL_RING_BASE_ALIGN,
917 : 0 : dev->device->numa_node);
918 [ # # ]: 0 : if (!mz) {
919 : 0 : PMD_INIT_LOG(ERR, "Failed to reserve DMA memory for TX completion queue");
920 : : ret = -ENOMEM;
921 : 0 : goto err_cq_mz_rsv;
922 : : }
923 : 0 : cq->tx_ring_dma = mz->iova;
924 : 0 : cq->compl_ring = mz->addr;
925 : 0 : cq->mz = mz;
926 : :
927 : 0 : cpfl_tx_hairpin_complq_reset(cq);
928 : 0 : cpfl_vport->p2p_tx_complq = cq;
929 : : }
930 : :
931 : 0 : txq->complq = cpfl_vport->p2p_tx_complq;
932 : :
933 : 0 : cpfl_vport->nb_p2p_txq++;
934 : 0 : txq->q_set = true;
935 : 0 : dev->data->tx_queues[queue_idx] = cpfl_txq;
936 : :
937 : 0 : return 0;
938 : :
939 : : err_cq_mz_rsv:
940 : 0 : rte_free(cq);
941 : 0 : err_cq_alloc:
942 : : cpfl_dma_zone_release(mz);
943 : 0 : err_txq_mz_rsv:
944 : 0 : rte_free(cpfl_txq);
945 : 0 : return ret;
946 : : }
947 : :
948 : : int
949 : 0 : cpfl_hairpin_rx_bufq_config(struct cpfl_vport *cpfl_vport)
950 : : {
951 : 0 : struct idpf_rx_queue *rx_bufq = cpfl_vport->p2p_rx_bufq;
952 : : struct virtchnl2_rxq_info rxq_info;
953 : :
954 : : memset(&rxq_info, 0, sizeof(rxq_info));
955 : :
956 : 0 : rxq_info.type = VIRTCHNL2_QUEUE_TYPE_RX_BUFFER;
957 : 0 : rxq_info.queue_id = rx_bufq->queue_id;
958 : 0 : rxq_info.ring_len = rx_bufq->nb_rx_desc;
959 : 0 : rxq_info.dma_ring_addr = rx_bufq->rx_ring_phys_addr;
960 : 0 : rxq_info.desc_ids = VIRTCHNL2_RXDID_2_FLEX_SPLITQ_M;
961 : 0 : rxq_info.rx_buffer_low_watermark = CPFL_RXBUF_LOW_WATERMARK;
962 : 0 : rxq_info.model = VIRTCHNL2_QUEUE_MODEL_SPLIT;
963 : 0 : rxq_info.data_buffer_size = rx_bufq->rx_buf_len;
964 : 0 : rxq_info.buffer_notif_stride = CPFL_RX_BUF_STRIDE;
965 : :
966 : 0 : return idpf_vc_rxq_config_by_info(&cpfl_vport->base, &rxq_info, 1);
967 : : }
968 : :
969 : : int
970 : 0 : cpfl_hairpin_rxq_config(struct idpf_vport *vport, struct cpfl_rx_queue *cpfl_rxq)
971 : : {
972 : : struct virtchnl2_rxq_info rxq_info;
973 : : struct idpf_rx_queue *rxq = &cpfl_rxq->base;
974 : :
975 : : memset(&rxq_info, 0, sizeof(rxq_info));
976 : :
977 : 0 : rxq_info.type = VIRTCHNL2_QUEUE_TYPE_RX;
978 : 0 : rxq_info.queue_id = rxq->queue_id;
979 : 0 : rxq_info.ring_len = rxq->nb_rx_desc;
980 : 0 : rxq_info.dma_ring_addr = rxq->rx_ring_phys_addr;
981 : 0 : rxq_info.rx_bufq1_id = rxq->bufq1->queue_id;
982 : 0 : rxq_info.max_pkt_size = vport->max_pkt_len;
983 : 0 : rxq_info.desc_ids = VIRTCHNL2_RXDID_2_FLEX_SPLITQ_M;
984 : 0 : rxq_info.qflags |= VIRTCHNL2_RX_DESC_SIZE_16BYTE;
985 : :
986 : 0 : rxq_info.data_buffer_size = rxq->rx_buf_len;
987 : 0 : rxq_info.model = VIRTCHNL2_QUEUE_MODEL_SPLIT;
988 : 0 : rxq_info.rx_buffer_low_watermark = CPFL_RXBUF_LOW_WATERMARK;
989 : :
990 : 0 : PMD_DRV_LOG(NOTICE, "hairpin: vport %u, Rxq id 0x%x",
991 : : vport->vport_id, rxq_info.queue_id);
992 : :
993 : 0 : return idpf_vc_rxq_config_by_info(vport, &rxq_info, 1);
994 : : }
995 : :
996 : : int
997 : 0 : cpfl_hairpin_tx_complq_config(struct cpfl_vport *cpfl_vport)
998 : : {
999 : 0 : struct ci_tx_queue *tx_complq = cpfl_vport->p2p_tx_complq;
1000 : : struct virtchnl2_txq_info txq_info;
1001 : :
1002 : : memset(&txq_info, 0, sizeof(txq_info));
1003 : :
1004 : 0 : txq_info.dma_ring_addr = tx_complq->tx_ring_dma;
1005 : 0 : txq_info.type = VIRTCHNL2_QUEUE_TYPE_TX_COMPLETION;
1006 : 0 : txq_info.queue_id = tx_complq->queue_id;
1007 : 0 : txq_info.ring_len = tx_complq->nb_tx_desc;
1008 : 0 : txq_info.peer_rx_queue_id = cpfl_vport->p2p_rx_bufq->queue_id;
1009 : 0 : txq_info.model = VIRTCHNL2_QUEUE_MODEL_SPLIT;
1010 : 0 : txq_info.sched_mode = VIRTCHNL2_TXQ_SCHED_MODE_FLOW;
1011 : :
1012 : 0 : return idpf_vc_txq_config_by_info(&cpfl_vport->base, &txq_info, 1);
1013 : : }
1014 : :
1015 : : int
1016 : 0 : cpfl_hairpin_txq_config(struct idpf_vport *vport, struct cpfl_tx_queue *cpfl_txq)
1017 : : {
1018 : : struct ci_tx_queue *txq = &cpfl_txq->base;
1019 : : struct virtchnl2_txq_info txq_info;
1020 : :
1021 : : memset(&txq_info, 0, sizeof(txq_info));
1022 : :
1023 : 0 : txq_info.dma_ring_addr = txq->tx_ring_dma;
1024 : : txq_info.type = VIRTCHNL2_QUEUE_TYPE_TX;
1025 : 0 : txq_info.queue_id = txq->queue_id;
1026 : 0 : txq_info.ring_len = txq->nb_tx_desc;
1027 : 0 : txq_info.tx_compl_queue_id = txq->complq->queue_id;
1028 : 0 : txq_info.relative_queue_id = txq->queue_id;
1029 : 0 : txq_info.peer_rx_queue_id = cpfl_txq->hairpin_info.peer_rxq_id;
1030 : 0 : txq_info.model = VIRTCHNL2_QUEUE_MODEL_SPLIT;
1031 : 0 : txq_info.sched_mode = VIRTCHNL2_TXQ_SCHED_MODE_FLOW;
1032 : :
1033 : 0 : return idpf_vc_txq_config_by_info(vport, &txq_info, 1);
1034 : : }
1035 : :
1036 : : int
1037 : 0 : cpfl_switch_hairpin_complq(struct cpfl_vport *cpfl_vport, bool on)
1038 : : {
1039 : 0 : struct idpf_vport *vport = &cpfl_vport->base;
1040 : : uint32_t type;
1041 : : int err, queue_id;
1042 : :
1043 : : type = VIRTCHNL2_QUEUE_TYPE_TX_COMPLETION;
1044 : 0 : queue_id = cpfl_vport->p2p_tx_complq->queue_id;
1045 : 0 : err = idpf_vc_ena_dis_one_queue(vport, queue_id, type, on);
1046 : :
1047 : 0 : return err;
1048 : : }
1049 : :
1050 : : int
1051 : 0 : cpfl_switch_hairpin_bufq(struct cpfl_vport *cpfl_vport, bool on)
1052 : : {
1053 : 0 : struct idpf_vport *vport = &cpfl_vport->base;
1054 : : uint32_t type;
1055 : : int err, queue_id;
1056 : :
1057 : : type = VIRTCHNL2_QUEUE_TYPE_RX_BUFFER;
1058 : 0 : queue_id = cpfl_vport->p2p_rx_bufq->queue_id;
1059 : 0 : err = idpf_vc_ena_dis_one_queue(vport, queue_id, type, on);
1060 : :
1061 : 0 : return err;
1062 : : }
1063 : :
1064 : : int
1065 : 0 : cpfl_switch_hairpin_rxtx_queue(struct cpfl_vport *cpfl_vport, uint16_t logic_qid,
1066 : : bool rx, bool on)
1067 : : {
1068 : 0 : struct idpf_vport *vport = &cpfl_vport->base;
1069 : : uint32_t type;
1070 : : int err, queue_id;
1071 : :
1072 : 0 : type = rx ? VIRTCHNL2_QUEUE_TYPE_RX : VIRTCHNL2_QUEUE_TYPE_TX;
1073 : :
1074 [ # # ]: 0 : if (type == VIRTCHNL2_QUEUE_TYPE_RX)
1075 : 0 : queue_id = cpfl_hw_qid_get(cpfl_vport->p2p_q_chunks_info->rx_start_qid, logic_qid);
1076 : : else
1077 : 0 : queue_id = cpfl_hw_qid_get(cpfl_vport->p2p_q_chunks_info->tx_start_qid, logic_qid);
1078 : 0 : err = idpf_vc_ena_dis_one_queue(vport, queue_id, type, on);
1079 : : if (err)
1080 : : return err;
1081 : :
1082 : : return err;
1083 : : }
1084 : :
1085 : : static int
1086 : 0 : cpfl_alloc_split_p2p_rxq_mbufs(struct idpf_rx_queue *rxq)
1087 : : {
1088 : : volatile struct virtchnl2_p2p_rx_buf_desc *rxd;
1089 : : struct rte_mbuf *mbuf = NULL;
1090 : : uint64_t dma_addr;
1091 : : uint16_t i;
1092 : :
1093 [ # # ]: 0 : for (i = 0; i < rxq->nb_rx_desc; i++) {
1094 : 0 : mbuf = rte_mbuf_raw_alloc(rxq->mp);
1095 [ # # ]: 0 : if (unlikely(!mbuf)) {
1096 : 0 : PMD_DRV_LOG(ERR, "Failed to allocate mbuf for RX");
1097 : 0 : return -ENOMEM;
1098 : : }
1099 : :
1100 : : rte_mbuf_refcnt_set(mbuf, 1);
1101 : 0 : mbuf->next = NULL;
1102 : 0 : mbuf->data_off = RTE_PKTMBUF_HEADROOM;
1103 : 0 : mbuf->nb_segs = 1;
1104 : 0 : mbuf->port = rxq->port_id;
1105 : : dma_addr = rte_cpu_to_le_64(rte_mbuf_data_iova_default(mbuf));
1106 : :
1107 : 0 : rxd = &((volatile struct virtchnl2_p2p_rx_buf_desc *)(rxq->rx_ring))[i];
1108 : 0 : rxd->reserve0 = 0;
1109 : 0 : rxd->pkt_addr = dma_addr;
1110 : : }
1111 : :
1112 : 0 : rxq->nb_rx_hold = 0;
1113 : : /* The value written in the RX buffer queue tail register, must be a multiple of 8.*/
1114 : 0 : rxq->rx_tail = rxq->nb_rx_desc - CPFL_HAIRPIN_Q_TAIL_AUX_VALUE;
1115 : :
1116 : 0 : return 0;
1117 : : }
1118 : :
1119 : : int
1120 : 0 : cpfl_rx_queue_init(struct rte_eth_dev *dev, uint16_t rx_queue_id)
1121 : : {
1122 : : struct cpfl_rx_queue *cpfl_rxq;
1123 : : struct idpf_rx_queue *rxq;
1124 : : uint16_t max_pkt_len;
1125 : : uint32_t frame_size;
1126 : : int err;
1127 : :
1128 [ # # ]: 0 : if (rx_queue_id >= dev->data->nb_rx_queues)
1129 : : return -EINVAL;
1130 : :
1131 : 0 : cpfl_rxq = dev->data->rx_queues[rx_queue_id];
1132 : 0 : rxq = &cpfl_rxq->base;
1133 : :
1134 [ # # # # ]: 0 : if (rxq == NULL || !rxq->q_set) {
1135 : 0 : PMD_DRV_LOG(ERR, "RX queue %u not available or setup",
1136 : : rx_queue_id);
1137 : 0 : return -EINVAL;
1138 : : }
1139 : :
1140 : 0 : frame_size = dev->data->mtu + CPFL_ETH_OVERHEAD;
1141 : :
1142 : 0 : max_pkt_len =
1143 : 0 : RTE_MIN((uint32_t)CPFL_SUPPORT_CHAIN_NUM * rxq->rx_buf_len,
1144 : : frame_size);
1145 : :
1146 : 0 : rxq->max_pkt_len = max_pkt_len;
1147 [ # # # # ]: 0 : if ((dev->data->dev_conf.rxmode.offloads & RTE_ETH_RX_OFFLOAD_SCATTER) ||
1148 : : frame_size > rxq->rx_buf_len)
1149 : 0 : dev->data->scattered_rx = 1;
1150 : :
1151 : 0 : err = idpf_qc_ts_mbuf_register(rxq);
1152 [ # # ]: 0 : if (err != 0) {
1153 : 0 : PMD_DRV_LOG(ERR, "fail to register timestamp mbuf %u",
1154 : : rx_queue_id);
1155 : 0 : return -EIO;
1156 : : }
1157 : :
1158 [ # # ]: 0 : if (rxq->adapter->is_rx_singleq) {
1159 : : /* Single queue */
1160 : 0 : err = idpf_qc_single_rxq_mbufs_alloc(rxq);
1161 [ # # ]: 0 : if (err != 0) {
1162 : 0 : PMD_DRV_LOG(ERR, "Failed to allocate RX queue mbuf");
1163 : 0 : return err;
1164 : : }
1165 : :
1166 : : rte_wmb();
1167 : :
1168 : : /* Init the RX tail register. */
1169 : 0 : IDPF_PCI_REG_WRITE(rxq->qrx_tail, rxq->nb_rx_desc - 1);
1170 : : } else {
1171 : : /* Split queue */
1172 [ # # ]: 0 : if (cpfl_rxq->hairpin_info.hairpin_q) {
1173 : 0 : err = cpfl_alloc_split_p2p_rxq_mbufs(rxq->bufq1);
1174 [ # # ]: 0 : if (err != 0) {
1175 : 0 : PMD_DRV_LOG(ERR, "Failed to allocate p2p RX buffer queue mbuf");
1176 : 0 : return err;
1177 : : }
1178 : : } else {
1179 : 0 : err = idpf_qc_split_rxq_mbufs_alloc(rxq->bufq1);
1180 [ # # ]: 0 : if (err != 0) {
1181 : 0 : PMD_DRV_LOG(ERR, "Failed to allocate RX buffer queue mbuf");
1182 : 0 : return err;
1183 : : }
1184 : 0 : err = idpf_qc_split_rxq_mbufs_alloc(rxq->bufq2);
1185 [ # # ]: 0 : if (err != 0) {
1186 : 0 : PMD_DRV_LOG(ERR, "Failed to allocate RX buffer queue mbuf");
1187 : 0 : return err;
1188 : : }
1189 : : }
1190 : :
1191 : : rte_wmb();
1192 : :
1193 : : /* Init the RX tail register. */
1194 : 0 : IDPF_PCI_REG_WRITE(rxq->bufq1->qrx_tail, rxq->bufq1->rx_tail);
1195 [ # # ]: 0 : if (rxq->bufq2)
1196 : 0 : IDPF_PCI_REG_WRITE(rxq->bufq2->qrx_tail, rxq->bufq2->rx_tail);
1197 : : }
1198 : :
1199 : : return err;
1200 : : }
1201 : :
1202 : : int
1203 : 0 : cpfl_rx_queue_start(struct rte_eth_dev *dev, uint16_t rx_queue_id)
1204 : : {
1205 : 0 : struct cpfl_vport *cpfl_vport = dev->data->dev_private;
1206 : 0 : struct idpf_vport *vport = &cpfl_vport->base;
1207 : 0 : struct cpfl_rx_queue *cpfl_rxq = dev->data->rx_queues[rx_queue_id];
1208 : 0 : struct idpf_rx_queue *rxq = &cpfl_rxq->base;
1209 : : int err = 0;
1210 : :
1211 : 0 : err = idpf_vc_rxq_config(vport, rxq);
1212 [ # # ]: 0 : if (err != 0) {
1213 : 0 : PMD_DRV_LOG(ERR, "Fail to configure Rx queue %u", rx_queue_id);
1214 : 0 : return err;
1215 : : }
1216 : :
1217 : 0 : err = cpfl_rx_queue_init(dev, rx_queue_id);
1218 [ # # ]: 0 : if (err != 0) {
1219 : 0 : PMD_DRV_LOG(ERR, "Failed to init RX queue %u",
1220 : : rx_queue_id);
1221 : 0 : return err;
1222 : : }
1223 : :
1224 : : /* Ready to switch the queue on */
1225 : 0 : err = idpf_vc_queue_switch(vport, rx_queue_id, true, true,
1226 : : VIRTCHNL2_QUEUE_TYPE_RX);
1227 [ # # ]: 0 : if (err != 0) {
1228 : 0 : PMD_DRV_LOG(ERR, "Failed to switch RX queue %u on",
1229 : : rx_queue_id);
1230 : : } else {
1231 : 0 : rxq->q_started = true;
1232 : 0 : dev->data->rx_queue_state[rx_queue_id] =
1233 : : RTE_ETH_QUEUE_STATE_STARTED;
1234 : : }
1235 : :
1236 : : return err;
1237 : : }
1238 : :
1239 : : int
1240 : 0 : cpfl_tx_queue_init(struct rte_eth_dev *dev, uint16_t tx_queue_id)
1241 : : {
1242 : : struct cpfl_tx_queue *cpfl_txq;
1243 : :
1244 [ # # ]: 0 : if (tx_queue_id >= dev->data->nb_tx_queues)
1245 : : return -EINVAL;
1246 : :
1247 : 0 : cpfl_txq = dev->data->tx_queues[tx_queue_id];
1248 : :
1249 : : /* Init the RX tail register. */
1250 : 0 : IDPF_PCI_REG_WRITE(cpfl_txq->base.qtx_tail, 0);
1251 : :
1252 : 0 : return 0;
1253 : : }
1254 : :
1255 : : int
1256 : 0 : cpfl_tx_queue_start(struct rte_eth_dev *dev, uint16_t tx_queue_id)
1257 : : {
1258 : 0 : struct cpfl_vport *cpfl_vport = dev->data->dev_private;
1259 : 0 : struct idpf_vport *vport = &cpfl_vport->base;
1260 : 0 : struct cpfl_tx_queue *cpfl_txq =
1261 : 0 : dev->data->tx_queues[tx_queue_id];
1262 : : int err = 0;
1263 : :
1264 : 0 : err = idpf_vc_txq_config(vport, &cpfl_txq->base);
1265 [ # # ]: 0 : if (err != 0) {
1266 : 0 : PMD_DRV_LOG(ERR, "Fail to configure Tx queue %u", tx_queue_id);
1267 : 0 : return err;
1268 : : }
1269 : :
1270 : 0 : err = cpfl_tx_queue_init(dev, tx_queue_id);
1271 [ # # ]: 0 : if (err != 0) {
1272 : 0 : PMD_DRV_LOG(ERR, "Failed to init TX queue %u",
1273 : : tx_queue_id);
1274 : 0 : return err;
1275 : : }
1276 : :
1277 : : /* Ready to switch the queue on */
1278 : 0 : err = idpf_vc_queue_switch(vport, tx_queue_id, false, true,
1279 : : VIRTCHNL2_QUEUE_TYPE_TX);
1280 [ # # ]: 0 : if (err != 0) {
1281 : 0 : PMD_DRV_LOG(ERR, "Failed to switch TX queue %u on",
1282 : : tx_queue_id);
1283 : : } else {
1284 : 0 : dev->data->tx_queue_state[tx_queue_id] =
1285 : : RTE_ETH_QUEUE_STATE_STARTED;
1286 : : }
1287 : :
1288 : : return err;
1289 : : }
1290 : :
1291 : : int
1292 : 0 : cpfl_rx_queue_stop(struct rte_eth_dev *dev, uint16_t rx_queue_id)
1293 : : {
1294 : 0 : struct cpfl_vport *cpfl_vport = dev->data->dev_private;
1295 : 0 : struct idpf_vport *vport = &cpfl_vport->base;
1296 : : struct cpfl_rx_queue *cpfl_rxq;
1297 : : struct idpf_rx_queue *rxq;
1298 : : int err;
1299 : :
1300 [ # # ]: 0 : if (rx_queue_id >= dev->data->nb_rx_queues)
1301 : : return -EINVAL;
1302 : :
1303 : 0 : cpfl_rxq = dev->data->rx_queues[rx_queue_id];
1304 [ # # ]: 0 : if (cpfl_rxq->hairpin_info.hairpin_q)
1305 : 0 : err = cpfl_switch_hairpin_rxtx_queue(cpfl_vport,
1306 : 0 : rx_queue_id - cpfl_vport->nb_data_txq,
1307 : : true, false);
1308 : : else
1309 : 0 : err = idpf_vc_queue_switch(vport, rx_queue_id, true, false,
1310 : : VIRTCHNL2_QUEUE_TYPE_RX);
1311 [ # # ]: 0 : if (err != 0) {
1312 : 0 : PMD_DRV_LOG(ERR, "Failed to switch RX queue %u off",
1313 : : rx_queue_id);
1314 : 0 : return err;
1315 : : }
1316 : :
1317 : 0 : rxq = &cpfl_rxq->base;
1318 : 0 : rxq->q_started = false;
1319 [ # # ]: 0 : if (vport->rxq_model == VIRTCHNL2_QUEUE_MODEL_SINGLE) {
1320 : 0 : rxq->idpf_ops->release_mbufs(rxq);
1321 : 0 : idpf_qc_single_rx_queue_reset(rxq);
1322 : : } else {
1323 : 0 : rxq->bufq1->idpf_ops->release_mbufs(rxq->bufq1);
1324 [ # # ]: 0 : if (rxq->bufq2)
1325 : 0 : rxq->bufq2->idpf_ops->release_mbufs(rxq->bufq2);
1326 [ # # ]: 0 : if (cpfl_rxq->hairpin_info.hairpin_q) {
1327 : : cpfl_rx_hairpin_descq_reset(rxq);
1328 [ # # ]: 0 : cpfl_rx_hairpin_bufq_reset(rxq->bufq1);
1329 : : } else {
1330 : 0 : idpf_qc_split_rx_queue_reset(rxq);
1331 : : }
1332 : : }
1333 [ # # ]: 0 : if (!cpfl_rxq->hairpin_info.hairpin_q)
1334 : 0 : dev->data->rx_queue_state[rx_queue_id] = RTE_ETH_QUEUE_STATE_STOPPED;
1335 : :
1336 : : return 0;
1337 : : }
1338 : :
1339 : : int
1340 : 0 : cpfl_tx_queue_stop(struct rte_eth_dev *dev, uint16_t tx_queue_id)
1341 : : {
1342 : 0 : struct cpfl_vport *cpfl_vport = dev->data->dev_private;
1343 : 0 : struct idpf_vport *vport = &cpfl_vport->base;
1344 : : struct cpfl_tx_queue *cpfl_txq;
1345 : : struct ci_tx_queue *txq;
1346 : : int err;
1347 : :
1348 [ # # ]: 0 : if (tx_queue_id >= dev->data->nb_tx_queues)
1349 : : return -EINVAL;
1350 : :
1351 : 0 : cpfl_txq = dev->data->tx_queues[tx_queue_id];
1352 : :
1353 [ # # ]: 0 : if (cpfl_txq->hairpin_info.hairpin_q)
1354 : 0 : err = cpfl_switch_hairpin_rxtx_queue(cpfl_vport,
1355 : 0 : tx_queue_id - cpfl_vport->nb_data_txq,
1356 : : false, false);
1357 : : else
1358 : 0 : err = idpf_vc_queue_switch(vport, tx_queue_id, false, false,
1359 : : VIRTCHNL2_QUEUE_TYPE_TX);
1360 [ # # ]: 0 : if (err != 0) {
1361 : 0 : PMD_DRV_LOG(ERR, "Failed to switch TX queue %u off",
1362 : : tx_queue_id);
1363 : 0 : return err;
1364 : : }
1365 : :
1366 : 0 : txq = &cpfl_txq->base;
1367 : 0 : ci_txq_release_all_mbufs(txq, txq->use_vec_entry);
1368 [ # # ]: 0 : if (vport->txq_model == VIRTCHNL2_QUEUE_MODEL_SINGLE) {
1369 : 0 : idpf_qc_single_tx_queue_reset(txq);
1370 : : } else {
1371 [ # # ]: 0 : if (cpfl_txq->hairpin_info.hairpin_q) {
1372 : 0 : cpfl_tx_hairpin_descq_reset(txq);
1373 : 0 : cpfl_tx_hairpin_complq_reset(txq->complq);
1374 : : } else {
1375 : 0 : idpf_qc_split_tx_descq_reset(txq);
1376 : 0 : idpf_qc_split_tx_complq_reset(txq->complq);
1377 : : }
1378 : : }
1379 : :
1380 [ # # ]: 0 : if (!cpfl_txq->hairpin_info.hairpin_q)
1381 : 0 : dev->data->tx_queue_state[tx_queue_id] = RTE_ETH_QUEUE_STATE_STOPPED;
1382 : :
1383 : : return 0;
1384 : : }
1385 : :
1386 : : void
1387 : 0 : cpfl_dev_rx_queue_release(struct rte_eth_dev *dev, uint16_t qid)
1388 : : {
1389 : 0 : cpfl_rx_queue_release(dev->data->rx_queues[qid]);
1390 : 0 : }
1391 : :
1392 : : void
1393 : 0 : cpfl_dev_tx_queue_release(struct rte_eth_dev *dev, uint16_t qid)
1394 : : {
1395 : 0 : cpfl_tx_queue_release(dev->data->tx_queues[qid]);
1396 : 0 : }
1397 : :
1398 : : void
1399 : 0 : cpfl_stop_queues(struct rte_eth_dev *dev)
1400 : : {
1401 : 0 : struct cpfl_vport *cpfl_vport =
1402 : 0 : (struct cpfl_vport *)dev->data->dev_private;
1403 : : struct cpfl_rx_queue *cpfl_rxq;
1404 : : struct cpfl_tx_queue *cpfl_txq;
1405 : : int i;
1406 : :
1407 [ # # ]: 0 : if (cpfl_vport->p2p_tx_complq != NULL) {
1408 [ # # ]: 0 : if (cpfl_switch_hairpin_complq(cpfl_vport, false) != 0)
1409 : 0 : PMD_DRV_LOG(ERR, "Failed to stop hairpin Tx complq");
1410 : : }
1411 : :
1412 [ # # ]: 0 : if (cpfl_vport->p2p_rx_bufq != NULL) {
1413 [ # # ]: 0 : if (cpfl_switch_hairpin_bufq(cpfl_vport, false) != 0)
1414 : 0 : PMD_DRV_LOG(ERR, "Failed to stop hairpin Rx bufq");
1415 : : }
1416 : :
1417 [ # # ]: 0 : for (i = 0; i < dev->data->nb_rx_queues; i++) {
1418 : 0 : cpfl_rxq = dev->data->rx_queues[i];
1419 [ # # ]: 0 : if (cpfl_rxq == NULL)
1420 : 0 : continue;
1421 : :
1422 [ # # ]: 0 : if (cpfl_rx_queue_stop(dev, i) != 0)
1423 : 0 : PMD_DRV_LOG(WARNING, "Fail to stop Rx queue %d", i);
1424 : : }
1425 : :
1426 [ # # ]: 0 : for (i = 0; i < dev->data->nb_tx_queues; i++) {
1427 : 0 : cpfl_txq = dev->data->tx_queues[i];
1428 [ # # ]: 0 : if (cpfl_txq == NULL)
1429 : 0 : continue;
1430 : :
1431 [ # # ]: 0 : if (cpfl_tx_queue_stop(dev, i) != 0)
1432 : 0 : PMD_DRV_LOG(WARNING, "Fail to stop Tx queue %d", i);
1433 : : }
1434 : 0 : }
1435 : :
1436 : : void
1437 : 0 : cpfl_set_rx_function(struct rte_eth_dev *dev)
1438 : : {
1439 : 0 : struct cpfl_vport *cpfl_vport = dev->data->dev_private;
1440 : : struct idpf_vport *vport = &cpfl_vport->base;
1441 : 0 : struct idpf_adapter *ad = vport->adapter;
1442 : 0 : struct ci_rx_path_features req_features = {
1443 : 0 : .rx_offloads = dev->data->dev_conf.rxmode.offloads,
1444 : : .simd_width = RTE_VECT_SIMD_DISABLED,
1445 : : };
1446 : : #ifdef RTE_ARCH_X86
1447 : : struct cpfl_rx_queue *cpfl_rxq;
1448 : : int i;
1449 : : #endif
1450 : :
1451 : : /* If the device has started the function has already been selected. */
1452 [ # # ]: 0 : if (dev->data->dev_started)
1453 : 0 : goto out;
1454 : :
1455 : : #ifdef RTE_ARCH_X86
1456 [ # # # # ]: 0 : if (cpfl_rx_vec_dev_check_default(dev) == CPFL_VECTOR_PATH &&
1457 : 0 : rte_vect_get_max_simd_bitwidth() >= RTE_VECT_SIMD_256)
1458 : 0 : req_features.simd_width = cpfl_get_max_simd_bitwidth();
1459 : : #endif
1460 : :
1461 : 0 : req_features.single_queue = (vport->rxq_model == VIRTCHNL2_QUEUE_MODEL_SINGLE);
1462 : 0 : req_features.scattered = dev->data->scattered_rx;
1463 : :
1464 : 0 : ad->rx_func_type = ci_rx_path_select(&req_features,
1465 : : &idpf_rx_path_infos[0],
1466 : : IDPF_RX_MAX,
1467 : : IDPF_RX_DEFAULT);
1468 : :
1469 : : #ifdef RTE_ARCH_X86
1470 [ # # ]: 0 : if (idpf_rx_path_infos[ad->rx_func_type].features.simd_width >= RTE_VECT_SIMD_256) {
1471 : : /* Vector function selected. Prepare the rxq accordingly. */
1472 [ # # ]: 0 : if (idpf_rx_path_infos[ad->rx_func_type].features.single_queue) {
1473 [ # # ]: 0 : for (i = 0; i < dev->data->nb_rx_queues; i++) {
1474 : 0 : cpfl_rxq = dev->data->rx_queues[i];
1475 : 0 : (void)idpf_qc_singleq_rx_vec_setup(&cpfl_rxq->base);
1476 : : }
1477 : : } else {
1478 [ # # ]: 0 : for (i = 0; i < dev->data->nb_rx_queues; i++) {
1479 : 0 : cpfl_rxq = dev->data->rx_queues[i];
1480 [ # # ]: 0 : if (cpfl_rxq->hairpin_info.hairpin_q)
1481 : 0 : continue;
1482 : 0 : (void)idpf_qc_splitq_rx_vec_setup(&cpfl_rxq->base);
1483 : : }
1484 : : }
1485 : : }
1486 : : #endif
1487 : :
1488 : 0 : out:
1489 : 0 : dev->rx_pkt_burst = idpf_rx_path_infos[ad->rx_func_type].pkt_burst;
1490 : 0 : PMD_DRV_LOG(NOTICE, "Using %s Rx (port %d).",
1491 : : idpf_rx_path_infos[ad->rx_func_type].info, dev->data->port_id);
1492 : :
1493 : 0 : }
1494 : :
1495 : : static bool
1496 : 0 : cpfl_tx_simple_allowed(struct rte_eth_dev *dev)
1497 : : {
1498 : 0 : struct cpfl_vport *cpfl_vport = dev->data->dev_private;
1499 : : struct idpf_vport *vport = &cpfl_vport->base;
1500 : : struct ci_tx_queue *txq;
1501 : :
1502 [ # # ]: 0 : if (vport->txq_model != VIRTCHNL2_QUEUE_MODEL_SINGLE)
1503 : : return false;
1504 : :
1505 [ # # ]: 0 : for (int i = 0; i < dev->data->nb_tx_queues; i++) {
1506 : 0 : txq = dev->data->tx_queues[i];
1507 [ # # ]: 0 : if (txq == NULL)
1508 : 0 : continue;
1509 [ # # ]: 0 : if (txq->offloads != (txq->offloads & RTE_ETH_TX_OFFLOAD_MBUF_FAST_FREE) ||
1510 [ # # ]: 0 : txq->tx_rs_thresh < IDPF_VPMD_TX_MAX_BURST)
1511 : : return false;
1512 : : }
1513 : : return true;
1514 : : }
1515 : :
1516 : : void
1517 : 0 : cpfl_set_tx_function(struct rte_eth_dev *dev)
1518 : : {
1519 : 0 : struct cpfl_vport *cpfl_vport = dev->data->dev_private;
1520 : : struct idpf_vport *vport = &cpfl_vport->base;
1521 : : struct ci_tx_queue *txq;
1522 : : int i;
1523 : 0 : struct idpf_adapter *ad = vport->adapter;
1524 : 0 : bool simple_allowed = cpfl_tx_simple_allowed(dev);
1525 : 0 : struct ci_tx_path_features req_features = {
1526 : 0 : .tx_offloads = dev->data->dev_conf.txmode.offloads,
1527 : : .simd_width = RTE_VECT_SIMD_DISABLED,
1528 : 0 : .single_queue = (vport->txq_model == VIRTCHNL2_QUEUE_MODEL_SINGLE),
1529 : : .simple_tx = simple_allowed
1530 : : };
1531 : :
1532 : : /* If the device has started the function has already been selected. */
1533 [ # # ]: 0 : if (dev->data->dev_started)
1534 : 0 : goto out;
1535 : :
1536 : : #ifdef RTE_ARCH_X86
1537 [ # # ]: 0 : if (cpfl_tx_vec_dev_check_default(dev) == CPFL_VECTOR_PATH)
1538 : 0 : req_features.simd_width = cpfl_get_max_simd_bitwidth();
1539 : : #endif
1540 : :
1541 : 0 : ad->tx_func_type = ci_tx_path_select(&req_features,
1542 : : &idpf_tx_path_infos[0],
1543 : : IDPF_TX_MAX,
1544 : : IDPF_TX_DEFAULT);
1545 : :
1546 : : /* Set use_vec_entry for single queue mode - only IDPF_TX_SINGLEQ uses regular entries */
1547 [ # # ]: 0 : if (vport->txq_model == VIRTCHNL2_QUEUE_MODEL_SINGLE) {
1548 [ # # ]: 0 : for (i = 0; i < dev->data->nb_tx_queues; i++) {
1549 : 0 : txq = dev->data->tx_queues[i];
1550 [ # # ]: 0 : if (txq == NULL)
1551 : 0 : continue;
1552 : 0 : txq->use_vec_entry = (ad->tx_func_type != IDPF_TX_SINGLEQ);
1553 : : }
1554 : : }
1555 : :
1556 : 0 : out:
1557 : 0 : dev->tx_pkt_burst = idpf_tx_path_infos[ad->tx_func_type].pkt_burst;
1558 : 0 : dev->tx_pkt_prepare = idpf_dp_prep_pkts;
1559 : 0 : PMD_DRV_LOG(NOTICE, "Using %s Tx (port %d).",
1560 : : idpf_tx_path_infos[ad->tx_func_type].info, dev->data->port_id);
1561 : 0 : }
|