Branch data Line data Source code
1 : : /* SPDX-License-Identifier: BSD-3-Clause
2 : : * Copyright(c) 2022 Intel Corporation
3 : : */
4 : :
5 : : #include <ethdev_driver.h>
6 : : #include <rte_net.h>
7 : : #include <rte_vect.h>
8 : :
9 : : #include "idpf_ethdev.h"
10 : : #include "idpf_rxtx.h"
11 : : #include "idpf_rxtx_vec_common.h"
12 : :
13 : : static uint64_t
14 : 0 : idpf_rx_offload_convert(uint64_t offload)
15 : : {
16 : : uint64_t ol = 0;
17 : :
18 [ # # ]: 0 : if ((offload & RTE_ETH_RX_OFFLOAD_IPV4_CKSUM) != 0)
19 : : ol |= IDPF_RX_OFFLOAD_IPV4_CKSUM;
20 [ # # ]: 0 : if ((offload & RTE_ETH_RX_OFFLOAD_UDP_CKSUM) != 0)
21 : 0 : ol |= IDPF_RX_OFFLOAD_UDP_CKSUM;
22 [ # # ]: 0 : if ((offload & RTE_ETH_RX_OFFLOAD_TCP_CKSUM) != 0)
23 : 0 : ol |= IDPF_RX_OFFLOAD_TCP_CKSUM;
24 [ # # ]: 0 : if ((offload & RTE_ETH_RX_OFFLOAD_OUTER_IPV4_CKSUM) != 0)
25 : 0 : ol |= IDPF_RX_OFFLOAD_OUTER_IPV4_CKSUM;
26 [ # # ]: 0 : if ((offload & RTE_ETH_RX_OFFLOAD_TIMESTAMP) != 0)
27 : 0 : ol |= IDPF_RX_OFFLOAD_TIMESTAMP;
28 : :
29 : 0 : return ol;
30 : : }
31 : :
32 : : static uint64_t
33 : 0 : idpf_tx_offload_convert(uint64_t offload)
34 : : {
35 : : uint64_t ol = 0;
36 : :
37 [ # # ]: 0 : if ((offload & RTE_ETH_TX_OFFLOAD_IPV4_CKSUM) != 0)
38 : : ol |= IDPF_TX_OFFLOAD_IPV4_CKSUM;
39 [ # # ]: 0 : if ((offload & RTE_ETH_TX_OFFLOAD_UDP_CKSUM) != 0)
40 : 0 : ol |= IDPF_TX_OFFLOAD_UDP_CKSUM;
41 [ # # ]: 0 : if ((offload & RTE_ETH_TX_OFFLOAD_TCP_CKSUM) != 0)
42 : 0 : ol |= IDPF_TX_OFFLOAD_TCP_CKSUM;
43 [ # # ]: 0 : if ((offload & RTE_ETH_TX_OFFLOAD_SCTP_CKSUM) != 0)
44 : 0 : ol |= IDPF_TX_OFFLOAD_SCTP_CKSUM;
45 [ # # ]: 0 : if ((offload & RTE_ETH_TX_OFFLOAD_TCP_TSO) != 0)
46 : 0 : ol |= IDPF_TX_OFFLOAD_TCP_TSO;
47 [ # # ]: 0 : if ((offload & RTE_ETH_TX_OFFLOAD_MULTI_SEGS) != 0)
48 : 0 : ol |= IDPF_TX_OFFLOAD_MULTI_SEGS;
49 [ # # ]: 0 : if ((offload & RTE_ETH_TX_OFFLOAD_MBUF_FAST_FREE) != 0)
50 : 0 : ol |= IDPF_TX_OFFLOAD_MBUF_FAST_FREE;
51 : :
52 : 0 : return ol;
53 : : }
54 : :
55 : : static const struct idpf_rxq_ops def_rxq_ops = {
56 : : .release_mbufs = idpf_qc_rxq_mbufs_release,
57 : : };
58 : :
59 : : static const struct rte_memzone *
60 [ # # # # : 0 : idpf_dma_zone_reserve(struct rte_eth_dev *dev, uint16_t queue_idx,
# ]
61 : : uint16_t len, uint16_t queue_type,
62 : : unsigned int socket_id, bool splitq)
63 : : {
64 : : char ring_name[RTE_MEMZONE_NAMESIZE];
65 : : const struct rte_memzone *mz;
66 : : uint32_t ring_size;
67 : :
68 : : memset(ring_name, 0, RTE_MEMZONE_NAMESIZE);
69 [ # # # # : 0 : switch (queue_type) {
# ]
70 : 0 : case VIRTCHNL2_QUEUE_TYPE_TX:
71 [ # # ]: 0 : if (splitq)
72 : 0 : ring_size = RTE_ALIGN(len * sizeof(struct idpf_flex_tx_sched_desc),
73 : : IDPF_DMA_MEM_ALIGN);
74 : : else
75 : 0 : ring_size = RTE_ALIGN(len * sizeof(struct idpf_base_tx_desc),
76 : : IDPF_DMA_MEM_ALIGN);
77 : : rte_memcpy(ring_name, "idpf Tx ring", sizeof("idpf Tx ring"));
78 : : break;
79 : 0 : case VIRTCHNL2_QUEUE_TYPE_RX:
80 [ # # ]: 0 : if (splitq)
81 : 0 : ring_size = RTE_ALIGN(len * sizeof(struct virtchnl2_rx_flex_desc_adv_nic_3),
82 : : IDPF_DMA_MEM_ALIGN);
83 : : else
84 : 0 : ring_size = RTE_ALIGN(len * sizeof(struct virtchnl2_singleq_rx_buf_desc),
85 : : IDPF_DMA_MEM_ALIGN);
86 : : rte_memcpy(ring_name, "idpf Rx ring", sizeof("idpf Rx ring"));
87 : : break;
88 : 0 : case VIRTCHNL2_QUEUE_TYPE_TX_COMPLETION:
89 [ # # ]: 0 : ring_size = RTE_ALIGN(len * sizeof(struct idpf_splitq_tx_compl_desc),
90 : : IDPF_DMA_MEM_ALIGN);
91 : : rte_memcpy(ring_name, "idpf Tx compl ring", sizeof("idpf Tx compl ring"));
92 : : break;
93 : 0 : case VIRTCHNL2_QUEUE_TYPE_RX_BUFFER:
94 [ # # ]: 0 : ring_size = RTE_ALIGN(len * sizeof(struct virtchnl2_splitq_rx_buf_desc),
95 : : IDPF_DMA_MEM_ALIGN);
96 : : rte_memcpy(ring_name, "idpf Rx buf ring", sizeof("idpf Rx buf ring"));
97 : : break;
98 : 0 : default:
99 : 0 : PMD_INIT_LOG(ERR, "Invalid queue type");
100 : 0 : return NULL;
101 : : }
102 : :
103 : 0 : mz = rte_eth_dma_zone_reserve(dev, ring_name, queue_idx,
104 : : ring_size, IDPF_RING_BASE_ALIGN,
105 : : socket_id);
106 [ # # ]: 0 : if (mz == NULL) {
107 : 0 : PMD_INIT_LOG(ERR, "Failed to reserve DMA memory for ring");
108 : 0 : return NULL;
109 : : }
110 : :
111 : : /* Zero all the descriptors in the ring. */
112 : 0 : memset(mz->addr, 0, ring_size);
113 : :
114 : 0 : return mz;
115 : : }
116 : :
117 : : static void
118 : : idpf_dma_zone_release(const struct rte_memzone *mz)
119 : : {
120 : 0 : rte_memzone_free(mz);
121 : 0 : }
122 : :
123 : : static int
124 : 0 : idpf_rx_split_bufq_setup(struct rte_eth_dev *dev, struct idpf_rx_queue *rxq,
125 : : uint16_t queue_idx, uint16_t rx_free_thresh,
126 : : uint16_t nb_desc, unsigned int socket_id,
127 : : struct rte_mempool *mp, uint8_t bufq_id)
128 : : {
129 : 0 : struct idpf_vport *vport = dev->data->dev_private;
130 : 0 : struct idpf_adapter *adapter = vport->adapter;
131 : : struct idpf_hw *hw = &adapter->hw;
132 : : const struct rte_memzone *mz;
133 : : struct idpf_rx_queue *bufq;
134 : : uint16_t len;
135 : : int ret;
136 : :
137 : 0 : bufq = rte_zmalloc_socket("idpf bufq",
138 : : sizeof(struct idpf_rx_queue),
139 : : RTE_CACHE_LINE_SIZE,
140 : : socket_id);
141 [ # # ]: 0 : if (bufq == NULL) {
142 : 0 : PMD_INIT_LOG(ERR, "Failed to allocate memory for rx buffer queue.");
143 : : ret = -ENOMEM;
144 : 0 : goto err_bufq1_alloc;
145 : : }
146 : :
147 : 0 : bufq->mp = mp;
148 : 0 : bufq->nb_rx_desc = nb_desc;
149 : 0 : bufq->rx_free_thresh = rx_free_thresh;
150 : 0 : bufq->queue_id = vport->chunks_info.rx_buf_start_qid + queue_idx;
151 : 0 : bufq->port_id = dev->data->port_id;
152 : 0 : bufq->rx_hdr_len = 0;
153 [ # # ]: 0 : bufq->adapter = adapter;
154 : :
155 : 0 : len = rte_pktmbuf_data_room_size(bufq->mp) - RTE_PKTMBUF_HEADROOM;
156 : 0 : bufq->rx_buf_len = RTE_ALIGN_FLOOR(len, (1 << IDPF_RLAN_CTX_DBUF_S));
157 : 0 : bufq->rx_buf_len = RTE_MIN(bufq->rx_buf_len, IDPF_RX_MAX_DATA_BUF_SIZE);
158 : :
159 : : /* Allocate a little more to support bulk allocate. */
160 : 0 : len = nb_desc + IDPF_RX_MAX_BURST;
161 : :
162 : 0 : mz = idpf_dma_zone_reserve(dev, queue_idx, len,
163 : : VIRTCHNL2_QUEUE_TYPE_RX_BUFFER,
164 : : socket_id, true);
165 [ # # ]: 0 : if (mz == NULL) {
166 : : ret = -ENOMEM;
167 : 0 : goto err_mz_reserve;
168 : : }
169 : :
170 : 0 : bufq->rx_ring_phys_addr = mz->iova;
171 : 0 : bufq->rx_ring = mz->addr;
172 : 0 : bufq->mz = mz;
173 : :
174 : 0 : bufq->sw_ring =
175 : 0 : rte_zmalloc_socket("idpf rx bufq sw ring",
176 : : sizeof(struct rte_mbuf *) * len,
177 : : RTE_CACHE_LINE_SIZE,
178 : : socket_id);
179 [ # # ]: 0 : if (bufq->sw_ring == NULL) {
180 : 0 : PMD_INIT_LOG(ERR, "Failed to allocate memory for SW ring");
181 : : ret = -ENOMEM;
182 : 0 : goto err_sw_ring_alloc;
183 : : }
184 : :
185 : 0 : idpf_qc_split_rx_bufq_reset(bufq);
186 : 0 : bufq->qrx_tail = hw->hw_addr + (vport->chunks_info.rx_buf_qtail_start +
187 : 0 : queue_idx * vport->chunks_info.rx_buf_qtail_spacing);
188 : 0 : bufq->idpf_ops = &def_rxq_ops;
189 : 0 : bufq->q_set = true;
190 : :
191 [ # # ]: 0 : if (bufq_id == IDPF_RX_SPLIT_BUFQ1_ID) {
192 : 0 : rxq->bufq1 = bufq;
193 [ # # ]: 0 : } else if (bufq_id == IDPF_RX_SPLIT_BUFQ2_ID) {
194 : 0 : rxq->bufq2 = bufq;
195 : : } else {
196 : 0 : PMD_INIT_LOG(ERR, "Invalid buffer queue index.");
197 : : ret = -EINVAL;
198 : 0 : goto err_bufq_id;
199 : : }
200 : :
201 : : return 0;
202 : :
203 : : err_bufq_id:
204 : 0 : rte_free(bufq->sw_ring);
205 : 0 : err_sw_ring_alloc:
206 : : idpf_dma_zone_release(mz);
207 : 0 : err_mz_reserve:
208 : 0 : rte_free(bufq);
209 : : err_bufq1_alloc:
210 : : return ret;
211 : : }
212 : :
213 : : static void
214 : 0 : idpf_rx_split_bufq_release(struct idpf_rx_queue *bufq)
215 : : {
216 : 0 : rte_free(bufq->sw_ring);
217 : 0 : idpf_dma_zone_release(bufq->mz);
218 : 0 : rte_free(bufq);
219 : 0 : }
220 : :
221 : : int
222 : 0 : idpf_rx_queue_setup(struct rte_eth_dev *dev, uint16_t queue_idx,
223 : : uint16_t nb_desc, unsigned int socket_id,
224 : : const struct rte_eth_rxconf *rx_conf,
225 : : struct rte_mempool *mp)
226 : : {
227 : 0 : struct idpf_vport *vport = dev->data->dev_private;
228 : 0 : struct idpf_adapter *adapter = vport->adapter;
229 : : struct idpf_hw *hw = &adapter->hw;
230 : : const struct rte_memzone *mz;
231 : : struct idpf_rx_queue *rxq;
232 : : uint16_t rx_free_thresh;
233 : : uint64_t offloads;
234 : : bool is_splitq;
235 : : uint16_t len;
236 : : int ret;
237 : :
238 : 0 : offloads = rx_conf->offloads | dev->data->dev_conf.rxmode.offloads;
239 : :
240 : : /* Check free threshold */
241 [ # # ]: 0 : rx_free_thresh = (rx_conf->rx_free_thresh == 0) ?
242 : : IDPF_DEFAULT_RX_FREE_THRESH :
243 : : rx_conf->rx_free_thresh;
244 [ # # ]: 0 : if (idpf_qc_rx_thresh_check(nb_desc, rx_free_thresh) != 0)
245 : : return -EINVAL;
246 : :
247 : : /* Free memory if needed */
248 [ # # ]: 0 : if (dev->data->rx_queues[queue_idx] != NULL) {
249 : 0 : idpf_qc_rx_queue_release(dev->data->rx_queues[queue_idx]);
250 : 0 : dev->data->rx_queues[queue_idx] = NULL;
251 : : }
252 : :
253 : : /* Setup Rx queue */
254 : 0 : rxq = rte_zmalloc_socket("idpf rxq",
255 : : sizeof(struct idpf_rx_queue),
256 : : RTE_CACHE_LINE_SIZE,
257 : : socket_id);
258 [ # # ]: 0 : if (rxq == NULL) {
259 : 0 : PMD_INIT_LOG(ERR, "Failed to allocate memory for rx queue data structure");
260 : : ret = -ENOMEM;
261 : 0 : goto err_rxq_alloc;
262 : : }
263 : :
264 : 0 : is_splitq = !!(vport->rxq_model == VIRTCHNL2_QUEUE_MODEL_SPLIT);
265 : :
266 : 0 : rxq->mp = mp;
267 : 0 : rxq->nb_rx_desc = nb_desc;
268 : 0 : rxq->rx_free_thresh = rx_free_thresh;
269 : 0 : rxq->queue_id = vport->chunks_info.rx_start_qid + queue_idx;
270 : 0 : rxq->port_id = dev->data->port_id;
271 : 0 : rxq->rx_deferred_start = rx_conf->rx_deferred_start;
272 : 0 : rxq->rx_hdr_len = 0;
273 : 0 : rxq->adapter = adapter;
274 [ # # ]: 0 : rxq->offloads = idpf_rx_offload_convert(offloads);
275 : :
276 : 0 : len = rte_pktmbuf_data_room_size(rxq->mp) - RTE_PKTMBUF_HEADROOM;
277 : 0 : rxq->rx_buf_len = RTE_ALIGN_FLOOR(len, (1 << IDPF_RLAN_CTX_DBUF_S));
278 : 0 : rxq->rx_buf_len = RTE_MIN(rxq->rx_buf_len, IDPF_RX_MAX_DATA_BUF_SIZE);
279 : :
280 : : /* Allocate a little more to support bulk allocate. */
281 : 0 : len = nb_desc + IDPF_RX_MAX_BURST;
282 : 0 : mz = idpf_dma_zone_reserve(dev, queue_idx, len, VIRTCHNL2_QUEUE_TYPE_RX,
283 : : socket_id, is_splitq);
284 [ # # ]: 0 : if (mz == NULL) {
285 : : ret = -ENOMEM;
286 : 0 : goto err_mz_reserve;
287 : : }
288 : 0 : rxq->rx_ring_phys_addr = mz->iova;
289 : 0 : rxq->rx_ring = mz->addr;
290 : 0 : rxq->mz = mz;
291 : :
292 [ # # ]: 0 : if (!is_splitq) {
293 : 0 : rxq->sw_ring = rte_zmalloc_socket("idpf rxq sw ring",
294 : : sizeof(struct rte_mbuf *) * len,
295 : : RTE_CACHE_LINE_SIZE,
296 : : socket_id);
297 [ # # ]: 0 : if (rxq->sw_ring == NULL) {
298 : 0 : PMD_INIT_LOG(ERR, "Failed to allocate memory for SW ring");
299 : : ret = -ENOMEM;
300 : 0 : goto err_sw_ring_alloc;
301 : : }
302 : :
303 : 0 : idpf_qc_single_rx_queue_reset(rxq);
304 : 0 : rxq->qrx_tail = hw->hw_addr + (vport->chunks_info.rx_qtail_start +
305 : 0 : queue_idx * vport->chunks_info.rx_qtail_spacing);
306 : 0 : rxq->idpf_ops = &def_rxq_ops;
307 : : } else {
308 : 0 : idpf_qc_split_rx_descq_reset(rxq);
309 : :
310 : : /* Setup Rx buffer queues */
311 : 0 : ret = idpf_rx_split_bufq_setup(dev, rxq, 2 * queue_idx,
312 : : rx_free_thresh, nb_desc,
313 : : socket_id, mp, 1);
314 [ # # ]: 0 : if (ret != 0) {
315 : 0 : PMD_INIT_LOG(ERR, "Failed to setup buffer queue 1");
316 : : ret = -EINVAL;
317 : 0 : goto err_bufq1_setup;
318 : : }
319 : :
320 : 0 : ret = idpf_rx_split_bufq_setup(dev, rxq, 2 * queue_idx + 1,
321 : : rx_free_thresh, nb_desc,
322 : : socket_id, mp, 2);
323 [ # # ]: 0 : if (ret != 0) {
324 : 0 : PMD_INIT_LOG(ERR, "Failed to setup buffer queue 2");
325 : : ret = -EINVAL;
326 : 0 : goto err_bufq2_setup;
327 : : }
328 : : }
329 : :
330 : 0 : rxq->q_set = true;
331 : 0 : dev->data->rx_queues[queue_idx] = rxq;
332 : :
333 : 0 : return 0;
334 : :
335 : : err_bufq2_setup:
336 : 0 : idpf_rx_split_bufq_release(rxq->bufq1);
337 : 0 : err_bufq1_setup:
338 : 0 : err_sw_ring_alloc:
339 : : idpf_dma_zone_release(mz);
340 : 0 : err_mz_reserve:
341 : 0 : rte_free(rxq);
342 : : err_rxq_alloc:
343 : : return ret;
344 : : }
345 : :
346 : : static int
347 : 0 : idpf_tx_complq_setup(struct rte_eth_dev *dev, struct ci_tx_queue *txq,
348 : : uint16_t queue_idx, uint16_t nb_desc,
349 : : unsigned int socket_id)
350 : : {
351 : 0 : struct idpf_vport *vport = dev->data->dev_private;
352 : : const struct rte_memzone *mz;
353 : : struct ci_tx_queue *cq;
354 : : int ret;
355 : :
356 : 0 : cq = rte_zmalloc_socket("idpf splitq cq",
357 : : sizeof(*cq),
358 : : RTE_CACHE_LINE_SIZE,
359 : : socket_id);
360 [ # # ]: 0 : if (cq == NULL) {
361 : 0 : PMD_INIT_LOG(ERR, "Failed to allocate memory for Tx compl queue");
362 : : ret = -ENOMEM;
363 : 0 : goto err_cq_alloc;
364 : : }
365 : :
366 : 0 : cq->nb_tx_desc = nb_desc;
367 : 0 : cq->queue_id = vport->chunks_info.tx_compl_start_qid + queue_idx;
368 : 0 : cq->port_id = dev->data->port_id;
369 : 0 : cq->txqs = dev->data->tx_queues;
370 : 0 : cq->tx_start_qid = vport->chunks_info.tx_start_qid;
371 : :
372 : 0 : mz = idpf_dma_zone_reserve(dev, queue_idx, nb_desc,
373 : : VIRTCHNL2_QUEUE_TYPE_TX_COMPLETION,
374 : : socket_id, true);
375 [ # # ]: 0 : if (mz == NULL) {
376 : : ret = -ENOMEM;
377 : 0 : goto err_mz_reserve;
378 : : }
379 : 0 : cq->tx_ring_dma = mz->iova;
380 : 0 : cq->compl_ring = mz->addr;
381 : 0 : cq->mz = mz;
382 : 0 : idpf_qc_split_tx_complq_reset(cq);
383 : :
384 : 0 : txq->complq = cq;
385 : :
386 : 0 : return 0;
387 : :
388 : : err_mz_reserve:
389 : 0 : rte_free(cq);
390 : : err_cq_alloc:
391 : : return ret;
392 : : }
393 : :
394 : : int
395 : 0 : idpf_tx_queue_setup(struct rte_eth_dev *dev, uint16_t queue_idx,
396 : : uint16_t nb_desc, unsigned int socket_id,
397 : : const struct rte_eth_txconf *tx_conf)
398 : : {
399 : 0 : struct idpf_vport *vport = dev->data->dev_private;
400 : 0 : struct idpf_adapter *adapter = vport->adapter;
401 : : uint16_t tx_rs_thresh, tx_free_thresh;
402 : : struct idpf_hw *hw = &adapter->hw;
403 : : const struct rte_memzone *mz;
404 : : struct ci_tx_queue *txq;
405 : : uint64_t offloads;
406 : : uint16_t len;
407 : : bool is_splitq;
408 : : int ret;
409 : :
410 : 0 : offloads = tx_conf->offloads | dev->data->dev_conf.txmode.offloads;
411 : :
412 [ # # ]: 0 : tx_rs_thresh = (uint16_t)((tx_conf->tx_rs_thresh > 0) ?
413 : : tx_conf->tx_rs_thresh : IDPF_DEFAULT_TX_RS_THRESH);
414 [ # # ]: 0 : tx_free_thresh = (uint16_t)((tx_conf->tx_free_thresh > 0) ?
415 : : tx_conf->tx_free_thresh : IDPF_DEFAULT_TX_FREE_THRESH);
416 [ # # ]: 0 : if (idpf_qc_tx_thresh_check(nb_desc, tx_rs_thresh, tx_free_thresh) != 0)
417 : : return -EINVAL;
418 : :
419 : : /* Free memory if needed. */
420 [ # # ]: 0 : if (dev->data->tx_queues[queue_idx] != NULL) {
421 : 0 : idpf_qc_tx_queue_release(dev->data->tx_queues[queue_idx]);
422 : 0 : dev->data->tx_queues[queue_idx] = NULL;
423 : : }
424 : :
425 : : /* Allocate the TX queue data structure. */
426 : 0 : txq = rte_zmalloc_socket("idpf txq",
427 : : sizeof(struct ci_tx_queue),
428 : : RTE_CACHE_LINE_SIZE,
429 : : socket_id);
430 [ # # ]: 0 : if (txq == NULL) {
431 : 0 : PMD_INIT_LOG(ERR, "Failed to allocate memory for tx queue structure");
432 : : ret = -ENOMEM;
433 : 0 : goto err_txq_alloc;
434 : : }
435 : :
436 : 0 : is_splitq = !!(vport->txq_model == VIRTCHNL2_QUEUE_MODEL_SPLIT);
437 : :
438 : 0 : txq->nb_tx_desc = nb_desc;
439 : 0 : txq->tx_rs_thresh = tx_rs_thresh;
440 : 0 : txq->tx_free_thresh = tx_free_thresh;
441 : 0 : txq->queue_id = vport->chunks_info.tx_start_qid + queue_idx;
442 : 0 : txq->port_id = dev->data->port_id;
443 : 0 : txq->offloads = idpf_tx_offload_convert(offloads);
444 : 0 : txq->tx_deferred_start = tx_conf->tx_deferred_start;
445 : :
446 [ # # ]: 0 : if (is_splitq)
447 : 0 : len = 2 * nb_desc;
448 : : else
449 : : len = nb_desc;
450 : 0 : txq->sw_nb_desc = len;
451 : :
452 : : /* Allocate TX hardware ring descriptors. */
453 : 0 : mz = idpf_dma_zone_reserve(dev, queue_idx, nb_desc, VIRTCHNL2_QUEUE_TYPE_TX,
454 : : socket_id, is_splitq);
455 [ # # ]: 0 : if (mz == NULL) {
456 : : ret = -ENOMEM;
457 : 0 : goto err_mz_reserve;
458 : : }
459 : 0 : txq->tx_ring_dma = mz->iova;
460 : 0 : txq->mz = mz;
461 : :
462 : 0 : txq->sw_ring = rte_zmalloc_socket("idpf tx sw ring",
463 : : sizeof(struct ci_tx_entry) * len,
464 : : RTE_CACHE_LINE_SIZE, socket_id);
465 [ # # ]: 0 : if (txq->sw_ring == NULL) {
466 : 0 : PMD_INIT_LOG(ERR, "Failed to allocate memory for SW TX ring");
467 : : ret = -ENOMEM;
468 : 0 : goto err_sw_ring_alloc;
469 : : }
470 : :
471 [ # # ]: 0 : if (!is_splitq) {
472 : 0 : txq->idpf_tx_ring = mz->addr;
473 : 0 : idpf_qc_single_tx_queue_reset(txq);
474 : : } else {
475 : 0 : txq->desc_ring = mz->addr;
476 : 0 : idpf_qc_split_tx_descq_reset(txq);
477 : :
478 : : /* Setup tx completion queue if split model */
479 : 0 : ret = idpf_tx_complq_setup(dev, txq, queue_idx,
480 : : 2 * nb_desc, socket_id);
481 [ # # ]: 0 : if (ret != 0)
482 : 0 : goto err_complq_setup;
483 : : }
484 : :
485 : 0 : txq->qtx_tail = hw->hw_addr + (vport->chunks_info.tx_qtail_start +
486 : 0 : queue_idx * vport->chunks_info.tx_qtail_spacing);
487 : 0 : txq->q_set = true;
488 : 0 : dev->data->tx_queues[queue_idx] = txq;
489 : :
490 : 0 : return 0;
491 : :
492 : : err_complq_setup:
493 : 0 : err_sw_ring_alloc:
494 : : idpf_dma_zone_release(mz);
495 : 0 : err_mz_reserve:
496 : 0 : rte_free(txq);
497 : : err_txq_alloc:
498 : : return ret;
499 : : }
500 : :
501 : : int
502 : 0 : idpf_rx_queue_init(struct rte_eth_dev *dev, uint16_t rx_queue_id)
503 : : {
504 : : struct idpf_rx_queue *rxq;
505 : : uint16_t max_pkt_len;
506 : : uint32_t frame_size;
507 : : int err;
508 : :
509 [ # # ]: 0 : if (rx_queue_id >= dev->data->nb_rx_queues)
510 : : return -EINVAL;
511 : :
512 : 0 : rxq = dev->data->rx_queues[rx_queue_id];
513 : :
514 [ # # # # ]: 0 : if (rxq == NULL || !rxq->q_set) {
515 : 0 : PMD_DRV_LOG(ERR, "RX queue %u not available or setup",
516 : : rx_queue_id);
517 : 0 : return -EINVAL;
518 : : }
519 : :
520 : 0 : frame_size = dev->data->mtu + IDPF_ETH_OVERHEAD;
521 : :
522 : 0 : max_pkt_len =
523 : 0 : RTE_MIN((uint32_t)IDPF_SUPPORT_CHAIN_NUM * rxq->rx_buf_len,
524 : : frame_size);
525 : :
526 : 0 : rxq->max_pkt_len = max_pkt_len;
527 [ # # # # ]: 0 : if ((dev->data->dev_conf.rxmode.offloads & RTE_ETH_RX_OFFLOAD_SCATTER) ||
528 : : frame_size > rxq->rx_buf_len)
529 : 0 : dev->data->scattered_rx = 1;
530 : :
531 : 0 : err = idpf_qc_ts_mbuf_register(rxq);
532 [ # # ]: 0 : if (err != 0) {
533 : 0 : PMD_DRV_LOG(ERR, "fail to residter timestamp mbuf %u",
534 : : rx_queue_id);
535 : 0 : return -EIO;
536 : : }
537 : :
538 [ # # ]: 0 : if (rxq->adapter->is_rx_singleq) {
539 : : /* Single queue */
540 : 0 : err = idpf_qc_single_rxq_mbufs_alloc(rxq);
541 [ # # ]: 0 : if (err != 0) {
542 : 0 : PMD_DRV_LOG(ERR, "Failed to allocate RX queue mbuf");
543 : 0 : return err;
544 : : }
545 : :
546 : : rte_wmb();
547 : :
548 : : /* Init the RX tail register. */
549 : 0 : IDPF_PCI_REG_WRITE(rxq->qrx_tail, rxq->nb_rx_desc - 1);
550 : : } else {
551 : : /* Split queue */
552 : 0 : err = idpf_qc_split_rxq_mbufs_alloc(rxq->bufq1);
553 [ # # ]: 0 : if (err != 0) {
554 : 0 : PMD_DRV_LOG(ERR, "Failed to allocate RX buffer queue mbuf");
555 : 0 : return err;
556 : : }
557 : 0 : err = idpf_qc_split_rxq_mbufs_alloc(rxq->bufq2);
558 [ # # ]: 0 : if (err != 0) {
559 : 0 : PMD_DRV_LOG(ERR, "Failed to allocate RX buffer queue mbuf");
560 : 0 : return err;
561 : : }
562 : :
563 : : rte_wmb();
564 : :
565 : : /* Init the RX tail register. */
566 : 0 : IDPF_PCI_REG_WRITE(rxq->bufq1->qrx_tail, rxq->bufq1->rx_tail);
567 : 0 : IDPF_PCI_REG_WRITE(rxq->bufq2->qrx_tail, rxq->bufq2->rx_tail);
568 : : }
569 : :
570 : : return err;
571 : : }
572 : :
573 : : int
574 : 0 : idpf_rx_queue_start(struct rte_eth_dev *dev, uint16_t rx_queue_id)
575 : : {
576 : 0 : struct idpf_vport *vport = dev->data->dev_private;
577 : 0 : struct idpf_rx_queue *rxq =
578 : 0 : dev->data->rx_queues[rx_queue_id];
579 : : int err = 0;
580 : :
581 : 0 : err = idpf_vc_rxq_config(vport, rxq);
582 [ # # ]: 0 : if (err != 0) {
583 : 0 : PMD_DRV_LOG(ERR, "Fail to configure Rx queue %u", rx_queue_id);
584 : 0 : return err;
585 : : }
586 : :
587 : 0 : err = idpf_rx_queue_init(dev, rx_queue_id);
588 [ # # ]: 0 : if (err != 0) {
589 : 0 : PMD_DRV_LOG(ERR, "Failed to init RX queue %u",
590 : : rx_queue_id);
591 : 0 : return err;
592 : : }
593 : :
594 : : /* Ready to switch the queue on */
595 : 0 : err = idpf_vc_queue_switch(vport, rx_queue_id, true, true,
596 : : VIRTCHNL2_QUEUE_TYPE_RX);
597 [ # # ]: 0 : if (err != 0) {
598 : 0 : PMD_DRV_LOG(ERR, "Failed to switch RX queue %u on",
599 : : rx_queue_id);
600 : : } else {
601 : 0 : rxq->q_started = true;
602 : 0 : dev->data->rx_queue_state[rx_queue_id] =
603 : : RTE_ETH_QUEUE_STATE_STARTED;
604 : : }
605 : :
606 : : return err;
607 : : }
608 : :
609 : : int
610 : 0 : idpf_tx_queue_init(struct rte_eth_dev *dev, uint16_t tx_queue_id)
611 : : {
612 : : struct ci_tx_queue *txq;
613 : :
614 [ # # ]: 0 : if (tx_queue_id >= dev->data->nb_tx_queues)
615 : : return -EINVAL;
616 : :
617 : 0 : txq = dev->data->tx_queues[tx_queue_id];
618 : :
619 : : /* Init the RX tail register. */
620 : 0 : IDPF_PCI_REG_WRITE(txq->qtx_tail, 0);
621 : :
622 : 0 : return 0;
623 : : }
624 : :
625 : : int
626 : 0 : idpf_tx_queue_start(struct rte_eth_dev *dev, uint16_t tx_queue_id)
627 : : {
628 : 0 : struct idpf_vport *vport = dev->data->dev_private;
629 : 0 : struct ci_tx_queue *txq = dev->data->tx_queues[tx_queue_id];
630 : : int err = 0;
631 : :
632 : 0 : err = idpf_vc_txq_config(vport, txq);
633 [ # # ]: 0 : if (err != 0) {
634 : 0 : PMD_DRV_LOG(ERR, "Fail to configure Tx queue %u", tx_queue_id);
635 : 0 : return err;
636 : : }
637 : :
638 : 0 : err = idpf_tx_queue_init(dev, tx_queue_id);
639 [ # # ]: 0 : if (err != 0) {
640 : 0 : PMD_DRV_LOG(ERR, "Failed to init TX queue %u",
641 : : tx_queue_id);
642 : 0 : return err;
643 : : }
644 : :
645 : : /* Ready to switch the queue on */
646 : 0 : err = idpf_vc_queue_switch(vport, tx_queue_id, false, true,
647 : : VIRTCHNL2_QUEUE_TYPE_TX);
648 [ # # ]: 0 : if (err != 0) {
649 : 0 : PMD_DRV_LOG(ERR, "Failed to switch TX queue %u on",
650 : : tx_queue_id);
651 : : } else {
652 : 0 : dev->data->tx_queue_state[tx_queue_id] =
653 : : RTE_ETH_QUEUE_STATE_STARTED;
654 : : }
655 : :
656 : : return err;
657 : : }
658 : :
659 : : int
660 : 0 : idpf_rx_queue_stop(struct rte_eth_dev *dev, uint16_t rx_queue_id)
661 : : {
662 : 0 : struct idpf_vport *vport = dev->data->dev_private;
663 : : struct idpf_rx_queue *rxq;
664 : : int err;
665 : :
666 [ # # ]: 0 : if (rx_queue_id >= dev->data->nb_rx_queues)
667 : : return -EINVAL;
668 : :
669 : 0 : err = idpf_vc_queue_switch(vport, rx_queue_id, true, false,
670 : : VIRTCHNL2_QUEUE_TYPE_RX);
671 [ # # ]: 0 : if (err != 0) {
672 : 0 : PMD_DRV_LOG(ERR, "Failed to switch RX queue %u off",
673 : : rx_queue_id);
674 : 0 : return err;
675 : : }
676 : :
677 : 0 : rxq = dev->data->rx_queues[rx_queue_id];
678 : 0 : rxq->q_started = false;
679 [ # # ]: 0 : if (vport->rxq_model == VIRTCHNL2_QUEUE_MODEL_SINGLE) {
680 : 0 : rxq->idpf_ops->release_mbufs(rxq);
681 : 0 : idpf_qc_single_rx_queue_reset(rxq);
682 : : } else {
683 : 0 : rxq->bufq1->idpf_ops->release_mbufs(rxq->bufq1);
684 : 0 : rxq->bufq2->idpf_ops->release_mbufs(rxq->bufq2);
685 : 0 : idpf_qc_split_rx_queue_reset(rxq);
686 : : }
687 : 0 : dev->data->rx_queue_state[rx_queue_id] = RTE_ETH_QUEUE_STATE_STOPPED;
688 : :
689 : 0 : return 0;
690 : : }
691 : :
692 : : int
693 : 0 : idpf_tx_queue_stop(struct rte_eth_dev *dev, uint16_t tx_queue_id)
694 : : {
695 : 0 : struct idpf_vport *vport = dev->data->dev_private;
696 : : struct ci_tx_queue *txq;
697 : : int err;
698 : :
699 [ # # ]: 0 : if (tx_queue_id >= dev->data->nb_tx_queues)
700 : : return -EINVAL;
701 : :
702 : 0 : err = idpf_vc_queue_switch(vport, tx_queue_id, false, false,
703 : : VIRTCHNL2_QUEUE_TYPE_TX);
704 [ # # ]: 0 : if (err != 0) {
705 : 0 : PMD_DRV_LOG(ERR, "Failed to switch TX queue %u off",
706 : : tx_queue_id);
707 : 0 : return err;
708 : : }
709 : :
710 : 0 : txq = dev->data->tx_queues[tx_queue_id];
711 : 0 : ci_txq_release_all_mbufs(txq, false);
712 [ # # ]: 0 : if (vport->txq_model == VIRTCHNL2_QUEUE_MODEL_SINGLE) {
713 : 0 : idpf_qc_single_tx_queue_reset(txq);
714 : : } else {
715 : 0 : idpf_qc_split_tx_descq_reset(txq);
716 : 0 : idpf_qc_split_tx_complq_reset(txq->complq);
717 : : }
718 : 0 : dev->data->tx_queue_state[tx_queue_id] = RTE_ETH_QUEUE_STATE_STOPPED;
719 : :
720 : 0 : return 0;
721 : : }
722 : :
723 : : void
724 : 0 : idpf_dev_rx_queue_release(struct rte_eth_dev *dev, uint16_t qid)
725 : : {
726 : 0 : idpf_qc_rx_queue_release(dev->data->rx_queues[qid]);
727 : 0 : }
728 : :
729 : : void
730 : 0 : idpf_dev_tx_queue_release(struct rte_eth_dev *dev, uint16_t qid)
731 : : {
732 : 0 : idpf_qc_tx_queue_release(dev->data->tx_queues[qid]);
733 : 0 : }
734 : :
735 : : void
736 : 0 : idpf_stop_queues(struct rte_eth_dev *dev)
737 : : {
738 : : struct idpf_rx_queue *rxq;
739 : : struct ci_tx_queue *txq;
740 : : int i;
741 : :
742 [ # # ]: 0 : for (i = 0; i < dev->data->nb_rx_queues; i++) {
743 : 0 : rxq = dev->data->rx_queues[i];
744 [ # # ]: 0 : if (rxq == NULL)
745 : 0 : continue;
746 : :
747 [ # # ]: 0 : if (idpf_rx_queue_stop(dev, i) != 0)
748 : 0 : PMD_DRV_LOG(WARNING, "Fail to stop Rx queue %d", i);
749 : : }
750 : :
751 [ # # ]: 0 : for (i = 0; i < dev->data->nb_tx_queues; i++) {
752 : 0 : txq = dev->data->tx_queues[i];
753 [ # # ]: 0 : if (txq == NULL)
754 : 0 : continue;
755 : :
756 [ # # ]: 0 : if (idpf_tx_queue_stop(dev, i) != 0)
757 : 0 : PMD_DRV_LOG(WARNING, "Fail to stop Tx queue %d", i);
758 : : }
759 : 0 : }
760 : :
761 : : void
762 : 0 : idpf_set_rx_function(struct rte_eth_dev *dev)
763 : : {
764 : 0 : struct idpf_vport *vport = dev->data->dev_private;
765 : 0 : struct idpf_adapter *ad = vport->adapter;
766 : 0 : struct ci_rx_path_features req_features = {
767 : 0 : .rx_offloads = dev->data->dev_conf.rxmode.offloads,
768 : : .simd_width = RTE_VECT_SIMD_DISABLED,
769 : : };
770 : : #ifdef RTE_ARCH_X86
771 : : struct idpf_rx_queue *rxq;
772 : : int i;
773 : :
774 [ # # # # ]: 0 : if (idpf_rx_vec_dev_check_default(dev) == IDPF_VECTOR_PATH &&
775 : 0 : rte_vect_get_max_simd_bitwidth() >= RTE_VECT_SIMD_256)
776 : 0 : req_features.simd_width = idpf_get_max_simd_bitwidth();
777 : : #endif /* RTE_ARCH_X86 */
778 : :
779 : 0 : req_features.extra.single_queue = (vport->rxq_model == VIRTCHNL2_QUEUE_MODEL_SINGLE);
780 : 0 : req_features.extra.scattered = dev->data->scattered_rx;
781 : :
782 : 0 : ad->rx_func_type = ci_rx_path_select(req_features,
783 : : &idpf_rx_path_infos[0],
784 : : IDPF_RX_MAX,
785 : : IDPF_RX_DEFAULT);
786 : :
787 : : #ifdef RTE_ARCH_X86
788 [ # # ]: 0 : if (idpf_rx_path_infos[ad->rx_func_type].features.simd_width >= RTE_VECT_SIMD_256) {
789 : : /* Vector function selected. Prepare the rxq accordingly. */
790 [ # # ]: 0 : if (idpf_rx_path_infos[ad->rx_func_type].features.extra.single_queue) {
791 [ # # ]: 0 : for (i = 0; i < dev->data->nb_rx_queues; i++) {
792 : 0 : rxq = dev->data->rx_queues[i];
793 : 0 : (void)idpf_qc_singleq_rx_vec_setup(rxq);
794 : : }
795 : : } else {
796 [ # # ]: 0 : for (i = 0; i < dev->data->nb_rx_queues; i++) {
797 : 0 : rxq = dev->data->rx_queues[i];
798 : 0 : (void)idpf_qc_splitq_rx_vec_setup(rxq);
799 : : }
800 : : }
801 : :
802 : : }
803 : : #endif
804 : :
805 : 0 : dev->rx_pkt_burst = idpf_rx_path_infos[ad->rx_func_type].pkt_burst;
806 : 0 : PMD_DRV_LOG(NOTICE, "Using %s Rx (port %d).",
807 : : idpf_rx_path_infos[ad->rx_func_type].info, dev->data->port_id);
808 : :
809 : 0 : }
810 : :
811 : : void
812 : 0 : idpf_set_tx_function(struct rte_eth_dev *dev)
813 : : {
814 : 0 : struct idpf_vport *vport = dev->data->dev_private;
815 : : #ifdef RTE_ARCH_X86
816 : : enum rte_vect_max_simd tx_simd_width = RTE_VECT_SIMD_DISABLED;
817 : : #ifdef CC_AVX512_SUPPORT
818 : : struct ci_tx_queue *txq;
819 : : int i;
820 : : #endif /* CC_AVX512_SUPPORT */
821 : :
822 [ # # # # ]: 0 : if (idpf_tx_vec_dev_check_default(dev) == IDPF_VECTOR_PATH &&
823 : 0 : rte_vect_get_max_simd_bitwidth() >= RTE_VECT_SIMD_128) {
824 : 0 : vport->tx_vec_allowed = true;
825 : : tx_simd_width = idpf_get_max_simd_bitwidth();
826 : : #ifdef CC_AVX512_SUPPORT
827 [ # # ]: 0 : if (tx_simd_width == RTE_VECT_SIMD_512) {
828 [ # # ]: 0 : for (i = 0; i < dev->data->nb_tx_queues; i++) {
829 : 0 : txq = dev->data->tx_queues[i];
830 : 0 : idpf_qc_tx_vec_avx512_setup(txq);
831 : : }
832 : : }
833 : : #else
834 : : PMD_DRV_LOG(NOTICE,
835 : : "AVX512 is not supported in build env");
836 : : #endif /* CC_AVX512_SUPPORT */
837 : : } else {
838 : 0 : vport->tx_vec_allowed = false;
839 : : }
840 : : #endif /* RTE_ARCH_X86 */
841 : :
842 : : #ifdef RTE_ARCH_X86
843 [ # # ]: 0 : if (vport->txq_model == VIRTCHNL2_QUEUE_MODEL_SPLIT) {
844 [ # # ]: 0 : if (vport->tx_vec_allowed) {
845 : : #ifdef CC_AVX512_SUPPORT
846 [ # # ]: 0 : if (tx_simd_width == RTE_VECT_SIMD_512) {
847 : 0 : PMD_DRV_LOG(NOTICE,
848 : : "Using Split AVX512 Vector Tx (port %d).",
849 : : dev->data->port_id);
850 : 0 : dev->tx_pkt_burst = idpf_dp_splitq_xmit_pkts_avx512;
851 : 0 : dev->tx_pkt_prepare = idpf_dp_prep_pkts;
852 : 0 : return;
853 : : }
854 : : #endif /* CC_AVX512_SUPPORT */
855 : : }
856 : 0 : PMD_DRV_LOG(NOTICE,
857 : : "Using Split Scalar Tx (port %d).",
858 : : dev->data->port_id);
859 : 0 : dev->tx_pkt_burst = idpf_dp_splitq_xmit_pkts;
860 : 0 : dev->tx_pkt_prepare = idpf_dp_prep_pkts;
861 : : } else {
862 [ # # ]: 0 : if (vport->tx_vec_allowed) {
863 : : #ifdef CC_AVX512_SUPPORT
864 [ # # ]: 0 : if (tx_simd_width == RTE_VECT_SIMD_512) {
865 [ # # ]: 0 : for (i = 0; i < dev->data->nb_tx_queues; i++) {
866 : 0 : txq = dev->data->tx_queues[i];
867 [ # # ]: 0 : if (txq == NULL)
868 : 0 : continue;
869 : 0 : idpf_qc_tx_vec_avx512_setup(txq);
870 : : }
871 : 0 : PMD_DRV_LOG(NOTICE,
872 : : "Using Single AVX512 Vector Tx (port %d).",
873 : : dev->data->port_id);
874 : 0 : dev->tx_pkt_burst = idpf_dp_singleq_xmit_pkts_avx512;
875 : 0 : dev->tx_pkt_prepare = idpf_dp_prep_pkts;
876 : 0 : return;
877 : : }
878 : : #endif /* CC_AVX512_SUPPORT */
879 [ # # ]: 0 : if (tx_simd_width == RTE_VECT_SIMD_256) {
880 : 0 : PMD_DRV_LOG(NOTICE,
881 : : "Using Single AVX2 Vector Tx (port %d).",
882 : : dev->data->port_id);
883 : 0 : dev->tx_pkt_burst = idpf_dp_singleq_xmit_pkts_avx2;
884 : 0 : dev->tx_pkt_prepare = idpf_dp_prep_pkts;
885 : 0 : return;
886 : : }
887 : : }
888 : 0 : PMD_DRV_LOG(NOTICE,
889 : : "Using Single Scalar Tx (port %d).",
890 : : dev->data->port_id);
891 : 0 : dev->tx_pkt_burst = idpf_dp_singleq_xmit_pkts;
892 : 0 : dev->tx_pkt_prepare = idpf_dp_prep_pkts;
893 : : }
894 : : #else
895 : : if (vport->txq_model == VIRTCHNL2_QUEUE_MODEL_SPLIT) {
896 : : PMD_DRV_LOG(NOTICE,
897 : : "Using Split Scalar Tx (port %d).",
898 : : dev->data->port_id);
899 : : dev->tx_pkt_burst = idpf_dp_splitq_xmit_pkts;
900 : : dev->tx_pkt_prepare = idpf_dp_prep_pkts;
901 : : } else {
902 : : PMD_DRV_LOG(NOTICE,
903 : : "Using Single Scalar Tx (port %d).",
904 : : dev->data->port_id);
905 : : dev->tx_pkt_burst = idpf_dp_singleq_xmit_pkts;
906 : : dev->tx_pkt_prepare = idpf_dp_prep_pkts;
907 : : }
908 : : #endif /* RTE_ARCH_X86 */
909 : : }
|