New upstream version 18.11-rc1
[deb_dpdk.git] / lib / librte_eventdev / rte_event_eth_tx_adapter.c
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 <rte_ethdev.h>
7
8 #include "rte_eventdev_pmd.h"
9 #include "rte_event_eth_tx_adapter.h"
10
11 #define TXA_BATCH_SIZE          32
12 #define TXA_SERVICE_NAME_LEN    32
13 #define TXA_MEM_NAME_LEN        32
14 #define TXA_FLUSH_THRESHOLD     1024
15 #define TXA_RETRY_CNT           100
16 #define TXA_MAX_NB_TX           128
17 #define TXA_INVALID_DEV_ID      INT32_C(-1)
18 #define TXA_INVALID_SERVICE_ID  INT64_C(-1)
19
20 #define txa_evdev(id) (&rte_eventdevs[txa_dev_id_array[(id)]])
21
22 #define txa_dev_caps_get(id) txa_evdev((id))->dev_ops->eth_tx_adapter_caps_get
23
24 #define txa_dev_adapter_create(t) txa_evdev(t)->dev_ops->eth_tx_adapter_create
25
26 #define txa_dev_adapter_create_ext(t) \
27                                 txa_evdev(t)->dev_ops->eth_tx_adapter_create
28
29 #define txa_dev_adapter_free(t) txa_evdev(t)->dev_ops->eth_tx_adapter_free
30
31 #define txa_dev_queue_add(id) txa_evdev(id)->dev_ops->eth_tx_adapter_queue_add
32
33 #define txa_dev_queue_del(t) txa_evdev(t)->dev_ops->eth_tx_adapter_queue_del
34
35 #define txa_dev_start(t) txa_evdev(t)->dev_ops->eth_tx_adapter_start
36
37 #define txa_dev_stop(t) txa_evdev(t)->dev_ops->eth_tx_adapter_stop
38
39 #define txa_dev_stats_reset(t) txa_evdev(t)->dev_ops->eth_tx_adapter_stats_reset
40
41 #define txa_dev_stats_get(t) txa_evdev(t)->dev_ops->eth_tx_adapter_stats_get
42
43 #define RTE_EVENT_ETH_TX_ADAPTER_ID_VALID_OR_ERR_RET(id, retval) \
44 do { \
45         if (!txa_valid_id(id)) { \
46                 RTE_EDEV_LOG_ERR("Invalid eth Rx adapter id = %d", id); \
47                 return retval; \
48         } \
49 } while (0)
50
51 #define TXA_CHECK_OR_ERR_RET(id) \
52 do {\
53         int ret; \
54         RTE_EVENT_ETH_TX_ADAPTER_ID_VALID_OR_ERR_RET((id), -EINVAL); \
55         ret = txa_init(); \
56         if (ret != 0) \
57                 return ret; \
58         if (!txa_adapter_exist((id))) \
59                 return -EINVAL; \
60 } while (0)
61
62 /* Tx retry callback structure */
63 struct txa_retry {
64         /* Ethernet port id */
65         uint16_t port_id;
66         /* Tx queue */
67         uint16_t tx_queue;
68         /* Adapter ID */
69         uint8_t id;
70 };
71
72 /* Per queue structure */
73 struct txa_service_queue_info {
74         /* Queue has been added */
75         uint8_t added;
76         /* Retry callback argument */
77         struct txa_retry txa_retry;
78         /* Tx buffer */
79         struct rte_eth_dev_tx_buffer *tx_buf;
80 };
81
82 /* PMD private structure */
83 struct txa_service_data {
84         /* Max mbufs processed in any service function invocation */
85         uint32_t max_nb_tx;
86         /* Number of Tx queues in adapter */
87         uint32_t nb_queues;
88         /*  Synchronization with data path */
89         rte_spinlock_t tx_lock;
90         /* Event port ID */
91         uint8_t port_id;
92         /* Event device identifier */
93         uint8_t eventdev_id;
94         /* Highest port id supported + 1 */
95         uint16_t dev_count;
96         /* Loop count to flush Tx buffers */
97         int loop_cnt;
98         /* Per ethernet device structure */
99         struct txa_service_ethdev *txa_ethdev;
100         /* Statistics */
101         struct rte_event_eth_tx_adapter_stats stats;
102         /* Adapter Identifier */
103         uint8_t id;
104         /* Conf arg must be freed */
105         uint8_t conf_free;
106         /* Configuration callback */
107         rte_event_eth_tx_adapter_conf_cb conf_cb;
108         /* Configuration callback argument */
109         void *conf_arg;
110         /* socket id */
111         int socket_id;
112         /* Per adapter EAL service */
113         int64_t service_id;
114         /* Memory allocation name */
115         char mem_name[TXA_MEM_NAME_LEN];
116 } __rte_cache_aligned;
117
118 /* Per eth device structure */
119 struct txa_service_ethdev {
120         /* Pointer to ethernet device */
121         struct rte_eth_dev *dev;
122         /* Number of queues added */
123         uint16_t nb_queues;
124         /* PMD specific queue data */
125         void *queues;
126 };
127
128 /* Array of adapter instances, initialized with event device id
129  * when adapter is created
130  */
131 static int *txa_dev_id_array;
132
133 /* Array of pointers to service implementation data */
134 static struct txa_service_data **txa_service_data_array;
135
136 static int32_t txa_service_func(void *args);
137 static int txa_service_adapter_create_ext(uint8_t id,
138                         struct rte_eventdev *dev,
139                         rte_event_eth_tx_adapter_conf_cb conf_cb,
140                         void *conf_arg);
141 static int txa_service_queue_del(uint8_t id,
142                                 const struct rte_eth_dev *dev,
143                                 int32_t tx_queue_id);
144
145 static int
146 txa_adapter_exist(uint8_t id)
147 {
148         return txa_dev_id_array[id] != TXA_INVALID_DEV_ID;
149 }
150
151 static inline int
152 txa_valid_id(uint8_t id)
153 {
154         return id < RTE_EVENT_ETH_TX_ADAPTER_MAX_INSTANCE;
155 }
156
157 static void *
158 txa_memzone_array_get(const char *name, unsigned int elt_size, int nb_elems)
159 {
160         const struct rte_memzone *mz;
161         unsigned int sz;
162
163         sz = elt_size * nb_elems;
164         sz = RTE_ALIGN(sz, RTE_CACHE_LINE_SIZE);
165
166         mz = rte_memzone_lookup(name);
167         if (mz == NULL) {
168                 mz = rte_memzone_reserve_aligned(name, sz, rte_socket_id(), 0,
169                                                  RTE_CACHE_LINE_SIZE);
170                 if (mz == NULL) {
171                         RTE_EDEV_LOG_ERR("failed to reserve memzone"
172                                         " name = %s err = %"
173                                         PRId32, name, rte_errno);
174                         return NULL;
175                 }
176         }
177
178         return  mz->addr;
179 }
180
181 static int
182 txa_dev_id_array_init(void)
183 {
184         if (txa_dev_id_array == NULL) {
185                 int i;
186
187                 txa_dev_id_array = txa_memzone_array_get("txa_adapter_array",
188                                         sizeof(int),
189                                         RTE_EVENT_ETH_TX_ADAPTER_MAX_INSTANCE);
190                 if (txa_dev_id_array == NULL)
191                         return -ENOMEM;
192
193                 for (i = 0; i < RTE_EVENT_ETH_TX_ADAPTER_MAX_INSTANCE; i++)
194                         txa_dev_id_array[i] = TXA_INVALID_DEV_ID;
195         }
196
197         return 0;
198 }
199
200 static int
201 txa_init(void)
202 {
203         return txa_dev_id_array_init();
204 }
205
206 static int
207 txa_service_data_init(void)
208 {
209         if (txa_service_data_array == NULL) {
210                 txa_service_data_array =
211                                 txa_memzone_array_get("txa_service_data_array",
212                                         sizeof(int),
213                                         RTE_EVENT_ETH_TX_ADAPTER_MAX_INSTANCE);
214                 if (txa_service_data_array == NULL)
215                         return -ENOMEM;
216         }
217
218         return 0;
219 }
220
221 static inline struct txa_service_data *
222 txa_service_id_to_data(uint8_t id)
223 {
224         return txa_service_data_array[id];
225 }
226
227 static inline struct txa_service_queue_info *
228 txa_service_queue(struct txa_service_data *txa, uint16_t port_id,
229                 uint16_t tx_queue_id)
230 {
231         struct txa_service_queue_info *tqi;
232
233         if (unlikely(txa->txa_ethdev == NULL || txa->dev_count < port_id + 1))
234                 return NULL;
235
236         tqi = txa->txa_ethdev[port_id].queues;
237
238         return likely(tqi != NULL) ? tqi + tx_queue_id : NULL;
239 }
240
241 static int
242 txa_service_conf_cb(uint8_t __rte_unused id, uint8_t dev_id,
243                 struct rte_event_eth_tx_adapter_conf *conf, void *arg)
244 {
245         int ret;
246         struct rte_eventdev *dev;
247         struct rte_event_port_conf *pc;
248         struct rte_event_dev_config dev_conf;
249         int started;
250         uint8_t port_id;
251
252         pc = arg;
253         dev = &rte_eventdevs[dev_id];
254         dev_conf = dev->data->dev_conf;
255
256         started = dev->data->dev_started;
257         if (started)
258                 rte_event_dev_stop(dev_id);
259
260         port_id = dev_conf.nb_event_ports;
261         dev_conf.nb_event_ports += 1;
262
263         ret = rte_event_dev_configure(dev_id, &dev_conf);
264         if (ret) {
265                 RTE_EDEV_LOG_ERR("failed to configure event dev %u",
266                                                 dev_id);
267                 if (started) {
268                         if (rte_event_dev_start(dev_id))
269                                 return -EIO;
270                 }
271                 return ret;
272         }
273
274         pc->disable_implicit_release = 0;
275         ret = rte_event_port_setup(dev_id, port_id, pc);
276         if (ret) {
277                 RTE_EDEV_LOG_ERR("failed to setup event port %u\n",
278                                         port_id);
279                 if (started) {
280                         if (rte_event_dev_start(dev_id))
281                                 return -EIO;
282                 }
283                 return ret;
284         }
285
286         conf->event_port_id = port_id;
287         conf->max_nb_tx = TXA_MAX_NB_TX;
288         if (started)
289                 ret = rte_event_dev_start(dev_id);
290         return ret;
291 }
292
293 static int
294 txa_service_ethdev_alloc(struct txa_service_data *txa)
295 {
296         struct txa_service_ethdev *txa_ethdev;
297         uint16_t i, dev_count;
298
299         dev_count = rte_eth_dev_count_avail();
300         if (txa->txa_ethdev && dev_count == txa->dev_count)
301                 return 0;
302
303         txa_ethdev = rte_zmalloc_socket(txa->mem_name,
304                                         dev_count * sizeof(*txa_ethdev),
305                                         0,
306                                         txa->socket_id);
307         if (txa_ethdev == NULL) {
308                 RTE_EDEV_LOG_ERR("Failed to alloc txa::txa_ethdev ");
309                 return -ENOMEM;
310         }
311
312         if (txa->dev_count)
313                 memcpy(txa_ethdev, txa->txa_ethdev,
314                         txa->dev_count * sizeof(*txa_ethdev));
315
316         RTE_ETH_FOREACH_DEV(i) {
317                 if (i == dev_count)
318                         break;
319                 txa_ethdev[i].dev = &rte_eth_devices[i];
320         }
321
322         txa->txa_ethdev = txa_ethdev;
323         txa->dev_count = dev_count;
324         return 0;
325 }
326
327 static int
328 txa_service_queue_array_alloc(struct txa_service_data *txa,
329                         uint16_t port_id)
330 {
331         struct txa_service_queue_info *tqi;
332         uint16_t nb_queue;
333         int ret;
334
335         ret = txa_service_ethdev_alloc(txa);
336         if (ret != 0)
337                 return ret;
338
339         if (txa->txa_ethdev[port_id].queues)
340                 return 0;
341
342         nb_queue = txa->txa_ethdev[port_id].dev->data->nb_tx_queues;
343         tqi = rte_zmalloc_socket(txa->mem_name,
344                                 nb_queue *
345                                 sizeof(struct txa_service_queue_info), 0,
346                                 txa->socket_id);
347         if (tqi == NULL)
348                 return -ENOMEM;
349         txa->txa_ethdev[port_id].queues = tqi;
350         return 0;
351 }
352
353 static void
354 txa_service_queue_array_free(struct txa_service_data *txa,
355                         uint16_t port_id)
356 {
357         struct txa_service_ethdev *txa_ethdev;
358         struct txa_service_queue_info *tqi;
359
360         txa_ethdev = &txa->txa_ethdev[port_id];
361         if (txa->txa_ethdev == NULL || txa_ethdev->nb_queues != 0)
362                 return;
363
364         tqi = txa_ethdev->queues;
365         txa_ethdev->queues = NULL;
366         rte_free(tqi);
367
368         if (txa->nb_queues == 0) {
369                 rte_free(txa->txa_ethdev);
370                 txa->txa_ethdev = NULL;
371         }
372 }
373
374 static void
375 txa_service_unregister(struct txa_service_data *txa)
376 {
377         if (txa->service_id != TXA_INVALID_SERVICE_ID) {
378                 rte_service_component_runstate_set(txa->service_id, 0);
379                 while (rte_service_may_be_active(txa->service_id))
380                         rte_pause();
381                 rte_service_component_unregister(txa->service_id);
382         }
383         txa->service_id = TXA_INVALID_SERVICE_ID;
384 }
385
386 static int
387 txa_service_register(struct txa_service_data *txa)
388 {
389         int ret;
390         struct rte_service_spec service;
391         struct rte_event_eth_tx_adapter_conf conf;
392
393         if (txa->service_id != TXA_INVALID_SERVICE_ID)
394                 return 0;
395
396         memset(&service, 0, sizeof(service));
397         snprintf(service.name, TXA_SERVICE_NAME_LEN, "txa_%d", txa->id);
398         service.socket_id = txa->socket_id;
399         service.callback = txa_service_func;
400         service.callback_userdata = txa;
401         service.capabilities = RTE_SERVICE_CAP_MT_SAFE;
402         ret = rte_service_component_register(&service,
403                                         (uint32_t *)&txa->service_id);
404         if (ret) {
405                 RTE_EDEV_LOG_ERR("failed to register service %s err = %"
406                                  PRId32, service.name, ret);
407                 return ret;
408         }
409
410         ret = txa->conf_cb(txa->id, txa->eventdev_id, &conf, txa->conf_arg);
411         if (ret) {
412                 txa_service_unregister(txa);
413                 return ret;
414         }
415
416         rte_service_component_runstate_set(txa->service_id, 1);
417         txa->port_id = conf.event_port_id;
418         txa->max_nb_tx = conf.max_nb_tx;
419         return 0;
420 }
421
422 static struct rte_eth_dev_tx_buffer *
423 txa_service_tx_buf_alloc(struct txa_service_data *txa,
424                         const struct rte_eth_dev *dev)
425 {
426         struct rte_eth_dev_tx_buffer *tb;
427         uint16_t port_id;
428
429         port_id = dev->data->port_id;
430         tb = rte_zmalloc_socket(txa->mem_name,
431                                 RTE_ETH_TX_BUFFER_SIZE(TXA_BATCH_SIZE),
432                                 0,
433                                 rte_eth_dev_socket_id(port_id));
434         if (tb == NULL)
435                 RTE_EDEV_LOG_ERR("Failed to allocate memory for tx buffer");
436         return tb;
437 }
438
439 static int
440 txa_service_is_queue_added(struct txa_service_data *txa,
441                         const struct rte_eth_dev *dev,
442                         uint16_t tx_queue_id)
443 {
444         struct txa_service_queue_info *tqi;
445
446         tqi = txa_service_queue(txa, dev->data->port_id, tx_queue_id);
447         return tqi && tqi->added;
448 }
449
450 static int
451 txa_service_ctrl(uint8_t id, int start)
452 {
453         int ret;
454         struct txa_service_data *txa;
455
456         txa = txa_service_id_to_data(id);
457         if (txa->service_id == TXA_INVALID_SERVICE_ID)
458                 return 0;
459
460         ret = rte_service_runstate_set(txa->service_id, start);
461         if (ret == 0 && !start) {
462                 while (rte_service_may_be_active(txa->service_id))
463                         rte_pause();
464         }
465         return ret;
466 }
467
468 static void
469 txa_service_buffer_retry(struct rte_mbuf **pkts, uint16_t unsent,
470                         void *userdata)
471 {
472         struct txa_retry *tr;
473         struct txa_service_data *data;
474         struct rte_event_eth_tx_adapter_stats *stats;
475         uint16_t sent = 0;
476         unsigned int retry = 0;
477         uint16_t i, n;
478
479         tr = (struct txa_retry *)(uintptr_t)userdata;
480         data = txa_service_id_to_data(tr->id);
481         stats = &data->stats;
482
483         do {
484                 n = rte_eth_tx_burst(tr->port_id, tr->tx_queue,
485                                &pkts[sent], unsent - sent);
486
487                 sent += n;
488         } while (sent != unsent && retry++ < TXA_RETRY_CNT);
489
490         for (i = sent; i < unsent; i++)
491                 rte_pktmbuf_free(pkts[i]);
492
493         stats->tx_retry += retry;
494         stats->tx_packets += sent;
495         stats->tx_dropped += unsent - sent;
496 }
497
498 static void
499 txa_service_tx(struct txa_service_data *txa, struct rte_event *ev,
500         uint32_t n)
501 {
502         uint32_t i;
503         uint16_t nb_tx;
504         struct rte_event_eth_tx_adapter_stats *stats;
505
506         stats = &txa->stats;
507
508         nb_tx = 0;
509         for (i = 0; i < n; i++) {
510                 struct rte_mbuf *m;
511                 uint16_t port;
512                 uint16_t queue;
513                 struct txa_service_queue_info *tqi;
514
515                 m = ev[i].mbuf;
516                 port = m->port;
517                 queue = rte_event_eth_tx_adapter_txq_get(m);
518
519                 tqi = txa_service_queue(txa, port, queue);
520                 if (unlikely(tqi == NULL || !tqi->added)) {
521                         rte_pktmbuf_free(m);
522                         continue;
523                 }
524
525                 nb_tx += rte_eth_tx_buffer(port, queue, tqi->tx_buf, m);
526         }
527
528         stats->tx_packets += nb_tx;
529 }
530
531 static int32_t
532 txa_service_func(void *args)
533 {
534         struct txa_service_data *txa = args;
535         uint8_t dev_id;
536         uint8_t port;
537         uint16_t n;
538         uint32_t nb_tx, max_nb_tx;
539         struct rte_event ev[TXA_BATCH_SIZE];
540
541         dev_id = txa->eventdev_id;
542         max_nb_tx = txa->max_nb_tx;
543         port = txa->port_id;
544
545         if (txa->nb_queues == 0)
546                 return 0;
547
548         if (!rte_spinlock_trylock(&txa->tx_lock))
549                 return 0;
550
551         for (nb_tx = 0; nb_tx < max_nb_tx; nb_tx += n) {
552
553                 n = rte_event_dequeue_burst(dev_id, port, ev, RTE_DIM(ev), 0);
554                 if (!n)
555                         break;
556                 txa_service_tx(txa, ev, n);
557         }
558
559         if ((txa->loop_cnt++ & (TXA_FLUSH_THRESHOLD - 1)) == 0) {
560
561                 struct txa_service_ethdev *tdi;
562                 struct txa_service_queue_info *tqi;
563                 struct rte_eth_dev *dev;
564                 uint16_t i;
565
566                 tdi = txa->txa_ethdev;
567                 nb_tx = 0;
568
569                 RTE_ETH_FOREACH_DEV(i) {
570                         uint16_t q;
571
572                         if (i == txa->dev_count)
573                                 break;
574
575                         dev = tdi[i].dev;
576                         if (tdi[i].nb_queues == 0)
577                                 continue;
578                         for (q = 0; q < dev->data->nb_tx_queues; q++) {
579
580                                 tqi = txa_service_queue(txa, i, q);
581                                 if (unlikely(tqi == NULL || !tqi->added))
582                                         continue;
583
584                                 nb_tx += rte_eth_tx_buffer_flush(i, q,
585                                                         tqi->tx_buf);
586                         }
587                 }
588
589                 txa->stats.tx_packets += nb_tx;
590         }
591         rte_spinlock_unlock(&txa->tx_lock);
592         return 0;
593 }
594
595 static int
596 txa_service_adapter_create(uint8_t id, struct rte_eventdev *dev,
597                         struct rte_event_port_conf *port_conf)
598 {
599         struct txa_service_data *txa;
600         struct rte_event_port_conf *cb_conf;
601         int ret;
602
603         cb_conf = rte_malloc(NULL, sizeof(*cb_conf), 0);
604         if (cb_conf == NULL)
605                 return -ENOMEM;
606
607         *cb_conf = *port_conf;
608         ret = txa_service_adapter_create_ext(id, dev, txa_service_conf_cb,
609                                         cb_conf);
610         if (ret) {
611                 rte_free(cb_conf);
612                 return ret;
613         }
614
615         txa = txa_service_id_to_data(id);
616         txa->conf_free = 1;
617         return ret;
618 }
619
620 static int
621 txa_service_adapter_create_ext(uint8_t id, struct rte_eventdev *dev,
622                         rte_event_eth_tx_adapter_conf_cb conf_cb,
623                         void *conf_arg)
624 {
625         struct txa_service_data *txa;
626         int socket_id;
627         char mem_name[TXA_SERVICE_NAME_LEN];
628         int ret;
629
630         if (conf_cb == NULL)
631                 return -EINVAL;
632
633         socket_id = dev->data->socket_id;
634         snprintf(mem_name, TXA_MEM_NAME_LEN,
635                 "rte_event_eth_txa_%d",
636                 id);
637
638         ret = txa_service_data_init();
639         if (ret != 0)
640                 return ret;
641
642         txa = rte_zmalloc_socket(mem_name,
643                                 sizeof(*txa),
644                                 RTE_CACHE_LINE_SIZE, socket_id);
645         if (txa == NULL) {
646                 RTE_EDEV_LOG_ERR("failed to get mem for tx adapter");
647                 return -ENOMEM;
648         }
649
650         txa->id = id;
651         txa->eventdev_id = dev->data->dev_id;
652         txa->socket_id = socket_id;
653         strncpy(txa->mem_name, mem_name, TXA_SERVICE_NAME_LEN);
654         txa->conf_cb = conf_cb;
655         txa->conf_arg = conf_arg;
656         txa->service_id = TXA_INVALID_SERVICE_ID;
657         rte_spinlock_init(&txa->tx_lock);
658         txa_service_data_array[id] = txa;
659
660         return 0;
661 }
662
663 static int
664 txa_service_event_port_get(uint8_t id, uint8_t *port)
665 {
666         struct txa_service_data *txa;
667
668         txa = txa_service_id_to_data(id);
669         if (txa->service_id == TXA_INVALID_SERVICE_ID)
670                 return -ENODEV;
671
672         *port = txa->port_id;
673         return 0;
674 }
675
676 static int
677 txa_service_adapter_free(uint8_t id)
678 {
679         struct txa_service_data *txa;
680
681         txa = txa_service_id_to_data(id);
682         if (txa->nb_queues) {
683                 RTE_EDEV_LOG_ERR("%" PRIu16 " Tx queues not deleted",
684                                 txa->nb_queues);
685                 return -EBUSY;
686         }
687
688         if (txa->conf_free)
689                 rte_free(txa->conf_arg);
690         rte_free(txa);
691         return 0;
692 }
693
694 static int
695 txa_service_queue_add(uint8_t id,
696                 __rte_unused struct rte_eventdev *dev,
697                 const struct rte_eth_dev *eth_dev,
698                 int32_t tx_queue_id)
699 {
700         struct txa_service_data *txa;
701         struct txa_service_ethdev *tdi;
702         struct txa_service_queue_info *tqi;
703         struct rte_eth_dev_tx_buffer *tb;
704         struct txa_retry *txa_retry;
705         int ret;
706
707         txa = txa_service_id_to_data(id);
708
709         if (tx_queue_id == -1) {
710                 int nb_queues;
711                 uint16_t i, j;
712                 uint16_t *qdone;
713
714                 nb_queues = eth_dev->data->nb_tx_queues;
715                 if (txa->dev_count > eth_dev->data->port_id) {
716                         tdi = &txa->txa_ethdev[eth_dev->data->port_id];
717                         nb_queues -= tdi->nb_queues;
718                 }
719
720                 qdone = rte_zmalloc(txa->mem_name,
721                                 nb_queues * sizeof(*qdone), 0);
722                 j = 0;
723                 for (i = 0; i < nb_queues; i++) {
724                         if (txa_service_is_queue_added(txa, eth_dev, i))
725                                 continue;
726                         ret = txa_service_queue_add(id, dev, eth_dev, i);
727                         if (ret == 0)
728                                 qdone[j++] = i;
729                         else
730                                 break;
731                 }
732
733                 if (i != nb_queues) {
734                         for (i = 0; i < j; i++)
735                                 txa_service_queue_del(id, eth_dev, qdone[i]);
736                 }
737                 rte_free(qdone);
738                 return ret;
739         }
740
741         ret = txa_service_register(txa);
742         if (ret)
743                 return ret;
744
745         rte_spinlock_lock(&txa->tx_lock);
746
747         if (txa_service_is_queue_added(txa, eth_dev, tx_queue_id)) {
748                 rte_spinlock_unlock(&txa->tx_lock);
749                 return 0;
750         }
751
752         ret = txa_service_queue_array_alloc(txa, eth_dev->data->port_id);
753         if (ret)
754                 goto err_unlock;
755
756         tb = txa_service_tx_buf_alloc(txa, eth_dev);
757         if (tb == NULL)
758                 goto err_unlock;
759
760         tdi = &txa->txa_ethdev[eth_dev->data->port_id];
761         tqi = txa_service_queue(txa, eth_dev->data->port_id, tx_queue_id);
762
763         txa_retry = &tqi->txa_retry;
764         txa_retry->id = txa->id;
765         txa_retry->port_id = eth_dev->data->port_id;
766         txa_retry->tx_queue = tx_queue_id;
767
768         rte_eth_tx_buffer_init(tb, TXA_BATCH_SIZE);
769         rte_eth_tx_buffer_set_err_callback(tb,
770                 txa_service_buffer_retry, txa_retry);
771
772         tqi->tx_buf = tb;
773         tqi->added = 1;
774         tdi->nb_queues++;
775         txa->nb_queues++;
776
777 err_unlock:
778         if (txa->nb_queues == 0) {
779                 txa_service_queue_array_free(txa,
780                                         eth_dev->data->port_id);
781                 txa_service_unregister(txa);
782         }
783
784         rte_spinlock_unlock(&txa->tx_lock);
785         return 0;
786 }
787
788 static int
789 txa_service_queue_del(uint8_t id,
790                 const struct rte_eth_dev *dev,
791                 int32_t tx_queue_id)
792 {
793         struct txa_service_data *txa;
794         struct txa_service_queue_info *tqi;
795         struct rte_eth_dev_tx_buffer *tb;
796         uint16_t port_id;
797
798         if (tx_queue_id == -1) {
799                 uint16_t i;
800                 int ret = -1;
801
802                 for (i = 0; i < dev->data->nb_tx_queues; i++) {
803                         ret = txa_service_queue_del(id, dev, i);
804                         if (ret != 0)
805                                 break;
806                 }
807                 return ret;
808         }
809
810         txa = txa_service_id_to_data(id);
811         port_id = dev->data->port_id;
812
813         tqi = txa_service_queue(txa, port_id, tx_queue_id);
814         if (tqi == NULL || !tqi->added)
815                 return 0;
816
817         tb = tqi->tx_buf;
818         tqi->added = 0;
819         tqi->tx_buf = NULL;
820         rte_free(tb);
821         txa->nb_queues--;
822         txa->txa_ethdev[port_id].nb_queues--;
823
824         txa_service_queue_array_free(txa, port_id);
825         return 0;
826 }
827
828 static int
829 txa_service_id_get(uint8_t id, uint32_t *service_id)
830 {
831         struct txa_service_data *txa;
832
833         txa = txa_service_id_to_data(id);
834         if (txa->service_id == TXA_INVALID_SERVICE_ID)
835                 return -ESRCH;
836
837         if (service_id == NULL)
838                 return -EINVAL;
839
840         *service_id = txa->service_id;
841         return 0;
842 }
843
844 static int
845 txa_service_start(uint8_t id)
846 {
847         return txa_service_ctrl(id, 1);
848 }
849
850 static int
851 txa_service_stats_get(uint8_t id,
852                 struct rte_event_eth_tx_adapter_stats *stats)
853 {
854         struct txa_service_data *txa;
855
856         txa = txa_service_id_to_data(id);
857         *stats = txa->stats;
858         return 0;
859 }
860
861 static int
862 txa_service_stats_reset(uint8_t id)
863 {
864         struct txa_service_data *txa;
865
866         txa = txa_service_id_to_data(id);
867         memset(&txa->stats, 0, sizeof(txa->stats));
868         return 0;
869 }
870
871 static int
872 txa_service_stop(uint8_t id)
873 {
874         return txa_service_ctrl(id, 0);
875 }
876
877
878 int __rte_experimental
879 rte_event_eth_tx_adapter_create(uint8_t id, uint8_t dev_id,
880                                 struct rte_event_port_conf *port_conf)
881 {
882         struct rte_eventdev *dev;
883         int ret;
884
885         if (port_conf == NULL)
886                 return -EINVAL;
887
888         RTE_EVENT_ETH_TX_ADAPTER_ID_VALID_OR_ERR_RET(id, -EINVAL);
889         RTE_EVENTDEV_VALID_DEVID_OR_ERR_RET(dev_id, -EINVAL);
890
891         dev = &rte_eventdevs[dev_id];
892
893         ret = txa_init();
894         if (ret != 0)
895                 return ret;
896
897         if (txa_adapter_exist(id))
898                 return -EEXIST;
899
900         txa_dev_id_array[id] = dev_id;
901         if (txa_dev_adapter_create(id))
902                 ret = txa_dev_adapter_create(id)(id, dev);
903
904         if (ret != 0) {
905                 txa_dev_id_array[id] = TXA_INVALID_DEV_ID;
906                 return ret;
907         }
908
909         ret = txa_service_adapter_create(id, dev, port_conf);
910         if (ret != 0) {
911                 if (txa_dev_adapter_free(id))
912                         txa_dev_adapter_free(id)(id, dev);
913                 txa_dev_id_array[id] = TXA_INVALID_DEV_ID;
914                 return ret;
915         }
916
917         txa_dev_id_array[id] = dev_id;
918         return 0;
919 }
920
921 int __rte_experimental
922 rte_event_eth_tx_adapter_create_ext(uint8_t id, uint8_t dev_id,
923                                 rte_event_eth_tx_adapter_conf_cb conf_cb,
924                                 void *conf_arg)
925 {
926         struct rte_eventdev *dev;
927         int ret;
928
929         RTE_EVENT_ETH_TX_ADAPTER_ID_VALID_OR_ERR_RET(id, -EINVAL);
930         RTE_EVENTDEV_VALID_DEVID_OR_ERR_RET(dev_id, -EINVAL);
931
932         ret = txa_init();
933         if (ret != 0)
934                 return ret;
935
936         if (txa_adapter_exist(id))
937                 return -EINVAL;
938
939         dev = &rte_eventdevs[dev_id];
940
941         txa_dev_id_array[id] = dev_id;
942         if (txa_dev_adapter_create_ext(id))
943                 ret = txa_dev_adapter_create_ext(id)(id, dev);
944
945         if (ret != 0) {
946                 txa_dev_id_array[id] = TXA_INVALID_DEV_ID;
947                 return ret;
948         }
949
950         ret = txa_service_adapter_create_ext(id, dev, conf_cb, conf_arg);
951         if (ret != 0) {
952                 if (txa_dev_adapter_free(id))
953                         txa_dev_adapter_free(id)(id, dev);
954                 txa_dev_id_array[id] = TXA_INVALID_DEV_ID;
955                 return ret;
956         }
957
958         txa_dev_id_array[id] = dev_id;
959         return 0;
960 }
961
962
963 int __rte_experimental
964 rte_event_eth_tx_adapter_event_port_get(uint8_t id, uint8_t *event_port_id)
965 {
966         TXA_CHECK_OR_ERR_RET(id);
967
968         return txa_service_event_port_get(id, event_port_id);
969 }
970
971 int __rte_experimental
972 rte_event_eth_tx_adapter_free(uint8_t id)
973 {
974         int ret;
975
976         TXA_CHECK_OR_ERR_RET(id);
977
978         ret = txa_dev_adapter_free(id) ?
979                 txa_dev_adapter_free(id)(id, txa_evdev(id)) :
980                 0;
981
982         if (ret == 0)
983                 ret = txa_service_adapter_free(id);
984         txa_dev_id_array[id] = TXA_INVALID_DEV_ID;
985
986         return ret;
987 }
988
989 int __rte_experimental
990 rte_event_eth_tx_adapter_queue_add(uint8_t id,
991                                 uint16_t eth_dev_id,
992                                 int32_t queue)
993 {
994         struct rte_eth_dev *eth_dev;
995         int ret;
996         uint32_t caps;
997
998         RTE_ETH_VALID_PORTID_OR_ERR_RET(eth_dev_id, -EINVAL);
999         TXA_CHECK_OR_ERR_RET(id);
1000
1001         eth_dev = &rte_eth_devices[eth_dev_id];
1002         if (queue != -1 && (uint16_t)queue >= eth_dev->data->nb_tx_queues) {
1003                 RTE_EDEV_LOG_ERR("Invalid tx queue_id %" PRIu16,
1004                                 (uint16_t)queue);
1005                 return -EINVAL;
1006         }
1007
1008         caps = 0;
1009         if (txa_dev_caps_get(id))
1010                 txa_dev_caps_get(id)(txa_evdev(id), eth_dev, &caps);
1011
1012         if (caps & RTE_EVENT_ETH_TX_ADAPTER_CAP_INTERNAL_PORT)
1013                 ret =  txa_dev_queue_add(id) ?
1014                                         txa_dev_queue_add(id)(id,
1015                                                         txa_evdev(id),
1016                                                         eth_dev,
1017                                                         queue) : 0;
1018         else
1019                 ret = txa_service_queue_add(id, txa_evdev(id), eth_dev, queue);
1020
1021         return ret;
1022 }
1023
1024 int __rte_experimental
1025 rte_event_eth_tx_adapter_queue_del(uint8_t id,
1026                                 uint16_t eth_dev_id,
1027                                 int32_t queue)
1028 {
1029         struct rte_eth_dev *eth_dev;
1030         int ret;
1031         uint32_t caps;
1032
1033         RTE_ETH_VALID_PORTID_OR_ERR_RET(eth_dev_id, -EINVAL);
1034         TXA_CHECK_OR_ERR_RET(id);
1035
1036         eth_dev = &rte_eth_devices[eth_dev_id];
1037         if (queue != -1 && (uint16_t)queue >= eth_dev->data->nb_tx_queues) {
1038                 RTE_EDEV_LOG_ERR("Invalid tx queue_id %" PRIu16,
1039                                 (uint16_t)queue);
1040                 return -EINVAL;
1041         }
1042
1043         caps = 0;
1044
1045         if (txa_dev_caps_get(id))
1046                 txa_dev_caps_get(id)(txa_evdev(id), eth_dev, &caps);
1047
1048         if (caps & RTE_EVENT_ETH_TX_ADAPTER_CAP_INTERNAL_PORT)
1049                 ret =  txa_dev_queue_del(id) ?
1050                                         txa_dev_queue_del(id)(id, txa_evdev(id),
1051                                                         eth_dev,
1052                                                         queue) : 0;
1053         else
1054                 ret = txa_service_queue_del(id, eth_dev, queue);
1055
1056         return ret;
1057 }
1058
1059 int __rte_experimental
1060 rte_event_eth_tx_adapter_service_id_get(uint8_t id, uint32_t *service_id)
1061 {
1062         TXA_CHECK_OR_ERR_RET(id);
1063
1064         return txa_service_id_get(id, service_id);
1065 }
1066
1067 int __rte_experimental
1068 rte_event_eth_tx_adapter_start(uint8_t id)
1069 {
1070         int ret;
1071
1072         TXA_CHECK_OR_ERR_RET(id);
1073
1074         ret = txa_dev_start(id) ? txa_dev_start(id)(id, txa_evdev(id)) : 0;
1075         if (ret == 0)
1076                 ret = txa_service_start(id);
1077         return ret;
1078 }
1079
1080 int __rte_experimental
1081 rte_event_eth_tx_adapter_stats_get(uint8_t id,
1082                                 struct rte_event_eth_tx_adapter_stats *stats)
1083 {
1084         int ret;
1085
1086         TXA_CHECK_OR_ERR_RET(id);
1087
1088         if (stats == NULL)
1089                 return -EINVAL;
1090
1091         *stats = (struct rte_event_eth_tx_adapter_stats){0};
1092
1093         ret = txa_dev_stats_get(id) ?
1094                         txa_dev_stats_get(id)(id, txa_evdev(id), stats) : 0;
1095
1096         if (ret == 0 && txa_service_id_get(id, NULL) != ESRCH) {
1097                 if (txa_dev_stats_get(id)) {
1098                         struct rte_event_eth_tx_adapter_stats service_stats;
1099
1100                         ret = txa_service_stats_get(id, &service_stats);
1101                         if (ret == 0) {
1102                                 stats->tx_retry += service_stats.tx_retry;
1103                                 stats->tx_packets += service_stats.tx_packets;
1104                                 stats->tx_dropped += service_stats.tx_dropped;
1105                         }
1106                 } else
1107                         ret = txa_service_stats_get(id, stats);
1108         }
1109
1110         return ret;
1111 }
1112
1113 int __rte_experimental
1114 rte_event_eth_tx_adapter_stats_reset(uint8_t id)
1115 {
1116         int ret;
1117
1118         TXA_CHECK_OR_ERR_RET(id);
1119
1120         ret = txa_dev_stats_reset(id) ?
1121                 txa_dev_stats_reset(id)(id, txa_evdev(id)) : 0;
1122         if (ret == 0)
1123                 ret = txa_service_stats_reset(id);
1124         return ret;
1125 }
1126
1127 int __rte_experimental
1128 rte_event_eth_tx_adapter_stop(uint8_t id)
1129 {
1130         int ret;
1131
1132         TXA_CHECK_OR_ERR_RET(id);
1133
1134         ret = txa_dev_stop(id) ? txa_dev_stop(id)(id,  txa_evdev(id)) : 0;
1135         if (ret == 0)
1136                 ret = txa_service_stop(id);
1137         return ret;
1138 }