Branch data Line data Source code
1 : : /* SPDX-License-Identifier: BSD-3-Clause
2 : : * Copyright(c) 2018 Intel Corporation.
3 : : */
4 : : #include <rte_spinlock.h>
5 : : #include <rte_service_component.h>
6 : : #include <ethdev_driver.h>
7 : :
8 : : #include "eventdev_pmd.h"
9 : : #include "eventdev_trace.h"
10 : : #include "rte_event_eth_tx_adapter.h"
11 : :
12 : : #define TXA_BATCH_SIZE 32
13 : : #define TXA_SERVICE_NAME_LEN 32
14 : : #define TXA_MEM_NAME_LEN 32
15 : : #define TXA_FLUSH_THRESHOLD 1024
16 : : #define TXA_RETRY_CNT 100
17 : : #define TXA_MAX_NB_TX 128
18 : : #define TXA_INVALID_DEV_ID INT32_C(-1)
19 : : #define TXA_INVALID_SERVICE_ID INT64_C(-1)
20 : :
21 : : #define TXA_ADAPTER_ARRAY "txa_adapter_array"
22 : : #define TXA_SERVICE_DATA_ARRAY "txa_service_data_array"
23 : :
24 : : #define txa_evdev(id) (&rte_eventdevs[txa_dev_id_array[(id)]])
25 : :
26 : : #define txa_dev_caps_get(id) txa_evdev((id))->dev_ops->eth_tx_adapter_caps_get
27 : :
28 : : #define txa_dev_adapter_create(t) txa_evdev(t)->dev_ops->eth_tx_adapter_create
29 : :
30 : : #define txa_dev_adapter_create_ext(t) \
31 : : txa_evdev(t)->dev_ops->eth_tx_adapter_create
32 : :
33 : : #define txa_dev_adapter_free(t) txa_evdev(t)->dev_ops->eth_tx_adapter_free
34 : :
35 : : #define txa_dev_queue_add(id) txa_evdev(id)->dev_ops->eth_tx_adapter_queue_add
36 : :
37 : : #define txa_dev_queue_del(t) txa_evdev(t)->dev_ops->eth_tx_adapter_queue_del
38 : :
39 : : #define txa_dev_start(t) txa_evdev(t)->dev_ops->eth_tx_adapter_start
40 : :
41 : : #define txa_dev_stop(t) txa_evdev(t)->dev_ops->eth_tx_adapter_stop
42 : :
43 : : #define txa_dev_stats_reset(t) txa_evdev(t)->dev_ops->eth_tx_adapter_stats_reset
44 : :
45 : : #define txa_dev_stats_get(t) txa_evdev(t)->dev_ops->eth_tx_adapter_stats_get
46 : :
47 : : #define txa_dev_instance_get(id) \
48 : : txa_evdev(id)->dev_ops->eth_tx_adapter_instance_get
49 : :
50 : : #define txa_dev_queue_start(id) \
51 : : txa_evdev(id)->dev_ops->eth_tx_adapter_queue_start
52 : :
53 : : #define txa_dev_queue_stop(id) \
54 : : txa_evdev(id)->dev_ops->eth_tx_adapter_queue_stop
55 : :
56 : : #define RTE_EVENT_ETH_TX_ADAPTER_ID_VALID_OR_ERR_RET(id, retval) \
57 : : do { \
58 : : if (!txa_valid_id(id)) { \
59 : : RTE_EDEV_LOG_ERR("Invalid eth Tx adapter id = %d", id); \
60 : : return retval; \
61 : : } \
62 : : } while (0)
63 : :
64 : : #define TXA_CHECK_OR_ERR_RET(id) \
65 : : do {\
66 : : int ret; \
67 : : RTE_EVENT_ETH_TX_ADAPTER_ID_VALID_OR_ERR_RET((id), -EINVAL); \
68 : : ret = txa_init(); \
69 : : if (ret != 0) \
70 : : return ret; \
71 : : if (!txa_adapter_exist((id))) \
72 : : return -EINVAL; \
73 : : } while (0)
74 : :
75 : : #define TXA_CHECK_TXQ(dev, queue) \
76 : : do {\
77 : : if ((dev)->data->nb_tx_queues == 0) { \
78 : : RTE_EDEV_LOG_ERR("No tx queues configured"); \
79 : : return -EINVAL; \
80 : : } \
81 : : if ((queue) != -1 && \
82 : : (uint16_t)(queue) >= (dev)->data->nb_tx_queues) { \
83 : : RTE_EDEV_LOG_ERR("Invalid tx queue_id %" PRIu16, \
84 : : (uint16_t)(queue)); \
85 : : return -EINVAL; \
86 : : } \
87 : : } while (0)
88 : :
89 : : /* Tx retry callback structure */
90 : : struct txa_retry {
91 : : /* Ethernet port id */
92 : : uint16_t port_id;
93 : : /* Tx queue */
94 : : uint16_t tx_queue;
95 : : /* Adapter ID */
96 : : uint8_t id;
97 : : };
98 : :
99 : : /* Per queue structure */
100 : : struct txa_service_queue_info {
101 : : /* Queue has been added */
102 : : uint8_t added;
103 : : /* Queue is stopped */
104 : : bool stopped;
105 : : /* Retry callback argument */
106 : : struct txa_retry txa_retry;
107 : : /* Tx buffer */
108 : : struct rte_eth_dev_tx_buffer *tx_buf;
109 : : };
110 : :
111 : : /* PMD private structure */
112 : : struct __rte_cache_aligned txa_service_data {
113 : : /* Max mbufs processed in any service function invocation */
114 : : uint32_t max_nb_tx;
115 : : /* Number of Tx queues in adapter */
116 : : uint32_t nb_queues;
117 : : /* Synchronization with data path */
118 : : rte_spinlock_t tx_lock;
119 : : /* Event port ID */
120 : : uint8_t port_id;
121 : : /* Event device identifier */
122 : : uint8_t eventdev_id;
123 : : /* Highest port id supported + 1 */
124 : : uint16_t dev_count;
125 : : /* Loop count to flush Tx buffers */
126 : : int loop_cnt;
127 : : /* Loop count threshold to flush Tx buffers */
128 : : uint16_t flush_threshold;
129 : : /* Per ethernet device structure */
130 : : struct txa_service_ethdev *txa_ethdev;
131 : : /* Statistics */
132 : : struct rte_event_eth_tx_adapter_stats stats;
133 : : /* Adapter Identifier */
134 : : uint8_t id;
135 : : /* Conf arg must be freed */
136 : : uint8_t conf_free;
137 : : /* Configuration callback */
138 : : rte_event_eth_tx_adapter_conf_cb conf_cb;
139 : : /* Configuration callback argument */
140 : : void *conf_arg;
141 : : /* socket id */
142 : : int socket_id;
143 : : /* Per adapter EAL service */
144 : : int64_t service_id;
145 : : /* Memory allocation name */
146 : : char mem_name[TXA_MEM_NAME_LEN];
147 : : };
148 : :
149 : : /* Per eth device structure */
150 : : struct txa_service_ethdev {
151 : : /* Pointer to ethernet device */
152 : : struct rte_eth_dev *dev;
153 : : /* Number of queues added */
154 : : uint16_t nb_queues;
155 : : /* PMD specific queue data */
156 : : void *queues;
157 : : };
158 : :
159 : : /* Array of adapter instances, initialized with event device id
160 : : * when adapter is created
161 : : */
162 : : static int *txa_dev_id_array;
163 : :
164 : : /* Array of pointers to service implementation data */
165 : : static struct txa_service_data **txa_service_data_array;
166 : :
167 : : static int32_t txa_service_func(void *args);
168 : : static int txa_service_adapter_create_ext(uint8_t id,
169 : : struct rte_eventdev *dev,
170 : : rte_event_eth_tx_adapter_conf_cb conf_cb,
171 : : void *conf_arg);
172 : : static int txa_service_queue_del(uint8_t id,
173 : : const struct rte_eth_dev *dev,
174 : : int32_t tx_queue_id);
175 : :
176 : : static int
177 : : txa_adapter_exist(uint8_t id)
178 : : {
179 : 70 : return txa_dev_id_array[id] != TXA_INVALID_DEV_ID;
180 : : }
181 : :
182 : : static inline int
183 : : txa_valid_id(uint8_t id)
184 : : {
185 : : return id < RTE_EVENT_ETH_TX_ADAPTER_MAX_INSTANCE;
186 : : }
187 : :
188 : : static void *
189 : 2 : txa_memzone_array_get(const char *name, unsigned int elt_size, int nb_elems)
190 : : {
191 : : const struct rte_memzone *mz;
192 : : unsigned int sz;
193 : :
194 : 2 : sz = elt_size * nb_elems;
195 : 2 : sz = RTE_ALIGN(sz, RTE_CACHE_LINE_SIZE);
196 : :
197 : 2 : mz = rte_memzone_lookup(name);
198 [ + - ]: 2 : if (mz == NULL) {
199 : 2 : mz = rte_memzone_reserve_aligned(name, sz, rte_socket_id(), 0,
200 : : RTE_CACHE_LINE_SIZE);
201 [ - + ]: 2 : if (mz == NULL) {
202 : 0 : RTE_EDEV_LOG_ERR("failed to reserve memzone"
203 : : " name = %s err = %"
204 : : PRId32, name, rte_errno);
205 : 0 : return NULL;
206 : : }
207 : : }
208 : :
209 : 2 : return mz->addr;
210 : : }
211 : :
212 : : static int
213 : 31 : txa_lookup(void)
214 : : {
215 : : const struct rte_memzone *mz;
216 : :
217 [ - + ]: 31 : if (txa_dev_id_array == NULL) {
218 : 0 : mz = rte_memzone_lookup(TXA_ADAPTER_ARRAY);
219 [ # # ]: 0 : if (mz == NULL)
220 : : return -ENOMEM;
221 : 0 : txa_dev_id_array = mz->addr;
222 : : }
223 : :
224 [ - + ]: 31 : if (txa_service_data_array == NULL) {
225 : 0 : mz = rte_memzone_lookup(TXA_SERVICE_DATA_ARRAY);
226 [ # # ]: 0 : if (mz == NULL)
227 : : return -ENOMEM;
228 : 0 : txa_service_data_array = mz->addr;
229 : : }
230 : :
231 : : return 0;
232 : : }
233 : :
234 : : static int
235 : 70 : txa_dev_id_array_init(void)
236 : : {
237 [ + + ]: 70 : if (txa_dev_id_array == NULL) {
238 : : int i;
239 : :
240 : 1 : txa_dev_id_array = txa_memzone_array_get(TXA_ADAPTER_ARRAY,
241 : : sizeof(int),
242 : : RTE_EVENT_ETH_TX_ADAPTER_MAX_INSTANCE);
243 [ + - ]: 1 : if (txa_dev_id_array == NULL)
244 : : return -ENOMEM;
245 : :
246 [ + + ]: 33 : for (i = 0; i < RTE_EVENT_ETH_TX_ADAPTER_MAX_INSTANCE; i++)
247 : 32 : txa_dev_id_array[i] = TXA_INVALID_DEV_ID;
248 : : }
249 : :
250 : : return 0;
251 : : }
252 : :
253 : : static int
254 : : txa_init(void)
255 : : {
256 : 70 : return txa_dev_id_array_init();
257 : : }
258 : :
259 : : static int
260 : 8 : txa_service_data_init(void)
261 : : {
262 [ + + ]: 8 : if (txa_service_data_array == NULL) {
263 : : int i;
264 : :
265 : 1 : txa_service_data_array =
266 : 1 : txa_memzone_array_get(TXA_SERVICE_DATA_ARRAY,
267 : : sizeof(*txa_service_data_array),
268 : : RTE_EVENT_ETH_TX_ADAPTER_MAX_INSTANCE);
269 [ + - ]: 1 : if (txa_service_data_array == NULL)
270 : : return -ENOMEM;
271 : :
272 : : /* Reset the txa service pointers */
273 [ + + ]: 33 : for (i = 0; i < RTE_EVENT_ETH_TX_ADAPTER_MAX_INSTANCE; i++)
274 : 32 : txa_service_data_array[i] = NULL;
275 : : }
276 : :
277 : : return 0;
278 : : }
279 : :
280 : : static inline struct txa_service_data *
281 : : txa_service_id_to_data(uint8_t id)
282 : : {
283 : 362 : return txa_service_data_array[id];
284 : : }
285 : :
286 : : static inline struct txa_service_queue_info *
287 : : txa_service_queue(struct txa_service_data *txa, uint16_t port_id,
288 : : uint16_t tx_queue_id)
289 : : {
290 : : struct txa_service_queue_info *tqi;
291 : :
292 [ + - + - : 69845 : if (unlikely(txa->txa_ethdev == NULL || txa->dev_count < port_id + 1))
+ - + - +
- + + + -
+ - + - -
- - - ]
293 : : return NULL;
294 : :
295 : 69844 : tqi = txa->txa_ethdev[port_id].queues;
296 : :
297 [ + - + - : 69844 : return likely(tqi != NULL) ? tqi + tx_queue_id : NULL;
+ - + - +
- + - + -
+ - - - -
- ]
298 : : }
299 : :
300 : : static int
301 : 7 : txa_service_conf_cb(uint8_t __rte_unused id, uint8_t dev_id,
302 : : struct rte_event_eth_tx_adapter_conf *conf, void *arg)
303 : : {
304 : : int ret;
305 : : struct rte_eventdev *dev;
306 : : struct rte_event_port_conf *pc;
307 : : struct rte_event_dev_config dev_conf;
308 : : int started;
309 : : uint8_t port_id;
310 : :
311 : : pc = arg;
312 : 7 : dev = &rte_eventdevs[dev_id];
313 : 7 : dev_conf = dev->data->dev_conf;
314 : :
315 : 7 : started = dev->data->dev_started;
316 [ - + ]: 7 : if (started)
317 : 0 : rte_event_dev_stop(dev_id);
318 : :
319 : 7 : port_id = dev_conf.nb_event_ports;
320 : 7 : dev_conf.nb_event_ports += 1;
321 [ - + ]: 7 : if (pc->event_port_cfg & RTE_EVENT_PORT_CFG_SINGLE_LINK)
322 : 0 : dev_conf.nb_single_link_event_port_queues += 1;
323 : :
324 : 7 : ret = rte_event_dev_configure(dev_id, &dev_conf);
325 [ - + ]: 7 : if (ret) {
326 : 0 : RTE_EDEV_LOG_ERR("failed to configure event dev %u",
327 : : dev_id);
328 [ # # ]: 0 : if (started) {
329 [ # # ]: 0 : if (rte_event_dev_start(dev_id))
330 : : return -EIO;
331 : : }
332 : 0 : return ret;
333 : : }
334 : :
335 : 7 : ret = rte_event_port_setup(dev_id, port_id, pc);
336 [ - + ]: 7 : if (ret) {
337 : 0 : RTE_EDEV_LOG_ERR("failed to setup event port %u",
338 : : port_id);
339 [ # # ]: 0 : if (started) {
340 [ # # ]: 0 : if (rte_event_dev_start(dev_id))
341 : : return -EIO;
342 : : }
343 : 0 : return ret;
344 : : }
345 : :
346 : 7 : conf->event_port_id = port_id;
347 : 7 : conf->max_nb_tx = TXA_MAX_NB_TX;
348 [ - + ]: 7 : if (started)
349 : 0 : ret = rte_event_dev_start(dev_id);
350 : : return ret;
351 : : }
352 : :
353 : : static int
354 : 54 : txa_service_ethdev_alloc(struct txa_service_data *txa)
355 : : {
356 : : struct txa_service_ethdev *txa_ethdev;
357 : : uint16_t i, dev_count;
358 : :
359 : 54 : dev_count = rte_eth_dev_count_avail();
360 [ + + + + ]: 54 : if (txa->txa_ethdev && dev_count == txa->dev_count)
361 : : return 0;
362 : :
363 : 8 : txa_ethdev = rte_zmalloc_socket(txa->mem_name,
364 : : dev_count * sizeof(*txa_ethdev),
365 : : 0,
366 : : txa->socket_id);
367 [ - + ]: 8 : if (txa_ethdev == NULL) {
368 : 0 : RTE_EDEV_LOG_ERR("Failed to alloc txa::txa_ethdev ");
369 : 0 : return -ENOMEM;
370 : : }
371 : :
372 [ + + ]: 8 : if (txa->dev_count)
373 : 1 : memcpy(txa_ethdev, txa->txa_ethdev,
374 : 1 : txa->dev_count * sizeof(*txa_ethdev));
375 : :
376 [ + + ]: 27 : RTE_ETH_FOREACH_DEV(i) {
377 [ + - ]: 19 : if (i == dev_count)
378 : : break;
379 : 19 : txa_ethdev[i].dev = &rte_eth_devices[i];
380 : : }
381 : :
382 : 8 : txa->txa_ethdev = txa_ethdev;
383 : 8 : txa->dev_count = dev_count;
384 : 8 : return 0;
385 : : }
386 : :
387 : : static int
388 : 54 : txa_service_queue_array_alloc(struct txa_service_data *txa,
389 : : uint16_t port_id)
390 : : {
391 : : struct txa_service_queue_info *tqi;
392 : : uint16_t nb_queue;
393 : : int ret;
394 : :
395 : 54 : ret = txa_service_ethdev_alloc(txa);
396 [ + - ]: 54 : if (ret != 0)
397 : : return ret;
398 : :
399 [ + + ]: 54 : if (txa->txa_ethdev[port_id].queues)
400 : : return 0;
401 : :
402 : 8 : nb_queue = txa->txa_ethdev[port_id].dev->data->nb_tx_queues;
403 : 8 : tqi = rte_zmalloc_socket(txa->mem_name,
404 : : nb_queue *
405 : : sizeof(struct txa_service_queue_info), 0,
406 : : txa->socket_id);
407 [ + - ]: 8 : if (tqi == NULL)
408 : : return -ENOMEM;
409 : 8 : txa->txa_ethdev[port_id].queues = tqi;
410 : 8 : return 0;
411 : : }
412 : :
413 : : static void
414 : 54 : txa_service_queue_array_free(struct txa_service_data *txa,
415 : : uint16_t port_id)
416 : : {
417 : : struct txa_service_ethdev *txa_ethdev;
418 : : struct txa_service_queue_info *tqi;
419 : :
420 : 54 : txa_ethdev = &txa->txa_ethdev[port_id];
421 [ + - + + ]: 54 : if (txa->txa_ethdev == NULL || txa_ethdev->nb_queues != 0)
422 : : return;
423 : :
424 : 8 : tqi = txa_ethdev->queues;
425 : 8 : txa_ethdev->queues = NULL;
426 : 8 : rte_free(tqi);
427 : :
428 [ + + ]: 8 : if (txa->nb_queues == 0) {
429 : 7 : rte_free(txa->txa_ethdev);
430 : 7 : txa->txa_ethdev = NULL;
431 : : }
432 : : }
433 : :
434 : : static void
435 : 0 : txa_service_unregister(struct txa_service_data *txa)
436 : : {
437 [ # # ]: 0 : if (txa->service_id != TXA_INVALID_SERVICE_ID) {
438 : 0 : rte_service_component_runstate_set(txa->service_id, 0);
439 [ # # ]: 0 : while (rte_service_may_be_active(txa->service_id))
440 : : rte_pause();
441 : 0 : rte_service_component_unregister(txa->service_id);
442 : : }
443 : 0 : txa->service_id = TXA_INVALID_SERVICE_ID;
444 : 0 : }
445 : :
446 : : static int
447 : 54 : txa_service_register(struct txa_service_data *txa)
448 : : {
449 : : int ret;
450 : : struct rte_service_spec service;
451 : : struct rte_event_eth_tx_adapter_conf conf;
452 : :
453 [ + + ]: 54 : if (txa->service_id != TXA_INVALID_SERVICE_ID)
454 : : return 0;
455 : :
456 : : memset(&service, 0, sizeof(service));
457 : 7 : snprintf(service.name, TXA_SERVICE_NAME_LEN, "txa_%d", txa->id);
458 : 7 : service.socket_id = txa->socket_id;
459 : 7 : service.callback = txa_service_func;
460 : 7 : service.callback_userdata = txa;
461 : 7 : service.capabilities = RTE_SERVICE_CAP_MT_SAFE;
462 : 7 : ret = rte_service_component_register(&service,
463 : 7 : (uint32_t *)&txa->service_id);
464 [ - + ]: 7 : if (ret) {
465 : 0 : RTE_EDEV_LOG_ERR("failed to register service %s err = %"
466 : : PRId32, service.name, ret);
467 : 0 : return ret;
468 : : }
469 : :
470 : 7 : ret = txa->conf_cb(txa->id, txa->eventdev_id, &conf, txa->conf_arg);
471 [ - + ]: 7 : if (ret) {
472 : 0 : txa_service_unregister(txa);
473 : 0 : return ret;
474 : : }
475 : :
476 : 7 : rte_service_component_runstate_set(txa->service_id, 1);
477 : 7 : txa->port_id = conf.event_port_id;
478 : 7 : txa->max_nb_tx = conf.max_nb_tx;
479 : 7 : return 0;
480 : : }
481 : :
482 : : static struct rte_eth_dev_tx_buffer *
483 : 54 : txa_service_tx_buf_alloc(struct txa_service_data *txa,
484 : : const struct rte_eth_dev *dev)
485 : : {
486 : : struct rte_eth_dev_tx_buffer *tb;
487 : : uint16_t port_id;
488 : :
489 : 54 : port_id = dev->data->port_id;
490 : 54 : tb = rte_zmalloc_socket(txa->mem_name,
491 : : RTE_ETH_TX_BUFFER_SIZE(TXA_BATCH_SIZE),
492 : : 0,
493 : : rte_eth_dev_socket_id(port_id));
494 [ - + ]: 54 : if (tb == NULL)
495 : 0 : RTE_EDEV_LOG_ERR("Failed to allocate memory for tx buffer");
496 : 54 : return tb;
497 : : }
498 : :
499 : : static int
500 : : txa_service_is_queue_added(struct txa_service_data *txa,
501 : : const struct rte_eth_dev *dev,
502 : : uint16_t tx_queue_id)
503 : : {
504 : : struct txa_service_queue_info *tqi;
505 : :
506 [ + + + + ]: 59 : tqi = txa_service_queue(txa, dev->data->port_id, tx_queue_id);
507 [ + - + + : 100 : return tqi && tqi->added;
+ - + + +
- + - ]
508 : : }
509 : :
510 : : static int
511 : 5 : txa_service_ctrl(uint8_t id, int start)
512 : : {
513 : : int ret;
514 : : struct txa_service_data *txa;
515 : :
516 : : txa = txa_service_id_to_data(id);
517 [ + - + - ]: 5 : if (txa == NULL || txa->service_id == TXA_INVALID_SERVICE_ID)
518 : : return 0;
519 : :
520 : 5 : rte_spinlock_lock(&txa->tx_lock);
521 : 5 : ret = rte_service_runstate_set(txa->service_id, start);
522 : : rte_spinlock_unlock(&txa->tx_lock);
523 : :
524 : 5 : return ret;
525 : : }
526 : :
527 : : static void
528 : 0 : txa_service_buffer_retry(struct rte_mbuf **pkts, uint16_t unsent,
529 : : void *userdata)
530 : : {
531 : : struct txa_retry *tr;
532 : : struct txa_service_data *data;
533 : : struct rte_event_eth_tx_adapter_stats *stats;
534 : : uint16_t sent = 0;
535 : : unsigned int retry = 0;
536 : : uint16_t i, n;
537 : :
538 : : tr = (struct txa_retry *)(uintptr_t)userdata;
539 : 0 : data = txa_service_id_to_data(tr->id);
540 : : stats = &data->stats;
541 : :
542 : : do {
543 : 0 : n = rte_eth_tx_burst(tr->port_id, tr->tx_queue,
544 : 0 : &pkts[sent], unsent - sent);
545 : :
546 : 0 : sent += n;
547 [ # # # # ]: 0 : } while (sent != unsent && retry++ < TXA_RETRY_CNT);
548 : :
549 [ # # ]: 0 : for (i = sent; i < unsent; i++)
550 : 0 : rte_pktmbuf_free(pkts[i]);
551 : :
552 : 0 : stats->tx_retry += retry;
553 : 0 : stats->tx_packets += sent;
554 : 0 : stats->tx_dropped += unsent - sent;
555 : 0 : }
556 : :
557 : : static uint16_t
558 : 0 : txa_process_event_vector(struct txa_service_data *txa,
559 : : struct rte_event_vector *vec)
560 : : {
561 : : struct txa_service_queue_info *tqi;
562 : : uint16_t port, queue, nb_tx = 0;
563 : : struct rte_mbuf **mbufs;
564 : : int i;
565 : :
566 : 0 : mbufs = (struct rte_mbuf **)vec->mbufs;
567 [ # # ]: 0 : if (vec->attr_valid) {
568 : 0 : port = vec->port;
569 : 0 : queue = vec->queue;
570 [ # # ]: 0 : tqi = txa_service_queue(txa, port, queue);
571 [ # # # # : 0 : if (unlikely(tqi == NULL || !tqi->added || tqi->stopped)) {
# # ]
572 : 0 : rte_pktmbuf_free_bulk(&mbufs[vec->elem_offset],
573 : 0 : vec->nb_elem);
574 : 0 : rte_mempool_put(rte_mempool_from_obj(vec), vec);
575 : 0 : return 0;
576 : : }
577 [ # # ]: 0 : for (i = 0; i < vec->nb_elem; i++) {
578 : 0 : nb_tx += rte_eth_tx_buffer(port, queue, tqi->tx_buf,
579 [ # # ]: 0 : mbufs[i + vec->elem_offset]);
580 : : }
581 : : } else {
582 [ # # ]: 0 : for (i = vec->elem_offset; i < vec->elem_offset + vec->nb_elem;
583 : 0 : i++) {
584 [ # # ]: 0 : port = mbufs[i]->port;
585 : : queue = rte_event_eth_tx_adapter_txq_get(mbufs[i]);
586 [ # # ]: 0 : tqi = txa_service_queue(txa, port, queue);
587 [ # # # # : 0 : if (unlikely(tqi == NULL || !tqi->added ||
# # ]
588 : : tqi->stopped)) {
589 : 0 : rte_pktmbuf_free(mbufs[i]);
590 : 0 : continue;
591 : : }
592 [ # # ]: 0 : nb_tx += rte_eth_tx_buffer(port, queue, tqi->tx_buf,
593 : : mbufs[i]);
594 : : }
595 : : }
596 : 0 : rte_mempool_put(rte_mempool_from_obj(vec), vec);
597 : :
598 : 0 : return nb_tx;
599 : : }
600 : :
601 : : static void
602 : 4096 : txa_service_tx(struct txa_service_data *txa, struct rte_event *ev,
603 : : uint32_t n)
604 : : {
605 : : uint32_t i;
606 : : uint16_t nb_tx;
607 : : struct rte_event_eth_tx_adapter_stats *stats;
608 : :
609 : : stats = &txa->stats;
610 : :
611 : : nb_tx = 0;
612 [ + + ]: 8192 : for (i = 0; i < n; i++) {
613 : : uint16_t port;
614 : : uint16_t queue;
615 : : struct txa_service_queue_info *tqi;
616 : :
617 [ + - ]: 4096 : if (!(ev[i].event_type & RTE_EVENT_TYPE_VECTOR)) {
618 : : struct rte_mbuf *m;
619 : :
620 : 4096 : m = ev[i].mbuf;
621 [ + - ]: 4096 : port = m->port;
622 : : queue = rte_event_eth_tx_adapter_txq_get(m);
623 : :
624 [ + - ]: 4096 : tqi = txa_service_queue(txa, port, queue);
625 [ + - + - : 4096 : if (unlikely(tqi == NULL || !tqi->added ||
- + ]
626 : : tqi->stopped)) {
627 : 0 : rte_pktmbuf_free(m);
628 : 0 : continue;
629 : : }
630 : :
631 [ - + ]: 4096 : nb_tx += rte_eth_tx_buffer(port, queue, tqi->tx_buf, m);
632 : : } else {
633 : 0 : nb_tx += txa_process_event_vector(txa, ev[i].vec);
634 : : }
635 : : }
636 : :
637 : 4096 : stats->tx_packets += nb_tx;
638 : 4096 : }
639 : :
640 : : static int32_t
641 : 4198400 : txa_service_func(void *args)
642 : : {
643 : : struct txa_service_data *txa = args;
644 : : uint8_t dev_id;
645 : : uint8_t port;
646 : : int ret = -EAGAIN;
647 : : uint16_t n;
648 : : uint32_t nb_tx, max_nb_tx;
649 : : struct rte_event ev[TXA_BATCH_SIZE];
650 : :
651 : 4198400 : dev_id = txa->eventdev_id;
652 : 4198400 : max_nb_tx = txa->max_nb_tx;
653 : 4198400 : port = txa->port_id;
654 : :
655 [ + - ]: 4198400 : if (txa->nb_queues == 0)
656 : : return ret;
657 : :
658 [ + - ]: 4198400 : if (!rte_spinlock_trylock(&txa->tx_lock))
659 : : return ret;
660 : :
661 [ + - ]: 4202496 : for (nb_tx = 0; nb_tx < max_nb_tx; nb_tx += n) {
662 : :
663 : 4202496 : n = rte_event_dequeue_burst(dev_id, port, ev, RTE_DIM(ev), 0);
664 [ + + ]: 4202496 : if (!n)
665 : : break;
666 : 4096 : txa_service_tx(txa, ev, n);
667 : : ret = 0;
668 : : }
669 : :
670 [ + + ]: 4198400 : if (txa->loop_cnt++ == txa->flush_threshold) {
671 : :
672 : : struct txa_service_ethdev *tdi;
673 : : struct txa_service_queue_info *tqi;
674 : : struct rte_eth_dev *dev;
675 : : uint16_t i;
676 : :
677 : 4096 : txa->loop_cnt = 0;
678 : 4096 : tdi = txa->txa_ethdev;
679 : : nb_tx = 0;
680 : :
681 [ + + ]: 12288 : RTE_ETH_FOREACH_DEV(i) {
682 : : uint16_t q;
683 : :
684 [ + - ]: 8192 : if (i >= txa->dev_count)
685 : : break;
686 : :
687 : 8192 : dev = tdi[i].dev;
688 [ + + ]: 8192 : if (tdi[i].nb_queues == 0)
689 : 4096 : continue;
690 [ + + ]: 69632 : for (q = 0; q < dev->data->nb_tx_queues; q++) {
691 : :
692 [ + - ]: 65536 : tqi = txa_service_queue(txa, i, q);
693 [ + - + - : 65536 : if (unlikely(tqi == NULL || !tqi->added ||
- + ]
694 : : tqi->stopped))
695 : 0 : continue;
696 : :
697 : 65536 : nb_tx += rte_eth_tx_buffer_flush(i, q,
698 : : tqi->tx_buf);
699 : : }
700 : : }
701 : :
702 [ + - ]: 4096 : if (likely(nb_tx > 0)) {
703 : 4096 : txa->stats.tx_packets += nb_tx;
704 : : ret = 0;
705 : : }
706 : : }
707 : : rte_spinlock_unlock(&txa->tx_lock);
708 : 4198400 : return ret;
709 : : }
710 : :
711 : : static int
712 : 8 : txa_service_adapter_create(uint8_t id, struct rte_eventdev *dev,
713 : : struct rte_event_port_conf *port_conf)
714 : : {
715 : : struct txa_service_data *txa;
716 : : struct rte_event_port_conf *cb_conf;
717 : : int ret;
718 : :
719 : 8 : cb_conf = rte_malloc(NULL, sizeof(*cb_conf), 0);
720 [ + - ]: 8 : if (cb_conf == NULL)
721 : : return -ENOMEM;
722 : :
723 : 8 : *cb_conf = *port_conf;
724 : 8 : ret = txa_service_adapter_create_ext(id, dev, txa_service_conf_cb,
725 : : cb_conf);
726 [ - + ]: 8 : if (ret) {
727 : 0 : rte_free(cb_conf);
728 : 0 : return ret;
729 : : }
730 : :
731 : : txa = txa_service_id_to_data(id);
732 : 8 : txa->conf_free = 1;
733 : 8 : return ret;
734 : : }
735 : :
736 : : static int
737 : 8 : txa_service_adapter_create_ext(uint8_t id, struct rte_eventdev *dev,
738 : : rte_event_eth_tx_adapter_conf_cb conf_cb,
739 : : void *conf_arg)
740 : : {
741 : : struct txa_service_data *txa;
742 : : int socket_id;
743 : : char mem_name[TXA_SERVICE_NAME_LEN];
744 : : int ret;
745 : :
746 [ + - ]: 8 : if (conf_cb == NULL)
747 : : return -EINVAL;
748 : :
749 : 8 : socket_id = dev->data->socket_id;
750 : 8 : snprintf(mem_name, TXA_MEM_NAME_LEN,
751 : : "rte_event_eth_txa_%d",
752 : : id);
753 : :
754 : 8 : ret = txa_service_data_init();
755 [ + - ]: 8 : if (ret != 0)
756 : : return ret;
757 : :
758 : 8 : txa = rte_zmalloc_socket(mem_name,
759 : : sizeof(*txa),
760 : : RTE_CACHE_LINE_SIZE, socket_id);
761 [ - + ]: 8 : if (txa == NULL) {
762 : 0 : RTE_EDEV_LOG_ERR("failed to get mem for tx adapter");
763 : 0 : return -ENOMEM;
764 : : }
765 : :
766 : 8 : txa->id = id;
767 : 8 : txa->eventdev_id = dev->data->dev_id;
768 : 8 : txa->socket_id = socket_id;
769 : 8 : strncpy(txa->mem_name, mem_name, TXA_SERVICE_NAME_LEN);
770 : 8 : txa->conf_cb = conf_cb;
771 : 8 : txa->conf_arg = conf_arg;
772 : 8 : txa->service_id = TXA_INVALID_SERVICE_ID;
773 : : rte_spinlock_init(&txa->tx_lock);
774 : 8 : txa_service_data_array[id] = txa;
775 : 8 : txa->flush_threshold = TXA_FLUSH_THRESHOLD;
776 : :
777 : 8 : return 0;
778 : : }
779 : :
780 : : static int
781 : : txa_service_event_port_get(uint8_t id, uint8_t *port)
782 : : {
783 : : struct txa_service_data *txa;
784 : :
785 : : txa = txa_service_id_to_data(id);
786 [ + - ]: 1 : if (txa->service_id == TXA_INVALID_SERVICE_ID)
787 : : return -ENODEV;
788 : :
789 : 1 : *port = txa->port_id;
790 : 1 : return 0;
791 : : }
792 : :
793 : : static int
794 : 8 : txa_service_adapter_free(uint8_t id)
795 : : {
796 : : struct txa_service_data *txa;
797 : :
798 : : txa = txa_service_id_to_data(id);
799 [ - + ]: 8 : if (txa->nb_queues) {
800 : 0 : RTE_EDEV_LOG_ERR("%" PRIu16 " Tx queues not deleted",
801 : : txa->nb_queues);
802 : 0 : return -EBUSY;
803 : : }
804 : :
805 [ + - ]: 8 : if (txa->conf_free)
806 : 8 : rte_free(txa->conf_arg);
807 : 8 : rte_free(txa);
808 : 8 : return 0;
809 : : }
810 : :
811 : : static int
812 : 57 : txa_service_queue_add(uint8_t id,
813 : : __rte_unused struct rte_eventdev *dev,
814 : : const struct rte_eth_dev *eth_dev,
815 : : int32_t tx_queue_id)
816 : : {
817 : : struct txa_service_data *txa;
818 : : struct txa_service_ethdev *tdi;
819 : : struct txa_service_queue_info *tqi;
820 : : struct rte_eth_dev_tx_buffer *tb;
821 : : struct txa_retry *txa_retry;
822 : : int ret = 0;
823 : :
824 : 57 : txa = txa_service_id_to_data(id);
825 : :
826 [ + + ]: 57 : if (tx_queue_id == -1) {
827 : : int nb_queues;
828 : : uint16_t i, j;
829 : : uint16_t *qdone;
830 : :
831 : 3 : nb_queues = eth_dev->data->nb_tx_queues;
832 [ + + ]: 3 : if (txa->dev_count > eth_dev->data->port_id) {
833 : 1 : tdi = &txa->txa_ethdev[eth_dev->data->port_id];
834 : 1 : nb_queues -= tdi->nb_queues;
835 : : }
836 : :
837 : 3 : qdone = rte_zmalloc(txa->mem_name,
838 : : nb_queues * sizeof(*qdone), 0);
839 [ + - ]: 3 : if (qdone == NULL)
840 : : return -ENOMEM;
841 : : j = 0;
842 [ + + ]: 50 : for (i = 0; i < nb_queues; i++) {
843 : 1 : if (txa_service_is_queue_added(txa, eth_dev, i))
844 : 1 : continue;
845 : 46 : ret = txa_service_queue_add(id, dev, eth_dev, i);
846 [ + - ]: 46 : if (ret == 0)
847 : 46 : qdone[j++] = i;
848 : : else
849 : : break;
850 : : }
851 : :
852 [ - + ]: 3 : if (i != nb_queues) {
853 [ # # ]: 0 : for (i = 0; i < j; i++)
854 : 0 : txa_service_queue_del(id, eth_dev, qdone[i]);
855 : : }
856 : 3 : rte_free(qdone);
857 : 3 : return ret;
858 : : }
859 : :
860 : 54 : ret = txa_service_register(txa);
861 [ + - ]: 54 : if (ret)
862 : : return ret;
863 : :
864 : 54 : rte_spinlock_lock(&txa->tx_lock);
865 : :
866 [ + + ]: 54 : if (txa_service_is_queue_added(txa, eth_dev, tx_queue_id))
867 : 0 : goto ret_unlock;
868 : :
869 : 54 : ret = txa_service_queue_array_alloc(txa, eth_dev->data->port_id);
870 [ - + ]: 54 : if (ret)
871 : 0 : goto err_unlock;
872 : :
873 : 54 : tb = txa_service_tx_buf_alloc(txa, eth_dev);
874 [ - + ]: 54 : if (tb == NULL)
875 : 0 : goto err_unlock;
876 : :
877 [ + - ]: 54 : tdi = &txa->txa_ethdev[eth_dev->data->port_id];
878 : : tqi = txa_service_queue(txa, eth_dev->data->port_id, tx_queue_id);
879 [ - + ]: 54 : if (tqi == NULL)
880 : 0 : goto err_unlock;
881 : :
882 : 54 : txa_retry = &tqi->txa_retry;
883 : 54 : txa_retry->id = txa->id;
884 : 54 : txa_retry->port_id = eth_dev->data->port_id;
885 : 54 : txa_retry->tx_queue = tx_queue_id;
886 : :
887 : 54 : rte_eth_tx_buffer_init(tb, TXA_BATCH_SIZE);
888 : 54 : rte_eth_tx_buffer_set_err_callback(tb,
889 : : txa_service_buffer_retry, txa_retry);
890 : :
891 : 54 : tqi->tx_buf = tb;
892 : 54 : tqi->added = 1;
893 : 54 : tqi->stopped = false;
894 : 54 : tdi->nb_queues++;
895 : 54 : txa->nb_queues++;
896 : :
897 : 54 : ret_unlock:
898 : : rte_spinlock_unlock(&txa->tx_lock);
899 : 54 : return 0;
900 : :
901 : 0 : err_unlock:
902 [ # # ]: 0 : if (txa->nb_queues == 0) {
903 : 0 : txa_service_queue_array_free(txa,
904 : 0 : eth_dev->data->port_id);
905 : 0 : txa_service_unregister(txa);
906 : : }
907 : :
908 : : rte_spinlock_unlock(&txa->tx_lock);
909 : 0 : return -1;
910 : : }
911 : :
912 : : static inline void
913 : 56 : txa_txq_buffer_drain(struct txa_service_queue_info *tqi)
914 : : {
915 : : struct rte_eth_dev_tx_buffer *b;
916 : : uint16_t i;
917 : :
918 : 56 : b = tqi->tx_buf;
919 : :
920 [ - + ]: 56 : for (i = 0; i < b->length; i++)
921 : 0 : rte_pktmbuf_free(b->pkts[i]);
922 : :
923 : 56 : b->length = 0;
924 : 56 : }
925 : :
926 : : static int
927 : 62 : txa_service_queue_del(uint8_t id,
928 : : const struct rte_eth_dev *dev,
929 : : int32_t tx_queue_id)
930 : : {
931 : : struct txa_service_data *txa;
932 : : struct txa_service_queue_info *tqi;
933 : : struct rte_eth_dev_tx_buffer *tb;
934 : : uint16_t port_id;
935 : :
936 : 62 : txa = txa_service_id_to_data(id);
937 : 62 : port_id = dev->data->port_id;
938 : :
939 [ + + ]: 62 : if (tx_queue_id == -1) {
940 : : uint16_t i, q, nb_queues;
941 : : int ret = 0;
942 : :
943 [ + + ]: 8 : if (txa->txa_ethdev == NULL)
944 : : return 0;
945 : 7 : nb_queues = txa->txa_ethdev[port_id].nb_queues;
946 [ + - ]: 7 : if (nb_queues == 0)
947 : : return 0;
948 : :
949 : : i = 0;
950 : : q = 0;
951 : 7 : tqi = txa->txa_ethdev[port_id].queues;
952 : :
953 [ + + ]: 60 : while (i < nb_queues) {
954 : :
955 [ + + ]: 53 : if (tqi[q].added) {
956 : 52 : ret = txa_service_queue_del(id, dev, q);
957 : 52 : i++;
958 [ + - ]: 52 : if (ret != 0)
959 : : break;
960 : : }
961 : 53 : q++;
962 : : }
963 : 7 : return ret;
964 : : }
965 : :
966 : : txa = txa_service_id_to_data(id);
967 : :
968 : 54 : rte_spinlock_lock(&txa->tx_lock);
969 [ + - ]: 54 : tqi = txa_service_queue(txa, port_id, tx_queue_id);
970 [ + - - + ]: 54 : if (tqi == NULL || !tqi->added)
971 : 0 : goto ret_unlock;
972 : :
973 : : /* Drain the buffered mbufs */
974 : 54 : txa_txq_buffer_drain(tqi);
975 : 54 : tb = tqi->tx_buf;
976 : 54 : tqi->added = 0;
977 : 54 : tqi->tx_buf = NULL;
978 : 54 : rte_free(tb);
979 : 54 : txa->nb_queues--;
980 : 54 : txa->txa_ethdev[port_id].nb_queues--;
981 : :
982 : 54 : txa_service_queue_array_free(txa, port_id);
983 : :
984 : 54 : ret_unlock:
985 : : rte_spinlock_unlock(&txa->tx_lock);
986 : 54 : return 0;
987 : : }
988 : :
989 : : static int
990 : 3 : txa_service_id_get(uint8_t id, uint32_t *service_id)
991 : : {
992 : : struct txa_service_data *txa;
993 : :
994 : : txa = txa_service_id_to_data(id);
995 [ + - ]: 3 : if (txa->service_id == TXA_INVALID_SERVICE_ID)
996 : : return -ESRCH;
997 : :
998 [ + + ]: 3 : if (service_id == NULL)
999 : : return -EINVAL;
1000 : :
1001 [ - + ]: 1 : *service_id = txa->service_id;
1002 : :
1003 : 1 : rte_eventdev_trace_eth_tx_adapter_service_id_get(id, *service_id);
1004 : 1 : return 0;
1005 : : }
1006 : :
1007 : : static int
1008 : : txa_service_start(uint8_t id)
1009 : : {
1010 : 3 : return txa_service_ctrl(id, 1);
1011 : : }
1012 : :
1013 : : static int
1014 : : txa_service_stats_get(uint8_t id,
1015 : : struct rte_event_eth_tx_adapter_stats *stats)
1016 : : {
1017 : : struct txa_service_data *txa;
1018 : :
1019 : : txa = txa_service_id_to_data(id);
1020 : 2 : *stats = txa->stats;
1021 : : return 0;
1022 : : }
1023 : :
1024 : : static int
1025 : : txa_service_stats_reset(uint8_t id)
1026 : : {
1027 : : struct txa_service_data *txa;
1028 : :
1029 : : txa = txa_service_id_to_data(id);
1030 : 1 : memset(&txa->stats, 0, sizeof(txa->stats));
1031 : : return 0;
1032 : : }
1033 : :
1034 : : static int
1035 : : txa_service_stop(uint8_t id)
1036 : : {
1037 : 2 : return txa_service_ctrl(id, 0);
1038 : : }
1039 : :
1040 : :
1041 : : int
1042 : 10 : rte_event_eth_tx_adapter_create(uint8_t id, uint8_t dev_id,
1043 : : struct rte_event_port_conf *port_conf)
1044 : : {
1045 : : struct rte_eventdev *dev;
1046 : : int ret;
1047 : :
1048 [ + + ]: 10 : if (port_conf == NULL)
1049 : : return -EINVAL;
1050 : :
1051 [ - + ]: 9 : RTE_EVENT_ETH_TX_ADAPTER_ID_VALID_OR_ERR_RET(id, -EINVAL);
1052 [ + - ]: 9 : RTE_EVENTDEV_VALID_DEVID_OR_ERR_RET(dev_id, -EINVAL);
1053 : :
1054 : : dev = &rte_eventdevs[dev_id];
1055 : :
1056 : : ret = txa_init();
1057 [ + - ]: 9 : if (ret != 0)
1058 : : return ret;
1059 : :
1060 [ + + ]: 9 : if (txa_adapter_exist(id))
1061 : : return -EEXIST;
1062 : :
1063 : 8 : txa_dev_id_array[id] = dev_id;
1064 [ - + ]: 8 : if (txa_dev_adapter_create(id))
1065 : 0 : ret = txa_dev_adapter_create(id)(id, dev);
1066 : :
1067 [ - + ]: 8 : if (ret != 0) {
1068 : 0 : txa_dev_id_array[id] = TXA_INVALID_DEV_ID;
1069 : 0 : return ret;
1070 : : }
1071 : :
1072 : 8 : ret = txa_service_adapter_create(id, dev, port_conf);
1073 [ - + ]: 8 : if (ret != 0) {
1074 [ # # ]: 0 : if (txa_dev_adapter_free(id))
1075 : 0 : txa_dev_adapter_free(id)(id, dev);
1076 : 0 : txa_dev_id_array[id] = TXA_INVALID_DEV_ID;
1077 : 0 : return ret;
1078 : : }
1079 : 8 : rte_eventdev_trace_eth_tx_adapter_create(id, dev_id, NULL, port_conf,
1080 : : ret);
1081 : 8 : txa_dev_id_array[id] = dev_id;
1082 : 8 : return 0;
1083 : : }
1084 : :
1085 : : int
1086 : 0 : rte_event_eth_tx_adapter_create_ext(uint8_t id, uint8_t dev_id,
1087 : : rte_event_eth_tx_adapter_conf_cb conf_cb,
1088 : : void *conf_arg)
1089 : : {
1090 : : struct rte_eventdev *dev;
1091 : : int ret;
1092 : :
1093 [ # # ]: 0 : RTE_EVENT_ETH_TX_ADAPTER_ID_VALID_OR_ERR_RET(id, -EINVAL);
1094 [ # # ]: 0 : RTE_EVENTDEV_VALID_DEVID_OR_ERR_RET(dev_id, -EINVAL);
1095 : :
1096 : : ret = txa_init();
1097 [ # # ]: 0 : if (ret != 0)
1098 : : return ret;
1099 : :
1100 [ # # ]: 0 : if (txa_adapter_exist(id))
1101 : : return -EINVAL;
1102 : :
1103 : 0 : dev = &rte_eventdevs[dev_id];
1104 : :
1105 : 0 : txa_dev_id_array[id] = dev_id;
1106 [ # # ]: 0 : if (txa_dev_adapter_create_ext(id))
1107 : 0 : ret = txa_dev_adapter_create_ext(id)(id, dev);
1108 : :
1109 [ # # ]: 0 : if (ret != 0) {
1110 : 0 : txa_dev_id_array[id] = TXA_INVALID_DEV_ID;
1111 : 0 : return ret;
1112 : : }
1113 : :
1114 : 0 : ret = txa_service_adapter_create_ext(id, dev, conf_cb, conf_arg);
1115 [ # # ]: 0 : if (ret != 0) {
1116 [ # # ]: 0 : if (txa_dev_adapter_free(id))
1117 : 0 : txa_dev_adapter_free(id)(id, dev);
1118 : 0 : txa_dev_id_array[id] = TXA_INVALID_DEV_ID;
1119 : 0 : return ret;
1120 : : }
1121 : :
1122 : 0 : rte_eventdev_trace_eth_tx_adapter_create(id, dev_id, conf_cb, conf_arg,
1123 : : ret);
1124 : 0 : txa_dev_id_array[id] = dev_id;
1125 : 0 : return 0;
1126 : : }
1127 : :
1128 : :
1129 : : int
1130 : 1 : rte_event_eth_tx_adapter_event_port_get(uint8_t id, uint8_t *event_port_id)
1131 : : {
1132 [ - + ]: 1 : rte_eventdev_trace_eth_tx_adapter_event_port_get(id);
1133 : :
1134 [ - + + - : 2 : TXA_CHECK_OR_ERR_RET(id);
+ - ]
1135 : :
1136 : : return txa_service_event_port_get(id, event_port_id);
1137 : : }
1138 : :
1139 : : int
1140 : 11 : rte_event_eth_tx_adapter_free(uint8_t id)
1141 : : {
1142 : : int ret;
1143 : :
1144 [ - + + - : 22 : TXA_CHECK_OR_ERR_RET(id);
+ + ]
1145 : :
1146 : 8 : ret = txa_dev_adapter_free(id) ?
1147 [ - + ]: 8 : txa_dev_adapter_free(id)(id, txa_evdev(id)) :
1148 : : 0;
1149 : :
1150 [ # # ]: 0 : if (ret == 0)
1151 : 8 : ret = txa_service_adapter_free(id);
1152 [ - + ]: 8 : txa_dev_id_array[id] = TXA_INVALID_DEV_ID;
1153 : :
1154 : 8 : rte_eventdev_trace_eth_tx_adapter_free(id, ret);
1155 : 8 : return ret;
1156 : : }
1157 : :
1158 : : int
1159 : 13 : rte_event_eth_tx_adapter_queue_add(uint8_t id,
1160 : : uint16_t eth_dev_id,
1161 : : int32_t queue)
1162 : : {
1163 : : struct rte_eth_dev *eth_dev;
1164 : : int ret;
1165 : : uint32_t caps;
1166 : :
1167 [ + + ]: 13 : RTE_ETH_VALID_PORTID_OR_ERR_RET(eth_dev_id, -EINVAL);
1168 [ - + + - : 24 : TXA_CHECK_OR_ERR_RET(id);
+ + ]
1169 : :
1170 : 11 : eth_dev = &rte_eth_devices[eth_dev_id];
1171 [ - + + + : 11 : TXA_CHECK_TXQ(eth_dev, queue);
- + ]
1172 : :
1173 : 11 : caps = 0;
1174 [ - + ]: 11 : if (txa_dev_caps_get(id))
1175 : 0 : txa_dev_caps_get(id)(txa_evdev(id), eth_dev, &caps);
1176 : :
1177 [ - + ]: 11 : if (caps & RTE_EVENT_ETH_TX_ADAPTER_CAP_INTERNAL_PORT)
1178 : 0 : ret = txa_dev_queue_add(id) ?
1179 : 0 : txa_dev_queue_add(id)(id,
1180 : : txa_evdev(id),
1181 : : eth_dev,
1182 [ # # ]: 0 : queue) : 0;
1183 : : else
1184 : 11 : ret = txa_service_queue_add(id, txa_evdev(id), eth_dev, queue);
1185 : :
1186 : 11 : rte_eventdev_trace_eth_tx_adapter_queue_add(id, eth_dev_id, queue,
1187 : : ret);
1188 : 11 : return ret;
1189 : : }
1190 : :
1191 : : int
1192 : 11 : rte_event_eth_tx_adapter_queue_del(uint8_t id,
1193 : : uint16_t eth_dev_id,
1194 : : int32_t queue)
1195 : : {
1196 : : struct rte_eth_dev *eth_dev;
1197 : : int ret;
1198 : : uint32_t caps;
1199 : :
1200 [ - + ]: 11 : RTE_ETH_VALID_PORTID_OR_ERR_RET(eth_dev_id, -EINVAL);
1201 [ - + + - : 22 : TXA_CHECK_OR_ERR_RET(id);
+ + ]
1202 : :
1203 : 10 : eth_dev = &rte_eth_devices[eth_dev_id];
1204 : :
1205 : 10 : caps = 0;
1206 : :
1207 [ - + ]: 10 : if (txa_dev_caps_get(id))
1208 : 0 : txa_dev_caps_get(id)(txa_evdev(id), eth_dev, &caps);
1209 : :
1210 [ - + ]: 10 : if (caps & RTE_EVENT_ETH_TX_ADAPTER_CAP_INTERNAL_PORT)
1211 : 0 : ret = txa_dev_queue_del(id) ?
1212 : 0 : txa_dev_queue_del(id)(id, txa_evdev(id),
1213 : : eth_dev,
1214 [ # # ]: 0 : queue) : 0;
1215 : : else
1216 : 10 : ret = txa_service_queue_del(id, eth_dev, queue);
1217 : :
1218 : 10 : rte_eventdev_trace_eth_tx_adapter_queue_del(id, eth_dev_id, queue,
1219 : : ret);
1220 : 10 : return ret;
1221 : : }
1222 : :
1223 : : int
1224 : 1 : rte_event_eth_tx_adapter_service_id_get(uint8_t id, uint32_t *service_id)
1225 : : {
1226 [ - + + - : 2 : TXA_CHECK_OR_ERR_RET(id);
+ - ]
1227 : :
1228 : 1 : return txa_service_id_get(id, service_id);
1229 : : }
1230 : :
1231 : : int
1232 : 4 : rte_event_eth_tx_adapter_start(uint8_t id)
1233 : : {
1234 : : int ret;
1235 : :
1236 [ - + + - : 8 : TXA_CHECK_OR_ERR_RET(id);
+ + ]
1237 : :
1238 [ - + ]: 3 : ret = txa_dev_start(id) ? txa_dev_start(id)(id, txa_evdev(id)) : 0;
1239 [ # # ]: 0 : if (ret == 0)
1240 : : ret = txa_service_start(id);
1241 : 3 : rte_eventdev_trace_eth_tx_adapter_start(id, ret);
1242 : 3 : return ret;
1243 : : }
1244 : :
1245 : : int
1246 : 4 : rte_event_eth_tx_adapter_stats_get(uint8_t id,
1247 : : struct rte_event_eth_tx_adapter_stats *stats)
1248 : : {
1249 : : int ret;
1250 : :
1251 [ - + + - : 8 : TXA_CHECK_OR_ERR_RET(id);
+ + ]
1252 : :
1253 [ + + ]: 3 : if (stats == NULL)
1254 : : return -EINVAL;
1255 : :
1256 : 2 : *stats = (struct rte_event_eth_tx_adapter_stats){0};
1257 : :
1258 : 2 : ret = txa_dev_stats_get(id) ?
1259 [ - + ]: 2 : txa_dev_stats_get(id)(id, txa_evdev(id), stats) : 0;
1260 : :
1261 [ - - + - ]: 2 : if (ret == 0 && txa_service_id_get(id, NULL) != ESRCH) {
1262 [ - + ]: 2 : if (txa_dev_stats_get(id)) {
1263 : : struct rte_event_eth_tx_adapter_stats service_stats;
1264 : :
1265 : : ret = txa_service_stats_get(id, &service_stats);
1266 : : if (ret == 0) {
1267 : 0 : stats->tx_retry += service_stats.tx_retry;
1268 : 0 : stats->tx_packets += service_stats.tx_packets;
1269 : 0 : stats->tx_dropped += service_stats.tx_dropped;
1270 : : }
1271 : : } else
1272 : : ret = txa_service_stats_get(id, stats);
1273 : : }
1274 : :
1275 [ - + ]: 2 : rte_eventdev_trace_eth_tx_adapter_stats_get(id, stats->tx_retry, stats->tx_packets,
1276 : : stats->tx_dropped, ret);
1277 : :
1278 : 2 : return ret;
1279 : : }
1280 : :
1281 : : int
1282 : 1 : rte_event_eth_tx_adapter_stats_reset(uint8_t id)
1283 : : {
1284 : : int ret;
1285 : :
1286 [ - + + - : 2 : TXA_CHECK_OR_ERR_RET(id);
+ - ]
1287 : :
1288 : 1 : ret = txa_dev_stats_reset(id) ?
1289 [ - + ]: 1 : txa_dev_stats_reset(id)(id, txa_evdev(id)) : 0;
1290 [ # # ]: 0 : if (ret == 0)
1291 : : ret = txa_service_stats_reset(id);
1292 : :
1293 : 1 : rte_eventdev_trace_eth_tx_adapter_stats_reset(id, ret);
1294 : :
1295 : 1 : return ret;
1296 : : }
1297 : :
1298 : : int
1299 : 2 : rte_event_eth_tx_adapter_runtime_params_init(
1300 : : struct rte_event_eth_tx_adapter_runtime_params *txa_params)
1301 : : {
1302 [ + - ]: 2 : if (txa_params == NULL)
1303 : : return -EINVAL;
1304 : :
1305 : : memset(txa_params, 0, sizeof(*txa_params));
1306 : 2 : txa_params->max_nb_tx = TXA_MAX_NB_TX;
1307 : 2 : txa_params->flush_threshold = TXA_FLUSH_THRESHOLD;
1308 : :
1309 : 2 : return 0;
1310 : : }
1311 : :
1312 : : static int
1313 : : txa_caps_check(struct txa_service_data *txa)
1314 : : {
1315 [ + - + - ]: 13 : if (!txa->dev_count)
1316 : : return -EINVAL;
1317 : :
1318 [ + - + - ]: 13 : if (txa->service_id != TXA_INVALID_SERVICE_ID)
1319 : : return 0;
1320 : :
1321 : : return -ENOTSUP;
1322 : : }
1323 : :
1324 : : int
1325 : 6 : rte_event_eth_tx_adapter_runtime_params_set(uint8_t id,
1326 : : struct rte_event_eth_tx_adapter_runtime_params *txa_params)
1327 : : {
1328 : : struct txa_service_data *txa;
1329 : : int ret;
1330 : :
1331 [ + - ]: 6 : if (txa_lookup())
1332 : : return -ENOMEM;
1333 : :
1334 [ - + + - : 12 : TXA_CHECK_OR_ERR_RET(id);
+ - ]
1335 : :
1336 [ + - ]: 6 : if (txa_params == NULL)
1337 : : return -EINVAL;
1338 : :
1339 : : txa = txa_service_id_to_data(id);
1340 [ + - ]: 6 : if (txa == NULL)
1341 : : return -EINVAL;
1342 : :
1343 : : ret = txa_caps_check(txa);
1344 : : if (ret)
1345 : 0 : return ret;
1346 : :
1347 : 6 : rte_spinlock_lock(&txa->tx_lock);
1348 : 6 : txa->flush_threshold = txa_params->flush_threshold;
1349 : 6 : txa->max_nb_tx = txa_params->max_nb_tx;
1350 : : rte_spinlock_unlock(&txa->tx_lock);
1351 : :
1352 : 6 : return 0;
1353 : : }
1354 : :
1355 : : int
1356 : 7 : rte_event_eth_tx_adapter_runtime_params_get(uint8_t id,
1357 : : struct rte_event_eth_tx_adapter_runtime_params *txa_params)
1358 : : {
1359 : : struct txa_service_data *txa;
1360 : : int ret;
1361 : :
1362 [ + - ]: 7 : if (txa_lookup())
1363 : : return -ENOMEM;
1364 : :
1365 [ - + + - : 14 : TXA_CHECK_OR_ERR_RET(id);
+ - ]
1366 : :
1367 [ + - ]: 7 : if (txa_params == NULL)
1368 : : return -EINVAL;
1369 : :
1370 : : txa = txa_service_id_to_data(id);
1371 [ + - ]: 7 : if (txa == NULL)
1372 : : return -EINVAL;
1373 : :
1374 : : ret = txa_caps_check(txa);
1375 : : if (ret)
1376 : 0 : return ret;
1377 : :
1378 : 7 : rte_spinlock_lock(&txa->tx_lock);
1379 : 7 : txa_params->flush_threshold = txa->flush_threshold;
1380 : 7 : txa_params->max_nb_tx = txa->max_nb_tx;
1381 : : rte_spinlock_unlock(&txa->tx_lock);
1382 : :
1383 : 7 : return 0;
1384 : : }
1385 : :
1386 : : int
1387 : 3 : rte_event_eth_tx_adapter_stop(uint8_t id)
1388 : : {
1389 : : int ret;
1390 : :
1391 [ - + + - : 6 : TXA_CHECK_OR_ERR_RET(id);
+ + ]
1392 : :
1393 [ - + ]: 2 : ret = txa_dev_stop(id) ? txa_dev_stop(id)(id, txa_evdev(id)) : 0;
1394 [ # # ]: 0 : if (ret == 0)
1395 : : ret = txa_service_stop(id);
1396 : 2 : rte_eventdev_trace_eth_tx_adapter_stop(id, ret);
1397 : 2 : return ret;
1398 : : }
1399 : :
1400 : : int
1401 : 18 : rte_event_eth_tx_adapter_instance_get(uint16_t eth_dev_id,
1402 : : uint16_t tx_queue_id,
1403 : : uint8_t *txa_inst_id)
1404 : : {
1405 : : uint8_t id;
1406 : : int ret = -EINVAL;
1407 : : uint32_t caps;
1408 : : struct txa_service_data *txa;
1409 : :
1410 [ + - ]: 18 : if (txa_lookup())
1411 : : return -ENOMEM;
1412 : :
1413 [ + + ]: 18 : if (eth_dev_id >= rte_eth_dev_count_avail()) {
1414 : 3 : RTE_EDEV_LOG_ERR("Invalid ethernet port id %u", eth_dev_id);
1415 : 3 : return -EINVAL;
1416 : : }
1417 : :
1418 [ + + ]: 15 : if (tx_queue_id >= rte_eth_devices[eth_dev_id].data->nb_tx_queues) {
1419 : 3 : RTE_EDEV_LOG_ERR("Invalid tx queue id %u", tx_queue_id);
1420 : 3 : return -EINVAL;
1421 : : }
1422 : :
1423 [ - + ]: 12 : if (txa_inst_id == NULL) {
1424 : 0 : RTE_EDEV_LOG_ERR("txa_instance_id cannot be NULL");
1425 : 0 : return -EINVAL;
1426 : : }
1427 : :
1428 : : /* Iterate through all Tx adapter instances */
1429 [ + + ]: 204 : for (id = 0; id < RTE_EVENT_ETH_TX_ADAPTER_MAX_INSTANCE; id++) {
1430 : : txa = txa_service_id_to_data(id);
1431 [ + + ]: 198 : if (!txa)
1432 : 186 : continue;
1433 : :
1434 : 12 : caps = 0;
1435 [ - + ]: 12 : if (rte_event_eth_tx_adapter_caps_get(txa->eventdev_id,
1436 : : eth_dev_id,
1437 : : &caps))
1438 : 0 : continue;
1439 : :
1440 [ - + ]: 12 : if (caps & RTE_EVENT_ETH_TX_ADAPTER_CAP_INTERNAL_PORT) {
1441 : 0 : ret = txa_dev_instance_get(id) ?
1442 : 0 : txa_dev_instance_get(id)(eth_dev_id,
1443 : : tx_queue_id,
1444 : : txa_inst_id)
1445 [ # # ]: 0 : : -EINVAL;
1446 [ # # ]: 0 : if (ret == 0) {
1447 : 0 : rte_eventdev_trace_eth_tx_adapter_instance_get(eth_dev_id,
1448 [ # # ]: 0 : tx_queue_id, *txa_inst_id);
1449 : 0 : return ret;
1450 : : }
1451 : : } else {
1452 : : struct rte_eth_dev *eth_dev;
1453 : :
1454 : : eth_dev = &rte_eth_devices[eth_dev_id];
1455 : :
1456 : : if (txa_service_is_queue_added(txa, eth_dev,
1457 : : tx_queue_id)) {
1458 [ - + ]: 6 : *txa_inst_id = txa->id;
1459 : 6 : rte_eventdev_trace_eth_tx_adapter_instance_get(eth_dev_id,
1460 : : tx_queue_id, *txa_inst_id);
1461 : 6 : return 0;
1462 : : }
1463 : : }
1464 : : }
1465 : :
1466 : : return -EINVAL;
1467 : : }
1468 : :
1469 : : static inline int
1470 : 4 : txa_sw_queue_start_state_set(uint16_t eth_dev_id, uint16_t tx_queue_id,
1471 : : bool start_state, struct txa_service_data *txa)
1472 : : {
1473 : : struct txa_service_queue_info *tqi = NULL;
1474 : :
1475 : 4 : rte_spinlock_lock(&txa->tx_lock);
1476 : : tqi = txa_service_queue(txa, eth_dev_id, tx_queue_id);
1477 [ + - - + ]: 4 : if (unlikely(tqi == NULL || !tqi->added)) {
1478 : : rte_spinlock_unlock(&txa->tx_lock);
1479 : 0 : return -EINVAL;
1480 : : }
1481 [ + + ]: 4 : if (start_state == false)
1482 : 2 : txa_txq_buffer_drain(tqi);
1483 : :
1484 : 4 : tqi->stopped = !start_state;
1485 : : rte_spinlock_unlock(&txa->tx_lock);
1486 : 4 : return 0;
1487 : : }
1488 : :
1489 : : static int
1490 : 12 : txa_queue_start_state_set(uint16_t eth_dev_id, uint16_t tx_queue_id,
1491 : : bool start_state)
1492 : : {
1493 : : struct txa_service_data *txa;
1494 : : uint8_t txa_inst_id;
1495 : : int ret;
1496 : 12 : uint32_t caps = 0;
1497 : :
1498 : : /* Below API already does validation of input parameters.
1499 : : * Hence skipping the validation here.
1500 : : */
1501 : 12 : ret = rte_event_eth_tx_adapter_instance_get(eth_dev_id,
1502 : : tx_queue_id,
1503 : : &txa_inst_id);
1504 [ + + ]: 12 : if (ret < 0)
1505 : : return -EINVAL;
1506 : :
1507 : 4 : txa = txa_service_id_to_data(txa_inst_id);
1508 : 4 : ret = rte_event_eth_tx_adapter_caps_get(txa->eventdev_id,
1509 : : eth_dev_id,
1510 : : &caps);
1511 [ + - ]: 4 : if (ret < 0)
1512 : : return -EINVAL;
1513 : :
1514 [ - + ]: 4 : if (caps & RTE_EVENT_ETH_TX_ADAPTER_CAP_INTERNAL_PORT) {
1515 [ # # ]: 0 : if (start_state == true) {
1516 : 0 : ret = txa_dev_queue_start(txa_inst_id) ?
1517 : 0 : txa_dev_queue_start(txa_inst_id)(txa_inst_id,
1518 : : eth_dev_id,
1519 [ # # ]: 0 : tx_queue_id) : 0;
1520 : : } else {
1521 : 0 : ret = txa_dev_queue_stop(txa_inst_id) ?
1522 : 0 : txa_dev_queue_stop(txa_inst_id)(txa_inst_id,
1523 : : eth_dev_id,
1524 [ # # ]: 0 : tx_queue_id) : 0;
1525 : : }
1526 : 0 : return ret;
1527 : : }
1528 : :
1529 : 4 : return txa_sw_queue_start_state_set(eth_dev_id, tx_queue_id,
1530 : : start_state, txa);
1531 : : }
1532 : :
1533 : : int
1534 : 6 : rte_event_eth_tx_adapter_queue_start(uint16_t eth_dev_id, uint16_t tx_queue_id)
1535 : : {
1536 [ - + ]: 6 : rte_eventdev_trace_eth_tx_adapter_queue_start(eth_dev_id, tx_queue_id);
1537 : :
1538 : 6 : return txa_queue_start_state_set(eth_dev_id, tx_queue_id, true);
1539 : : }
1540 : :
1541 : : int
1542 : 6 : rte_event_eth_tx_adapter_queue_stop(uint16_t eth_dev_id, uint16_t tx_queue_id)
1543 : : {
1544 [ - + ]: 6 : rte_eventdev_trace_eth_tx_adapter_queue_stop(eth_dev_id, tx_queue_id);
1545 : :
1546 : 6 : return txa_queue_start_state_set(eth_dev_id, tx_queue_id, false);
1547 : : }
|