xref: /dpdk/lib/eventdev/rte_event_eth_tx_adapter.c (revision 0fbb55efa542982ec12b77dec6fa59c38b8f61a3)
199a2dd95SBruce Richardson /* SPDX-License-Identifier: BSD-3-Clause
299a2dd95SBruce Richardson  * Copyright(c) 2018 Intel Corporation.
399a2dd95SBruce Richardson  */
499a2dd95SBruce Richardson #include <rte_spinlock.h>
599a2dd95SBruce Richardson #include <rte_service_component.h>
6f9bdee26SKonstantin Ananyev #include <ethdev_driver.h>
799a2dd95SBruce Richardson 
899a2dd95SBruce Richardson #include "eventdev_pmd.h"
9f26f2ca6SPavan Nikhilesh #include "eventdev_trace.h"
1099a2dd95SBruce Richardson #include "rte_event_eth_tx_adapter.h"
1199a2dd95SBruce Richardson 
1299a2dd95SBruce Richardson #define TXA_BATCH_SIZE		32
1399a2dd95SBruce Richardson #define TXA_SERVICE_NAME_LEN	32
1499a2dd95SBruce Richardson #define TXA_MEM_NAME_LEN	32
1599a2dd95SBruce Richardson #define TXA_FLUSH_THRESHOLD	1024
1699a2dd95SBruce Richardson #define TXA_RETRY_CNT		100
1799a2dd95SBruce Richardson #define TXA_MAX_NB_TX		128
1899a2dd95SBruce Richardson #define TXA_INVALID_DEV_ID	INT32_C(-1)
1999a2dd95SBruce Richardson #define TXA_INVALID_SERVICE_ID	INT64_C(-1)
2099a2dd95SBruce Richardson 
21b2963cbdSGanapati Kundapura #define TXA_ADAPTER_ARRAY "txa_adapter_array"
22b2963cbdSGanapati Kundapura #define TXA_SERVICE_DATA_ARRAY "txa_service_data_array"
23b2963cbdSGanapati Kundapura 
2499a2dd95SBruce Richardson #define txa_evdev(id) (&rte_eventdevs[txa_dev_id_array[(id)]])
2599a2dd95SBruce Richardson 
2699a2dd95SBruce Richardson #define txa_dev_caps_get(id) txa_evdev((id))->dev_ops->eth_tx_adapter_caps_get
2799a2dd95SBruce Richardson 
2899a2dd95SBruce Richardson #define txa_dev_adapter_create(t) txa_evdev(t)->dev_ops->eth_tx_adapter_create
2999a2dd95SBruce Richardson 
3099a2dd95SBruce Richardson #define txa_dev_adapter_create_ext(t) \
3199a2dd95SBruce Richardson 				txa_evdev(t)->dev_ops->eth_tx_adapter_create
3299a2dd95SBruce Richardson 
3399a2dd95SBruce Richardson #define txa_dev_adapter_free(t) txa_evdev(t)->dev_ops->eth_tx_adapter_free
3499a2dd95SBruce Richardson 
3599a2dd95SBruce Richardson #define txa_dev_queue_add(id) txa_evdev(id)->dev_ops->eth_tx_adapter_queue_add
3699a2dd95SBruce Richardson 
3799a2dd95SBruce Richardson #define txa_dev_queue_del(t) txa_evdev(t)->dev_ops->eth_tx_adapter_queue_del
3899a2dd95SBruce Richardson 
3999a2dd95SBruce Richardson #define txa_dev_start(t) txa_evdev(t)->dev_ops->eth_tx_adapter_start
4099a2dd95SBruce Richardson 
4199a2dd95SBruce Richardson #define txa_dev_stop(t) txa_evdev(t)->dev_ops->eth_tx_adapter_stop
4299a2dd95SBruce Richardson 
4399a2dd95SBruce Richardson #define txa_dev_stats_reset(t) txa_evdev(t)->dev_ops->eth_tx_adapter_stats_reset
4499a2dd95SBruce Richardson 
4599a2dd95SBruce Richardson #define txa_dev_stats_get(t) txa_evdev(t)->dev_ops->eth_tx_adapter_stats_get
4699a2dd95SBruce Richardson 
47b2963cbdSGanapati Kundapura #define txa_dev_instance_get(id) \
48b2963cbdSGanapati Kundapura 			txa_evdev(id)->dev_ops->eth_tx_adapter_instance_get
49b2963cbdSGanapati Kundapura 
5099a2dd95SBruce Richardson #define RTE_EVENT_ETH_TX_ADAPTER_ID_VALID_OR_ERR_RET(id, retval) \
5199a2dd95SBruce Richardson do { \
5299a2dd95SBruce Richardson 	if (!txa_valid_id(id)) { \
532ab9869cSNaga Harish K S V 		RTE_EDEV_LOG_ERR("Invalid eth Tx adapter id = %d", id); \
5499a2dd95SBruce Richardson 		return retval; \
5599a2dd95SBruce Richardson 	} \
5699a2dd95SBruce Richardson } while (0)
5799a2dd95SBruce Richardson 
5899a2dd95SBruce Richardson #define TXA_CHECK_OR_ERR_RET(id) \
5999a2dd95SBruce Richardson do {\
6099a2dd95SBruce Richardson 	int ret; \
6199a2dd95SBruce Richardson 	RTE_EVENT_ETH_TX_ADAPTER_ID_VALID_OR_ERR_RET((id), -EINVAL); \
6299a2dd95SBruce Richardson 	ret = txa_init(); \
6399a2dd95SBruce Richardson 	if (ret != 0) \
6499a2dd95SBruce Richardson 		return ret; \
6599a2dd95SBruce Richardson 	if (!txa_adapter_exist((id))) \
6699a2dd95SBruce Richardson 		return -EINVAL; \
6799a2dd95SBruce Richardson } while (0)
6899a2dd95SBruce Richardson 
6999a2dd95SBruce Richardson #define TXA_CHECK_TXQ(dev, queue) \
7099a2dd95SBruce Richardson do {\
7199a2dd95SBruce Richardson 	if ((dev)->data->nb_tx_queues == 0) { \
7299a2dd95SBruce Richardson 		RTE_EDEV_LOG_ERR("No tx queues configured"); \
7399a2dd95SBruce Richardson 		return -EINVAL; \
7499a2dd95SBruce Richardson 	} \
7599a2dd95SBruce Richardson 	if ((queue) != -1 && \
7699a2dd95SBruce Richardson 		(uint16_t)(queue) >= (dev)->data->nb_tx_queues) { \
7799a2dd95SBruce Richardson 		RTE_EDEV_LOG_ERR("Invalid tx queue_id %" PRIu16, \
7899a2dd95SBruce Richardson 				(uint16_t)(queue)); \
7999a2dd95SBruce Richardson 		return -EINVAL; \
8099a2dd95SBruce Richardson 	} \
8199a2dd95SBruce Richardson } while (0)
8299a2dd95SBruce Richardson 
8399a2dd95SBruce Richardson /* Tx retry callback structure */
8499a2dd95SBruce Richardson struct txa_retry {
8599a2dd95SBruce Richardson 	/* Ethernet port id */
8699a2dd95SBruce Richardson 	uint16_t port_id;
8799a2dd95SBruce Richardson 	/* Tx queue */
8899a2dd95SBruce Richardson 	uint16_t tx_queue;
8999a2dd95SBruce Richardson 	/* Adapter ID */
9099a2dd95SBruce Richardson 	uint8_t id;
9199a2dd95SBruce Richardson };
9299a2dd95SBruce Richardson 
9399a2dd95SBruce Richardson /* Per queue structure */
9499a2dd95SBruce Richardson struct txa_service_queue_info {
9599a2dd95SBruce Richardson 	/* Queue has been added */
9699a2dd95SBruce Richardson 	uint8_t added;
9799a2dd95SBruce Richardson 	/* Retry callback argument */
9899a2dd95SBruce Richardson 	struct txa_retry txa_retry;
9999a2dd95SBruce Richardson 	/* Tx buffer */
10099a2dd95SBruce Richardson 	struct rte_eth_dev_tx_buffer *tx_buf;
10199a2dd95SBruce Richardson };
10299a2dd95SBruce Richardson 
10399a2dd95SBruce Richardson /* PMD private structure */
10499a2dd95SBruce Richardson struct txa_service_data {
10599a2dd95SBruce Richardson 	/* Max mbufs processed in any service function invocation */
10699a2dd95SBruce Richardson 	uint32_t max_nb_tx;
10799a2dd95SBruce Richardson 	/* Number of Tx queues in adapter */
10899a2dd95SBruce Richardson 	uint32_t nb_queues;
10999a2dd95SBruce Richardson 	/*  Synchronization with data path */
11099a2dd95SBruce Richardson 	rte_spinlock_t tx_lock;
11199a2dd95SBruce Richardson 	/* Event port ID */
11299a2dd95SBruce Richardson 	uint8_t port_id;
11399a2dd95SBruce Richardson 	/* Event device identifier */
11499a2dd95SBruce Richardson 	uint8_t eventdev_id;
11599a2dd95SBruce Richardson 	/* Highest port id supported + 1 */
11699a2dd95SBruce Richardson 	uint16_t dev_count;
11799a2dd95SBruce Richardson 	/* Loop count to flush Tx buffers */
11899a2dd95SBruce Richardson 	int loop_cnt;
11999a2dd95SBruce Richardson 	/* Per ethernet device structure */
12099a2dd95SBruce Richardson 	struct txa_service_ethdev *txa_ethdev;
12199a2dd95SBruce Richardson 	/* Statistics */
12299a2dd95SBruce Richardson 	struct rte_event_eth_tx_adapter_stats stats;
12399a2dd95SBruce Richardson 	/* Adapter Identifier */
12499a2dd95SBruce Richardson 	uint8_t id;
12599a2dd95SBruce Richardson 	/* Conf arg must be freed */
12699a2dd95SBruce Richardson 	uint8_t conf_free;
12799a2dd95SBruce Richardson 	/* Configuration callback */
12899a2dd95SBruce Richardson 	rte_event_eth_tx_adapter_conf_cb conf_cb;
12999a2dd95SBruce Richardson 	/* Configuration callback argument */
13099a2dd95SBruce Richardson 	void *conf_arg;
13199a2dd95SBruce Richardson 	/* socket id */
13299a2dd95SBruce Richardson 	int socket_id;
13399a2dd95SBruce Richardson 	/* Per adapter EAL service */
13499a2dd95SBruce Richardson 	int64_t service_id;
13599a2dd95SBruce Richardson 	/* Memory allocation name */
13699a2dd95SBruce Richardson 	char mem_name[TXA_MEM_NAME_LEN];
13799a2dd95SBruce Richardson } __rte_cache_aligned;
13899a2dd95SBruce Richardson 
13999a2dd95SBruce Richardson /* Per eth device structure */
14099a2dd95SBruce Richardson struct txa_service_ethdev {
14199a2dd95SBruce Richardson 	/* Pointer to ethernet device */
14299a2dd95SBruce Richardson 	struct rte_eth_dev *dev;
14399a2dd95SBruce Richardson 	/* Number of queues added */
14499a2dd95SBruce Richardson 	uint16_t nb_queues;
14599a2dd95SBruce Richardson 	/* PMD specific queue data */
14699a2dd95SBruce Richardson 	void *queues;
14799a2dd95SBruce Richardson };
14899a2dd95SBruce Richardson 
14999a2dd95SBruce Richardson /* Array of adapter instances, initialized with event device id
15099a2dd95SBruce Richardson  * when adapter is created
15199a2dd95SBruce Richardson  */
15299a2dd95SBruce Richardson static int *txa_dev_id_array;
15399a2dd95SBruce Richardson 
15499a2dd95SBruce Richardson /* Array of pointers to service implementation data */
15599a2dd95SBruce Richardson static struct txa_service_data **txa_service_data_array;
15699a2dd95SBruce Richardson 
15799a2dd95SBruce Richardson static int32_t txa_service_func(void *args);
15899a2dd95SBruce Richardson static int txa_service_adapter_create_ext(uint8_t id,
15999a2dd95SBruce Richardson 			struct rte_eventdev *dev,
16099a2dd95SBruce Richardson 			rte_event_eth_tx_adapter_conf_cb conf_cb,
16199a2dd95SBruce Richardson 			void *conf_arg);
16299a2dd95SBruce Richardson static int txa_service_queue_del(uint8_t id,
16399a2dd95SBruce Richardson 				const struct rte_eth_dev *dev,
16499a2dd95SBruce Richardson 				int32_t tx_queue_id);
16599a2dd95SBruce Richardson 
16699a2dd95SBruce Richardson static int
16799a2dd95SBruce Richardson txa_adapter_exist(uint8_t id)
16899a2dd95SBruce Richardson {
16999a2dd95SBruce Richardson 	return txa_dev_id_array[id] != TXA_INVALID_DEV_ID;
17099a2dd95SBruce Richardson }
17199a2dd95SBruce Richardson 
17299a2dd95SBruce Richardson static inline int
17399a2dd95SBruce Richardson txa_valid_id(uint8_t id)
17499a2dd95SBruce Richardson {
17599a2dd95SBruce Richardson 	return id < RTE_EVENT_ETH_TX_ADAPTER_MAX_INSTANCE;
17699a2dd95SBruce Richardson }
17799a2dd95SBruce Richardson 
17899a2dd95SBruce Richardson static void *
17999a2dd95SBruce Richardson txa_memzone_array_get(const char *name, unsigned int elt_size, int nb_elems)
18099a2dd95SBruce Richardson {
18199a2dd95SBruce Richardson 	const struct rte_memzone *mz;
18299a2dd95SBruce Richardson 	unsigned int sz;
18399a2dd95SBruce Richardson 
18499a2dd95SBruce Richardson 	sz = elt_size * nb_elems;
18599a2dd95SBruce Richardson 	sz = RTE_ALIGN(sz, RTE_CACHE_LINE_SIZE);
18699a2dd95SBruce Richardson 
18799a2dd95SBruce Richardson 	mz = rte_memzone_lookup(name);
18899a2dd95SBruce Richardson 	if (mz == NULL) {
18999a2dd95SBruce Richardson 		mz = rte_memzone_reserve_aligned(name, sz, rte_socket_id(), 0,
19099a2dd95SBruce Richardson 						 RTE_CACHE_LINE_SIZE);
19199a2dd95SBruce Richardson 		if (mz == NULL) {
19299a2dd95SBruce Richardson 			RTE_EDEV_LOG_ERR("failed to reserve memzone"
19399a2dd95SBruce Richardson 					" name = %s err = %"
19499a2dd95SBruce Richardson 					PRId32, name, rte_errno);
19599a2dd95SBruce Richardson 			return NULL;
19699a2dd95SBruce Richardson 		}
19799a2dd95SBruce Richardson 	}
19899a2dd95SBruce Richardson 
19999a2dd95SBruce Richardson 	return  mz->addr;
20099a2dd95SBruce Richardson }
20199a2dd95SBruce Richardson 
20299a2dd95SBruce Richardson static int
203b2963cbdSGanapati Kundapura txa_lookup(void)
204b2963cbdSGanapati Kundapura {
205b2963cbdSGanapati Kundapura 	const struct rte_memzone *mz;
206b2963cbdSGanapati Kundapura 
207b2963cbdSGanapati Kundapura 	if (txa_dev_id_array == NULL) {
208b2963cbdSGanapati Kundapura 		mz = rte_memzone_lookup(TXA_ADAPTER_ARRAY);
209b2963cbdSGanapati Kundapura 		if (mz == NULL)
210b2963cbdSGanapati Kundapura 			return -ENOMEM;
211b2963cbdSGanapati Kundapura 		txa_dev_id_array = mz->addr;
212b2963cbdSGanapati Kundapura 	}
213b2963cbdSGanapati Kundapura 
214b2963cbdSGanapati Kundapura 	if (txa_service_data_array == NULL) {
215b2963cbdSGanapati Kundapura 		mz = rte_memzone_lookup(TXA_SERVICE_DATA_ARRAY);
216b2963cbdSGanapati Kundapura 		if (mz == NULL)
217b2963cbdSGanapati Kundapura 			return -ENOMEM;
218b2963cbdSGanapati Kundapura 		txa_service_data_array = mz->addr;
219b2963cbdSGanapati Kundapura 	}
220b2963cbdSGanapati Kundapura 
221b2963cbdSGanapati Kundapura 	return 0;
222b2963cbdSGanapati Kundapura }
223b2963cbdSGanapati Kundapura 
224b2963cbdSGanapati Kundapura static int
22599a2dd95SBruce Richardson txa_dev_id_array_init(void)
22699a2dd95SBruce Richardson {
22799a2dd95SBruce Richardson 	if (txa_dev_id_array == NULL) {
22899a2dd95SBruce Richardson 		int i;
22999a2dd95SBruce Richardson 
230b2963cbdSGanapati Kundapura 		txa_dev_id_array = txa_memzone_array_get(TXA_ADAPTER_ARRAY,
23199a2dd95SBruce Richardson 					sizeof(int),
23299a2dd95SBruce Richardson 					RTE_EVENT_ETH_TX_ADAPTER_MAX_INSTANCE);
23399a2dd95SBruce Richardson 		if (txa_dev_id_array == NULL)
23499a2dd95SBruce Richardson 			return -ENOMEM;
23599a2dd95SBruce Richardson 
23699a2dd95SBruce Richardson 		for (i = 0; i < RTE_EVENT_ETH_TX_ADAPTER_MAX_INSTANCE; i++)
23799a2dd95SBruce Richardson 			txa_dev_id_array[i] = TXA_INVALID_DEV_ID;
23899a2dd95SBruce Richardson 	}
23999a2dd95SBruce Richardson 
24099a2dd95SBruce Richardson 	return 0;
24199a2dd95SBruce Richardson }
24299a2dd95SBruce Richardson 
24399a2dd95SBruce Richardson static int
24499a2dd95SBruce Richardson txa_init(void)
24599a2dd95SBruce Richardson {
24699a2dd95SBruce Richardson 	return txa_dev_id_array_init();
24799a2dd95SBruce Richardson }
24899a2dd95SBruce Richardson 
24999a2dd95SBruce Richardson static int
25099a2dd95SBruce Richardson txa_service_data_init(void)
25199a2dd95SBruce Richardson {
25299a2dd95SBruce Richardson 	if (txa_service_data_array == NULL) {
253b2963cbdSGanapati Kundapura 		int i;
254b2963cbdSGanapati Kundapura 
25599a2dd95SBruce Richardson 		txa_service_data_array =
256b2963cbdSGanapati Kundapura 				txa_memzone_array_get(TXA_SERVICE_DATA_ARRAY,
2573d6e9dd4SNaga Harish K S V 					sizeof(*txa_service_data_array),
25899a2dd95SBruce Richardson 					RTE_EVENT_ETH_TX_ADAPTER_MAX_INSTANCE);
25999a2dd95SBruce Richardson 		if (txa_service_data_array == NULL)
26099a2dd95SBruce Richardson 			return -ENOMEM;
261b2963cbdSGanapati Kundapura 
262b2963cbdSGanapati Kundapura 		/* Reset the txa service pointers */
263b2963cbdSGanapati Kundapura 		for (i = 0; i < RTE_EVENT_ETH_TX_ADAPTER_MAX_INSTANCE; i++)
264b2963cbdSGanapati Kundapura 			txa_service_data_array[i] = NULL;
26599a2dd95SBruce Richardson 	}
26699a2dd95SBruce Richardson 
26799a2dd95SBruce Richardson 	return 0;
26899a2dd95SBruce Richardson }
26999a2dd95SBruce Richardson 
27099a2dd95SBruce Richardson static inline struct txa_service_data *
27199a2dd95SBruce Richardson txa_service_id_to_data(uint8_t id)
27299a2dd95SBruce Richardson {
27399a2dd95SBruce Richardson 	return txa_service_data_array[id];
27499a2dd95SBruce Richardson }
27599a2dd95SBruce Richardson 
27699a2dd95SBruce Richardson static inline struct txa_service_queue_info *
27799a2dd95SBruce Richardson txa_service_queue(struct txa_service_data *txa, uint16_t port_id,
27899a2dd95SBruce Richardson 		uint16_t tx_queue_id)
27999a2dd95SBruce Richardson {
28099a2dd95SBruce Richardson 	struct txa_service_queue_info *tqi;
28199a2dd95SBruce Richardson 
28299a2dd95SBruce Richardson 	if (unlikely(txa->txa_ethdev == NULL || txa->dev_count < port_id + 1))
28399a2dd95SBruce Richardson 		return NULL;
28499a2dd95SBruce Richardson 
28599a2dd95SBruce Richardson 	tqi = txa->txa_ethdev[port_id].queues;
28699a2dd95SBruce Richardson 
28799a2dd95SBruce Richardson 	return likely(tqi != NULL) ? tqi + tx_queue_id : NULL;
28899a2dd95SBruce Richardson }
28999a2dd95SBruce Richardson 
29099a2dd95SBruce Richardson static int
29199a2dd95SBruce Richardson txa_service_conf_cb(uint8_t __rte_unused id, uint8_t dev_id,
29299a2dd95SBruce Richardson 		struct rte_event_eth_tx_adapter_conf *conf, void *arg)
29399a2dd95SBruce Richardson {
29499a2dd95SBruce Richardson 	int ret;
29599a2dd95SBruce Richardson 	struct rte_eventdev *dev;
29699a2dd95SBruce Richardson 	struct rte_event_port_conf *pc;
29799a2dd95SBruce Richardson 	struct rte_event_dev_config dev_conf;
29899a2dd95SBruce Richardson 	int started;
29999a2dd95SBruce Richardson 	uint8_t port_id;
30099a2dd95SBruce Richardson 
30199a2dd95SBruce Richardson 	pc = arg;
30299a2dd95SBruce Richardson 	dev = &rte_eventdevs[dev_id];
30399a2dd95SBruce Richardson 	dev_conf = dev->data->dev_conf;
30499a2dd95SBruce Richardson 
30599a2dd95SBruce Richardson 	started = dev->data->dev_started;
30699a2dd95SBruce Richardson 	if (started)
30799a2dd95SBruce Richardson 		rte_event_dev_stop(dev_id);
30899a2dd95SBruce Richardson 
30999a2dd95SBruce Richardson 	port_id = dev_conf.nb_event_ports;
31099a2dd95SBruce Richardson 	dev_conf.nb_event_ports += 1;
31199a2dd95SBruce Richardson 
31299a2dd95SBruce Richardson 	ret = rte_event_dev_configure(dev_id, &dev_conf);
31399a2dd95SBruce Richardson 	if (ret) {
31499a2dd95SBruce Richardson 		RTE_EDEV_LOG_ERR("failed to configure event dev %u",
31599a2dd95SBruce Richardson 						dev_id);
31699a2dd95SBruce Richardson 		if (started) {
31799a2dd95SBruce Richardson 			if (rte_event_dev_start(dev_id))
31899a2dd95SBruce Richardson 				return -EIO;
31999a2dd95SBruce Richardson 		}
32099a2dd95SBruce Richardson 		return ret;
32199a2dd95SBruce Richardson 	}
32299a2dd95SBruce Richardson 
32399a2dd95SBruce Richardson 	ret = rte_event_port_setup(dev_id, port_id, pc);
32499a2dd95SBruce Richardson 	if (ret) {
32599a2dd95SBruce Richardson 		RTE_EDEV_LOG_ERR("failed to setup event port %u\n",
32699a2dd95SBruce Richardson 					port_id);
32799a2dd95SBruce Richardson 		if (started) {
32899a2dd95SBruce Richardson 			if (rte_event_dev_start(dev_id))
32999a2dd95SBruce Richardson 				return -EIO;
33099a2dd95SBruce Richardson 		}
33199a2dd95SBruce Richardson 		return ret;
33299a2dd95SBruce Richardson 	}
33399a2dd95SBruce Richardson 
33499a2dd95SBruce Richardson 	conf->event_port_id = port_id;
33599a2dd95SBruce Richardson 	conf->max_nb_tx = TXA_MAX_NB_TX;
33699a2dd95SBruce Richardson 	if (started)
33799a2dd95SBruce Richardson 		ret = rte_event_dev_start(dev_id);
33899a2dd95SBruce Richardson 	return ret;
33999a2dd95SBruce Richardson }
34099a2dd95SBruce Richardson 
34199a2dd95SBruce Richardson static int
34299a2dd95SBruce Richardson txa_service_ethdev_alloc(struct txa_service_data *txa)
34399a2dd95SBruce Richardson {
34499a2dd95SBruce Richardson 	struct txa_service_ethdev *txa_ethdev;
34599a2dd95SBruce Richardson 	uint16_t i, dev_count;
34699a2dd95SBruce Richardson 
34799a2dd95SBruce Richardson 	dev_count = rte_eth_dev_count_avail();
34899a2dd95SBruce Richardson 	if (txa->txa_ethdev && dev_count == txa->dev_count)
34999a2dd95SBruce Richardson 		return 0;
35099a2dd95SBruce Richardson 
35199a2dd95SBruce Richardson 	txa_ethdev = rte_zmalloc_socket(txa->mem_name,
35299a2dd95SBruce Richardson 					dev_count * sizeof(*txa_ethdev),
35399a2dd95SBruce Richardson 					0,
35499a2dd95SBruce Richardson 					txa->socket_id);
35599a2dd95SBruce Richardson 	if (txa_ethdev == NULL) {
35699a2dd95SBruce Richardson 		RTE_EDEV_LOG_ERR("Failed to alloc txa::txa_ethdev ");
35799a2dd95SBruce Richardson 		return -ENOMEM;
35899a2dd95SBruce Richardson 	}
35999a2dd95SBruce Richardson 
36099a2dd95SBruce Richardson 	if (txa->dev_count)
36199a2dd95SBruce Richardson 		memcpy(txa_ethdev, txa->txa_ethdev,
36299a2dd95SBruce Richardson 			txa->dev_count * sizeof(*txa_ethdev));
36399a2dd95SBruce Richardson 
36499a2dd95SBruce Richardson 	RTE_ETH_FOREACH_DEV(i) {
36599a2dd95SBruce Richardson 		if (i == dev_count)
36699a2dd95SBruce Richardson 			break;
36799a2dd95SBruce Richardson 		txa_ethdev[i].dev = &rte_eth_devices[i];
36899a2dd95SBruce Richardson 	}
36999a2dd95SBruce Richardson 
37099a2dd95SBruce Richardson 	txa->txa_ethdev = txa_ethdev;
37199a2dd95SBruce Richardson 	txa->dev_count = dev_count;
37299a2dd95SBruce Richardson 	return 0;
37399a2dd95SBruce Richardson }
37499a2dd95SBruce Richardson 
37599a2dd95SBruce Richardson static int
37699a2dd95SBruce Richardson txa_service_queue_array_alloc(struct txa_service_data *txa,
37799a2dd95SBruce Richardson 			uint16_t port_id)
37899a2dd95SBruce Richardson {
37999a2dd95SBruce Richardson 	struct txa_service_queue_info *tqi;
38099a2dd95SBruce Richardson 	uint16_t nb_queue;
38199a2dd95SBruce Richardson 	int ret;
38299a2dd95SBruce Richardson 
38399a2dd95SBruce Richardson 	ret = txa_service_ethdev_alloc(txa);
38499a2dd95SBruce Richardson 	if (ret != 0)
38599a2dd95SBruce Richardson 		return ret;
38699a2dd95SBruce Richardson 
38799a2dd95SBruce Richardson 	if (txa->txa_ethdev[port_id].queues)
38899a2dd95SBruce Richardson 		return 0;
38999a2dd95SBruce Richardson 
39099a2dd95SBruce Richardson 	nb_queue = txa->txa_ethdev[port_id].dev->data->nb_tx_queues;
39199a2dd95SBruce Richardson 	tqi = rte_zmalloc_socket(txa->mem_name,
39299a2dd95SBruce Richardson 				nb_queue *
39399a2dd95SBruce Richardson 				sizeof(struct txa_service_queue_info), 0,
39499a2dd95SBruce Richardson 				txa->socket_id);
39599a2dd95SBruce Richardson 	if (tqi == NULL)
39699a2dd95SBruce Richardson 		return -ENOMEM;
39799a2dd95SBruce Richardson 	txa->txa_ethdev[port_id].queues = tqi;
39899a2dd95SBruce Richardson 	return 0;
39999a2dd95SBruce Richardson }
40099a2dd95SBruce Richardson 
40199a2dd95SBruce Richardson static void
40299a2dd95SBruce Richardson txa_service_queue_array_free(struct txa_service_data *txa,
40399a2dd95SBruce Richardson 			uint16_t port_id)
40499a2dd95SBruce Richardson {
40599a2dd95SBruce Richardson 	struct txa_service_ethdev *txa_ethdev;
40699a2dd95SBruce Richardson 	struct txa_service_queue_info *tqi;
40799a2dd95SBruce Richardson 
40899a2dd95SBruce Richardson 	txa_ethdev = &txa->txa_ethdev[port_id];
40999a2dd95SBruce Richardson 	if (txa->txa_ethdev == NULL || txa_ethdev->nb_queues != 0)
41099a2dd95SBruce Richardson 		return;
41199a2dd95SBruce Richardson 
41299a2dd95SBruce Richardson 	tqi = txa_ethdev->queues;
41399a2dd95SBruce Richardson 	txa_ethdev->queues = NULL;
41499a2dd95SBruce Richardson 	rte_free(tqi);
41599a2dd95SBruce Richardson 
41699a2dd95SBruce Richardson 	if (txa->nb_queues == 0) {
41799a2dd95SBruce Richardson 		rte_free(txa->txa_ethdev);
41899a2dd95SBruce Richardson 		txa->txa_ethdev = NULL;
41999a2dd95SBruce Richardson 	}
42099a2dd95SBruce Richardson }
42199a2dd95SBruce Richardson 
42299a2dd95SBruce Richardson static void
42399a2dd95SBruce Richardson txa_service_unregister(struct txa_service_data *txa)
42499a2dd95SBruce Richardson {
42599a2dd95SBruce Richardson 	if (txa->service_id != TXA_INVALID_SERVICE_ID) {
42699a2dd95SBruce Richardson 		rte_service_component_runstate_set(txa->service_id, 0);
42799a2dd95SBruce Richardson 		while (rte_service_may_be_active(txa->service_id))
42899a2dd95SBruce Richardson 			rte_pause();
42999a2dd95SBruce Richardson 		rte_service_component_unregister(txa->service_id);
43099a2dd95SBruce Richardson 	}
43199a2dd95SBruce Richardson 	txa->service_id = TXA_INVALID_SERVICE_ID;
43299a2dd95SBruce Richardson }
43399a2dd95SBruce Richardson 
43499a2dd95SBruce Richardson static int
43599a2dd95SBruce Richardson txa_service_register(struct txa_service_data *txa)
43699a2dd95SBruce Richardson {
43799a2dd95SBruce Richardson 	int ret;
43899a2dd95SBruce Richardson 	struct rte_service_spec service;
43999a2dd95SBruce Richardson 	struct rte_event_eth_tx_adapter_conf conf;
44099a2dd95SBruce Richardson 
44199a2dd95SBruce Richardson 	if (txa->service_id != TXA_INVALID_SERVICE_ID)
44299a2dd95SBruce Richardson 		return 0;
44399a2dd95SBruce Richardson 
44499a2dd95SBruce Richardson 	memset(&service, 0, sizeof(service));
44599a2dd95SBruce Richardson 	snprintf(service.name, TXA_SERVICE_NAME_LEN, "txa_%d", txa->id);
44699a2dd95SBruce Richardson 	service.socket_id = txa->socket_id;
44799a2dd95SBruce Richardson 	service.callback = txa_service_func;
44899a2dd95SBruce Richardson 	service.callback_userdata = txa;
44999a2dd95SBruce Richardson 	service.capabilities = RTE_SERVICE_CAP_MT_SAFE;
45099a2dd95SBruce Richardson 	ret = rte_service_component_register(&service,
45199a2dd95SBruce Richardson 					(uint32_t *)&txa->service_id);
45299a2dd95SBruce Richardson 	if (ret) {
45399a2dd95SBruce Richardson 		RTE_EDEV_LOG_ERR("failed to register service %s err = %"
45499a2dd95SBruce Richardson 				 PRId32, service.name, ret);
45599a2dd95SBruce Richardson 		return ret;
45699a2dd95SBruce Richardson 	}
45799a2dd95SBruce Richardson 
45899a2dd95SBruce Richardson 	ret = txa->conf_cb(txa->id, txa->eventdev_id, &conf, txa->conf_arg);
45999a2dd95SBruce Richardson 	if (ret) {
46099a2dd95SBruce Richardson 		txa_service_unregister(txa);
46199a2dd95SBruce Richardson 		return ret;
46299a2dd95SBruce Richardson 	}
46399a2dd95SBruce Richardson 
46499a2dd95SBruce Richardson 	rte_service_component_runstate_set(txa->service_id, 1);
46599a2dd95SBruce Richardson 	txa->port_id = conf.event_port_id;
46699a2dd95SBruce Richardson 	txa->max_nb_tx = conf.max_nb_tx;
46799a2dd95SBruce Richardson 	return 0;
46899a2dd95SBruce Richardson }
46999a2dd95SBruce Richardson 
47099a2dd95SBruce Richardson static struct rte_eth_dev_tx_buffer *
47199a2dd95SBruce Richardson txa_service_tx_buf_alloc(struct txa_service_data *txa,
47299a2dd95SBruce Richardson 			const struct rte_eth_dev *dev)
47399a2dd95SBruce Richardson {
47499a2dd95SBruce Richardson 	struct rte_eth_dev_tx_buffer *tb;
47599a2dd95SBruce Richardson 	uint16_t port_id;
47699a2dd95SBruce Richardson 
47799a2dd95SBruce Richardson 	port_id = dev->data->port_id;
47899a2dd95SBruce Richardson 	tb = rte_zmalloc_socket(txa->mem_name,
47999a2dd95SBruce Richardson 				RTE_ETH_TX_BUFFER_SIZE(TXA_BATCH_SIZE),
48099a2dd95SBruce Richardson 				0,
48199a2dd95SBruce Richardson 				rte_eth_dev_socket_id(port_id));
48299a2dd95SBruce Richardson 	if (tb == NULL)
48399a2dd95SBruce Richardson 		RTE_EDEV_LOG_ERR("Failed to allocate memory for tx buffer");
48499a2dd95SBruce Richardson 	return tb;
48599a2dd95SBruce Richardson }
48699a2dd95SBruce Richardson 
48799a2dd95SBruce Richardson static int
48899a2dd95SBruce Richardson txa_service_is_queue_added(struct txa_service_data *txa,
48999a2dd95SBruce Richardson 			const struct rte_eth_dev *dev,
49099a2dd95SBruce Richardson 			uint16_t tx_queue_id)
49199a2dd95SBruce Richardson {
49299a2dd95SBruce Richardson 	struct txa_service_queue_info *tqi;
49399a2dd95SBruce Richardson 
49499a2dd95SBruce Richardson 	tqi = txa_service_queue(txa, dev->data->port_id, tx_queue_id);
49599a2dd95SBruce Richardson 	return tqi && tqi->added;
49699a2dd95SBruce Richardson }
49799a2dd95SBruce Richardson 
49899a2dd95SBruce Richardson static int
49999a2dd95SBruce Richardson txa_service_ctrl(uint8_t id, int start)
50099a2dd95SBruce Richardson {
50199a2dd95SBruce Richardson 	int ret;
50299a2dd95SBruce Richardson 	struct txa_service_data *txa;
50399a2dd95SBruce Richardson 
50499a2dd95SBruce Richardson 	txa = txa_service_id_to_data(id);
5052ab9869cSNaga Harish K S V 	if (txa == NULL || txa->service_id == TXA_INVALID_SERVICE_ID)
50699a2dd95SBruce Richardson 		return 0;
50799a2dd95SBruce Richardson 
5082ab9869cSNaga Harish K S V 	rte_spinlock_lock(&txa->tx_lock);
50999a2dd95SBruce Richardson 	ret = rte_service_runstate_set(txa->service_id, start);
5102ab9869cSNaga Harish K S V 	rte_spinlock_unlock(&txa->tx_lock);
5112ab9869cSNaga Harish K S V 
51299a2dd95SBruce Richardson 	return ret;
51399a2dd95SBruce Richardson }
51499a2dd95SBruce Richardson 
51599a2dd95SBruce Richardson static void
51699a2dd95SBruce Richardson txa_service_buffer_retry(struct rte_mbuf **pkts, uint16_t unsent,
51799a2dd95SBruce Richardson 			void *userdata)
51899a2dd95SBruce Richardson {
51999a2dd95SBruce Richardson 	struct txa_retry *tr;
52099a2dd95SBruce Richardson 	struct txa_service_data *data;
52199a2dd95SBruce Richardson 	struct rte_event_eth_tx_adapter_stats *stats;
52299a2dd95SBruce Richardson 	uint16_t sent = 0;
52399a2dd95SBruce Richardson 	unsigned int retry = 0;
52499a2dd95SBruce Richardson 	uint16_t i, n;
52599a2dd95SBruce Richardson 
52699a2dd95SBruce Richardson 	tr = (struct txa_retry *)(uintptr_t)userdata;
52799a2dd95SBruce Richardson 	data = txa_service_id_to_data(tr->id);
52899a2dd95SBruce Richardson 	stats = &data->stats;
52999a2dd95SBruce Richardson 
53099a2dd95SBruce Richardson 	do {
53199a2dd95SBruce Richardson 		n = rte_eth_tx_burst(tr->port_id, tr->tx_queue,
53299a2dd95SBruce Richardson 			       &pkts[sent], unsent - sent);
53399a2dd95SBruce Richardson 
53499a2dd95SBruce Richardson 		sent += n;
53599a2dd95SBruce Richardson 	} while (sent != unsent && retry++ < TXA_RETRY_CNT);
53699a2dd95SBruce Richardson 
53799a2dd95SBruce Richardson 	for (i = sent; i < unsent; i++)
53899a2dd95SBruce Richardson 		rte_pktmbuf_free(pkts[i]);
53999a2dd95SBruce Richardson 
54099a2dd95SBruce Richardson 	stats->tx_retry += retry;
54199a2dd95SBruce Richardson 	stats->tx_packets += sent;
54299a2dd95SBruce Richardson 	stats->tx_dropped += unsent - sent;
54399a2dd95SBruce Richardson }
54499a2dd95SBruce Richardson 
54599a2dd95SBruce Richardson static uint16_t
54699a2dd95SBruce Richardson txa_process_event_vector(struct txa_service_data *txa,
54799a2dd95SBruce Richardson 			 struct rte_event_vector *vec)
54899a2dd95SBruce Richardson {
54999a2dd95SBruce Richardson 	struct txa_service_queue_info *tqi;
55099a2dd95SBruce Richardson 	uint16_t port, queue, nb_tx = 0;
55199a2dd95SBruce Richardson 	struct rte_mbuf **mbufs;
55299a2dd95SBruce Richardson 	int i;
55399a2dd95SBruce Richardson 
55499a2dd95SBruce Richardson 	mbufs = (struct rte_mbuf **)vec->mbufs;
55599a2dd95SBruce Richardson 	if (vec->attr_valid) {
55699a2dd95SBruce Richardson 		port = vec->port;
55799a2dd95SBruce Richardson 		queue = vec->queue;
55899a2dd95SBruce Richardson 		tqi = txa_service_queue(txa, port, queue);
55999a2dd95SBruce Richardson 		if (unlikely(tqi == NULL || !tqi->added)) {
560*0fbb55efSPavan Nikhilesh 			rte_pktmbuf_free_bulk(&mbufs[vec->elem_offset],
561*0fbb55efSPavan Nikhilesh 					      vec->nb_elem);
56299a2dd95SBruce Richardson 			rte_mempool_put(rte_mempool_from_obj(vec), vec);
56399a2dd95SBruce Richardson 			return 0;
56499a2dd95SBruce Richardson 		}
56599a2dd95SBruce Richardson 		for (i = 0; i < vec->nb_elem; i++) {
56699a2dd95SBruce Richardson 			nb_tx += rte_eth_tx_buffer(port, queue, tqi->tx_buf,
567*0fbb55efSPavan Nikhilesh 						   mbufs[i + vec->elem_offset]);
56899a2dd95SBruce Richardson 		}
56999a2dd95SBruce Richardson 	} else {
570*0fbb55efSPavan Nikhilesh 		for (i = vec->elem_offset; i < vec->elem_offset + vec->nb_elem;
571*0fbb55efSPavan Nikhilesh 		     i++) {
57299a2dd95SBruce Richardson 			port = mbufs[i]->port;
57399a2dd95SBruce Richardson 			queue = rte_event_eth_tx_adapter_txq_get(mbufs[i]);
57499a2dd95SBruce Richardson 			tqi = txa_service_queue(txa, port, queue);
57599a2dd95SBruce Richardson 			if (unlikely(tqi == NULL || !tqi->added)) {
57699a2dd95SBruce Richardson 				rte_pktmbuf_free(mbufs[i]);
57799a2dd95SBruce Richardson 				continue;
57899a2dd95SBruce Richardson 			}
57999a2dd95SBruce Richardson 			nb_tx += rte_eth_tx_buffer(port, queue, tqi->tx_buf,
58099a2dd95SBruce Richardson 						   mbufs[i]);
58199a2dd95SBruce Richardson 		}
58299a2dd95SBruce Richardson 	}
58399a2dd95SBruce Richardson 	rte_mempool_put(rte_mempool_from_obj(vec), vec);
58499a2dd95SBruce Richardson 
58599a2dd95SBruce Richardson 	return nb_tx;
58699a2dd95SBruce Richardson }
58799a2dd95SBruce Richardson 
58899a2dd95SBruce Richardson static void
58999a2dd95SBruce Richardson txa_service_tx(struct txa_service_data *txa, struct rte_event *ev,
59099a2dd95SBruce Richardson 	uint32_t n)
59199a2dd95SBruce Richardson {
59299a2dd95SBruce Richardson 	uint32_t i;
59399a2dd95SBruce Richardson 	uint16_t nb_tx;
59499a2dd95SBruce Richardson 	struct rte_event_eth_tx_adapter_stats *stats;
59599a2dd95SBruce Richardson 
59699a2dd95SBruce Richardson 	stats = &txa->stats;
59799a2dd95SBruce Richardson 
59899a2dd95SBruce Richardson 	nb_tx = 0;
59999a2dd95SBruce Richardson 	for (i = 0; i < n; i++) {
60099a2dd95SBruce Richardson 		uint16_t port;
60199a2dd95SBruce Richardson 		uint16_t queue;
60299a2dd95SBruce Richardson 		struct txa_service_queue_info *tqi;
60399a2dd95SBruce Richardson 
60499a2dd95SBruce Richardson 		if (!(ev[i].event_type & RTE_EVENT_TYPE_VECTOR)) {
60599a2dd95SBruce Richardson 			struct rte_mbuf *m;
60699a2dd95SBruce Richardson 
60799a2dd95SBruce Richardson 			m = ev[i].mbuf;
60899a2dd95SBruce Richardson 			port = m->port;
60999a2dd95SBruce Richardson 			queue = rte_event_eth_tx_adapter_txq_get(m);
61099a2dd95SBruce Richardson 
61199a2dd95SBruce Richardson 			tqi = txa_service_queue(txa, port, queue);
61299a2dd95SBruce Richardson 			if (unlikely(tqi == NULL || !tqi->added)) {
61399a2dd95SBruce Richardson 				rte_pktmbuf_free(m);
61499a2dd95SBruce Richardson 				continue;
61599a2dd95SBruce Richardson 			}
61699a2dd95SBruce Richardson 
61799a2dd95SBruce Richardson 			nb_tx += rte_eth_tx_buffer(port, queue, tqi->tx_buf, m);
61899a2dd95SBruce Richardson 		} else {
61999a2dd95SBruce Richardson 			nb_tx += txa_process_event_vector(txa, ev[i].vec);
62099a2dd95SBruce Richardson 		}
62199a2dd95SBruce Richardson 	}
62299a2dd95SBruce Richardson 
62399a2dd95SBruce Richardson 	stats->tx_packets += nb_tx;
62499a2dd95SBruce Richardson }
62599a2dd95SBruce Richardson 
62699a2dd95SBruce Richardson static int32_t
62799a2dd95SBruce Richardson txa_service_func(void *args)
62899a2dd95SBruce Richardson {
62999a2dd95SBruce Richardson 	struct txa_service_data *txa = args;
63099a2dd95SBruce Richardson 	uint8_t dev_id;
63199a2dd95SBruce Richardson 	uint8_t port;
63299a2dd95SBruce Richardson 	uint16_t n;
63399a2dd95SBruce Richardson 	uint32_t nb_tx, max_nb_tx;
63499a2dd95SBruce Richardson 	struct rte_event ev[TXA_BATCH_SIZE];
63599a2dd95SBruce Richardson 
63699a2dd95SBruce Richardson 	dev_id = txa->eventdev_id;
63799a2dd95SBruce Richardson 	max_nb_tx = txa->max_nb_tx;
63899a2dd95SBruce Richardson 	port = txa->port_id;
63999a2dd95SBruce Richardson 
64099a2dd95SBruce Richardson 	if (txa->nb_queues == 0)
64199a2dd95SBruce Richardson 		return 0;
64299a2dd95SBruce Richardson 
64399a2dd95SBruce Richardson 	if (!rte_spinlock_trylock(&txa->tx_lock))
64499a2dd95SBruce Richardson 		return 0;
64599a2dd95SBruce Richardson 
64699a2dd95SBruce Richardson 	for (nb_tx = 0; nb_tx < max_nb_tx; nb_tx += n) {
64799a2dd95SBruce Richardson 
64899a2dd95SBruce Richardson 		n = rte_event_dequeue_burst(dev_id, port, ev, RTE_DIM(ev), 0);
64999a2dd95SBruce Richardson 		if (!n)
65099a2dd95SBruce Richardson 			break;
65199a2dd95SBruce Richardson 		txa_service_tx(txa, ev, n);
65299a2dd95SBruce Richardson 	}
65399a2dd95SBruce Richardson 
65499a2dd95SBruce Richardson 	if ((txa->loop_cnt++ & (TXA_FLUSH_THRESHOLD - 1)) == 0) {
65599a2dd95SBruce Richardson 
65699a2dd95SBruce Richardson 		struct txa_service_ethdev *tdi;
65799a2dd95SBruce Richardson 		struct txa_service_queue_info *tqi;
65899a2dd95SBruce Richardson 		struct rte_eth_dev *dev;
65999a2dd95SBruce Richardson 		uint16_t i;
66099a2dd95SBruce Richardson 
66199a2dd95SBruce Richardson 		tdi = txa->txa_ethdev;
66299a2dd95SBruce Richardson 		nb_tx = 0;
66399a2dd95SBruce Richardson 
66499a2dd95SBruce Richardson 		RTE_ETH_FOREACH_DEV(i) {
66599a2dd95SBruce Richardson 			uint16_t q;
66699a2dd95SBruce Richardson 
66799a2dd95SBruce Richardson 			if (i == txa->dev_count)
66899a2dd95SBruce Richardson 				break;
66999a2dd95SBruce Richardson 
67099a2dd95SBruce Richardson 			dev = tdi[i].dev;
67199a2dd95SBruce Richardson 			if (tdi[i].nb_queues == 0)
67299a2dd95SBruce Richardson 				continue;
67399a2dd95SBruce Richardson 			for (q = 0; q < dev->data->nb_tx_queues; q++) {
67499a2dd95SBruce Richardson 
67599a2dd95SBruce Richardson 				tqi = txa_service_queue(txa, i, q);
67699a2dd95SBruce Richardson 				if (unlikely(tqi == NULL || !tqi->added))
67799a2dd95SBruce Richardson 					continue;
67899a2dd95SBruce Richardson 
67999a2dd95SBruce Richardson 				nb_tx += rte_eth_tx_buffer_flush(i, q,
68099a2dd95SBruce Richardson 							tqi->tx_buf);
68199a2dd95SBruce Richardson 			}
68299a2dd95SBruce Richardson 		}
68399a2dd95SBruce Richardson 
68499a2dd95SBruce Richardson 		txa->stats.tx_packets += nb_tx;
68599a2dd95SBruce Richardson 	}
68699a2dd95SBruce Richardson 	rte_spinlock_unlock(&txa->tx_lock);
68799a2dd95SBruce Richardson 	return 0;
68899a2dd95SBruce Richardson }
68999a2dd95SBruce Richardson 
69099a2dd95SBruce Richardson static int
69199a2dd95SBruce Richardson txa_service_adapter_create(uint8_t id, struct rte_eventdev *dev,
69299a2dd95SBruce Richardson 			struct rte_event_port_conf *port_conf)
69399a2dd95SBruce Richardson {
69499a2dd95SBruce Richardson 	struct txa_service_data *txa;
69599a2dd95SBruce Richardson 	struct rte_event_port_conf *cb_conf;
69699a2dd95SBruce Richardson 	int ret;
69799a2dd95SBruce Richardson 
69899a2dd95SBruce Richardson 	cb_conf = rte_malloc(NULL, sizeof(*cb_conf), 0);
69999a2dd95SBruce Richardson 	if (cb_conf == NULL)
70099a2dd95SBruce Richardson 		return -ENOMEM;
70199a2dd95SBruce Richardson 
70299a2dd95SBruce Richardson 	*cb_conf = *port_conf;
70399a2dd95SBruce Richardson 	ret = txa_service_adapter_create_ext(id, dev, txa_service_conf_cb,
70499a2dd95SBruce Richardson 					cb_conf);
70599a2dd95SBruce Richardson 	if (ret) {
70699a2dd95SBruce Richardson 		rte_free(cb_conf);
70799a2dd95SBruce Richardson 		return ret;
70899a2dd95SBruce Richardson 	}
70999a2dd95SBruce Richardson 
71099a2dd95SBruce Richardson 	txa = txa_service_id_to_data(id);
71199a2dd95SBruce Richardson 	txa->conf_free = 1;
71299a2dd95SBruce Richardson 	return ret;
71399a2dd95SBruce Richardson }
71499a2dd95SBruce Richardson 
71599a2dd95SBruce Richardson static int
71699a2dd95SBruce Richardson txa_service_adapter_create_ext(uint8_t id, struct rte_eventdev *dev,
71799a2dd95SBruce Richardson 			rte_event_eth_tx_adapter_conf_cb conf_cb,
71899a2dd95SBruce Richardson 			void *conf_arg)
71999a2dd95SBruce Richardson {
72099a2dd95SBruce Richardson 	struct txa_service_data *txa;
72199a2dd95SBruce Richardson 	int socket_id;
72299a2dd95SBruce Richardson 	char mem_name[TXA_SERVICE_NAME_LEN];
72399a2dd95SBruce Richardson 	int ret;
72499a2dd95SBruce Richardson 
72599a2dd95SBruce Richardson 	if (conf_cb == NULL)
72699a2dd95SBruce Richardson 		return -EINVAL;
72799a2dd95SBruce Richardson 
72899a2dd95SBruce Richardson 	socket_id = dev->data->socket_id;
72999a2dd95SBruce Richardson 	snprintf(mem_name, TXA_MEM_NAME_LEN,
73099a2dd95SBruce Richardson 		"rte_event_eth_txa_%d",
73199a2dd95SBruce Richardson 		id);
73299a2dd95SBruce Richardson 
73399a2dd95SBruce Richardson 	ret = txa_service_data_init();
73499a2dd95SBruce Richardson 	if (ret != 0)
73599a2dd95SBruce Richardson 		return ret;
73699a2dd95SBruce Richardson 
73799a2dd95SBruce Richardson 	txa = rte_zmalloc_socket(mem_name,
73899a2dd95SBruce Richardson 				sizeof(*txa),
73999a2dd95SBruce Richardson 				RTE_CACHE_LINE_SIZE, socket_id);
74099a2dd95SBruce Richardson 	if (txa == NULL) {
74199a2dd95SBruce Richardson 		RTE_EDEV_LOG_ERR("failed to get mem for tx adapter");
74299a2dd95SBruce Richardson 		return -ENOMEM;
74399a2dd95SBruce Richardson 	}
74499a2dd95SBruce Richardson 
74599a2dd95SBruce Richardson 	txa->id = id;
74699a2dd95SBruce Richardson 	txa->eventdev_id = dev->data->dev_id;
74799a2dd95SBruce Richardson 	txa->socket_id = socket_id;
74899a2dd95SBruce Richardson 	strncpy(txa->mem_name, mem_name, TXA_SERVICE_NAME_LEN);
74999a2dd95SBruce Richardson 	txa->conf_cb = conf_cb;
75099a2dd95SBruce Richardson 	txa->conf_arg = conf_arg;
75199a2dd95SBruce Richardson 	txa->service_id = TXA_INVALID_SERVICE_ID;
75299a2dd95SBruce Richardson 	rte_spinlock_init(&txa->tx_lock);
75399a2dd95SBruce Richardson 	txa_service_data_array[id] = txa;
75499a2dd95SBruce Richardson 
75599a2dd95SBruce Richardson 	return 0;
75699a2dd95SBruce Richardson }
75799a2dd95SBruce Richardson 
75899a2dd95SBruce Richardson static int
75999a2dd95SBruce Richardson txa_service_event_port_get(uint8_t id, uint8_t *port)
76099a2dd95SBruce Richardson {
76199a2dd95SBruce Richardson 	struct txa_service_data *txa;
76299a2dd95SBruce Richardson 
76399a2dd95SBruce Richardson 	txa = txa_service_id_to_data(id);
76499a2dd95SBruce Richardson 	if (txa->service_id == TXA_INVALID_SERVICE_ID)
76599a2dd95SBruce Richardson 		return -ENODEV;
76699a2dd95SBruce Richardson 
76799a2dd95SBruce Richardson 	*port = txa->port_id;
76899a2dd95SBruce Richardson 	return 0;
76999a2dd95SBruce Richardson }
77099a2dd95SBruce Richardson 
77199a2dd95SBruce Richardson static int
77299a2dd95SBruce Richardson txa_service_adapter_free(uint8_t id)
77399a2dd95SBruce Richardson {
77499a2dd95SBruce Richardson 	struct txa_service_data *txa;
77599a2dd95SBruce Richardson 
77699a2dd95SBruce Richardson 	txa = txa_service_id_to_data(id);
77799a2dd95SBruce Richardson 	if (txa->nb_queues) {
77899a2dd95SBruce Richardson 		RTE_EDEV_LOG_ERR("%" PRIu16 " Tx queues not deleted",
77999a2dd95SBruce Richardson 				txa->nb_queues);
78099a2dd95SBruce Richardson 		return -EBUSY;
78199a2dd95SBruce Richardson 	}
78299a2dd95SBruce Richardson 
78399a2dd95SBruce Richardson 	if (txa->conf_free)
78499a2dd95SBruce Richardson 		rte_free(txa->conf_arg);
78599a2dd95SBruce Richardson 	rte_free(txa);
78699a2dd95SBruce Richardson 	return 0;
78799a2dd95SBruce Richardson }
78899a2dd95SBruce Richardson 
78999a2dd95SBruce Richardson static int
79099a2dd95SBruce Richardson txa_service_queue_add(uint8_t id,
79199a2dd95SBruce Richardson 		__rte_unused struct rte_eventdev *dev,
79299a2dd95SBruce Richardson 		const struct rte_eth_dev *eth_dev,
79399a2dd95SBruce Richardson 		int32_t tx_queue_id)
79499a2dd95SBruce Richardson {
79599a2dd95SBruce Richardson 	struct txa_service_data *txa;
79699a2dd95SBruce Richardson 	struct txa_service_ethdev *tdi;
79799a2dd95SBruce Richardson 	struct txa_service_queue_info *tqi;
79899a2dd95SBruce Richardson 	struct rte_eth_dev_tx_buffer *tb;
79999a2dd95SBruce Richardson 	struct txa_retry *txa_retry;
80099a2dd95SBruce Richardson 	int ret = 0;
80199a2dd95SBruce Richardson 
80299a2dd95SBruce Richardson 	txa = txa_service_id_to_data(id);
80399a2dd95SBruce Richardson 
80499a2dd95SBruce Richardson 	if (tx_queue_id == -1) {
80599a2dd95SBruce Richardson 		int nb_queues;
80699a2dd95SBruce Richardson 		uint16_t i, j;
80799a2dd95SBruce Richardson 		uint16_t *qdone;
80899a2dd95SBruce Richardson 
80999a2dd95SBruce Richardson 		nb_queues = eth_dev->data->nb_tx_queues;
81099a2dd95SBruce Richardson 		if (txa->dev_count > eth_dev->data->port_id) {
81199a2dd95SBruce Richardson 			tdi = &txa->txa_ethdev[eth_dev->data->port_id];
81299a2dd95SBruce Richardson 			nb_queues -= tdi->nb_queues;
81399a2dd95SBruce Richardson 		}
81499a2dd95SBruce Richardson 
81599a2dd95SBruce Richardson 		qdone = rte_zmalloc(txa->mem_name,
81699a2dd95SBruce Richardson 				nb_queues * sizeof(*qdone), 0);
81799a2dd95SBruce Richardson 		if (qdone == NULL)
81899a2dd95SBruce Richardson 			return -ENOMEM;
81999a2dd95SBruce Richardson 		j = 0;
82099a2dd95SBruce Richardson 		for (i = 0; i < nb_queues; i++) {
82199a2dd95SBruce Richardson 			if (txa_service_is_queue_added(txa, eth_dev, i))
82299a2dd95SBruce Richardson 				continue;
82399a2dd95SBruce Richardson 			ret = txa_service_queue_add(id, dev, eth_dev, i);
82499a2dd95SBruce Richardson 			if (ret == 0)
82599a2dd95SBruce Richardson 				qdone[j++] = i;
82699a2dd95SBruce Richardson 			else
82799a2dd95SBruce Richardson 				break;
82899a2dd95SBruce Richardson 		}
82999a2dd95SBruce Richardson 
83099a2dd95SBruce Richardson 		if (i != nb_queues) {
83199a2dd95SBruce Richardson 			for (i = 0; i < j; i++)
83299a2dd95SBruce Richardson 				txa_service_queue_del(id, eth_dev, qdone[i]);
83399a2dd95SBruce Richardson 		}
83499a2dd95SBruce Richardson 		rte_free(qdone);
83599a2dd95SBruce Richardson 		return ret;
83699a2dd95SBruce Richardson 	}
83799a2dd95SBruce Richardson 
83899a2dd95SBruce Richardson 	ret = txa_service_register(txa);
83999a2dd95SBruce Richardson 	if (ret)
84099a2dd95SBruce Richardson 		return ret;
84199a2dd95SBruce Richardson 
84299a2dd95SBruce Richardson 	rte_spinlock_lock(&txa->tx_lock);
84399a2dd95SBruce Richardson 
844bd0a32d1SNaga Harish K S V 	if (txa_service_is_queue_added(txa, eth_dev, tx_queue_id))
845bd0a32d1SNaga Harish K S V 		goto ret_unlock;
84699a2dd95SBruce Richardson 
84799a2dd95SBruce Richardson 	ret = txa_service_queue_array_alloc(txa, eth_dev->data->port_id);
84899a2dd95SBruce Richardson 	if (ret)
84999a2dd95SBruce Richardson 		goto err_unlock;
85099a2dd95SBruce Richardson 
85199a2dd95SBruce Richardson 	tb = txa_service_tx_buf_alloc(txa, eth_dev);
85299a2dd95SBruce Richardson 	if (tb == NULL)
85399a2dd95SBruce Richardson 		goto err_unlock;
85499a2dd95SBruce Richardson 
85599a2dd95SBruce Richardson 	tdi = &txa->txa_ethdev[eth_dev->data->port_id];
85699a2dd95SBruce Richardson 	tqi = txa_service_queue(txa, eth_dev->data->port_id, tx_queue_id);
857bd0a32d1SNaga Harish K S V 	if (tqi == NULL)
858bd0a32d1SNaga Harish K S V 		goto err_unlock;
85999a2dd95SBruce Richardson 
86099a2dd95SBruce Richardson 	txa_retry = &tqi->txa_retry;
86199a2dd95SBruce Richardson 	txa_retry->id = txa->id;
86299a2dd95SBruce Richardson 	txa_retry->port_id = eth_dev->data->port_id;
86399a2dd95SBruce Richardson 	txa_retry->tx_queue = tx_queue_id;
86499a2dd95SBruce Richardson 
86599a2dd95SBruce Richardson 	rte_eth_tx_buffer_init(tb, TXA_BATCH_SIZE);
86699a2dd95SBruce Richardson 	rte_eth_tx_buffer_set_err_callback(tb,
86799a2dd95SBruce Richardson 		txa_service_buffer_retry, txa_retry);
86899a2dd95SBruce Richardson 
86999a2dd95SBruce Richardson 	tqi->tx_buf = tb;
87099a2dd95SBruce Richardson 	tqi->added = 1;
87199a2dd95SBruce Richardson 	tdi->nb_queues++;
87299a2dd95SBruce Richardson 	txa->nb_queues++;
87399a2dd95SBruce Richardson 
874bd0a32d1SNaga Harish K S V ret_unlock:
875bd0a32d1SNaga Harish K S V 	rte_spinlock_unlock(&txa->tx_lock);
876bd0a32d1SNaga Harish K S V 	return 0;
877bd0a32d1SNaga Harish K S V 
87899a2dd95SBruce Richardson err_unlock:
87999a2dd95SBruce Richardson 	if (txa->nb_queues == 0) {
88099a2dd95SBruce Richardson 		txa_service_queue_array_free(txa,
88199a2dd95SBruce Richardson 					eth_dev->data->port_id);
88299a2dd95SBruce Richardson 		txa_service_unregister(txa);
88399a2dd95SBruce Richardson 	}
88499a2dd95SBruce Richardson 
88599a2dd95SBruce Richardson 	rte_spinlock_unlock(&txa->tx_lock);
886bd0a32d1SNaga Harish K S V 	return -1;
88799a2dd95SBruce Richardson }
88899a2dd95SBruce Richardson 
88999a2dd95SBruce Richardson static int
89099a2dd95SBruce Richardson txa_service_queue_del(uint8_t id,
89199a2dd95SBruce Richardson 		const struct rte_eth_dev *dev,
89299a2dd95SBruce Richardson 		int32_t tx_queue_id)
89399a2dd95SBruce Richardson {
89499a2dd95SBruce Richardson 	struct txa_service_data *txa;
89599a2dd95SBruce Richardson 	struct txa_service_queue_info *tqi;
89699a2dd95SBruce Richardson 	struct rte_eth_dev_tx_buffer *tb;
89799a2dd95SBruce Richardson 	uint16_t port_id;
89899a2dd95SBruce Richardson 
89999a2dd95SBruce Richardson 	txa = txa_service_id_to_data(id);
90099a2dd95SBruce Richardson 	port_id = dev->data->port_id;
90199a2dd95SBruce Richardson 
90299a2dd95SBruce Richardson 	if (tx_queue_id == -1) {
90399a2dd95SBruce Richardson 		uint16_t i, q, nb_queues;
90499a2dd95SBruce Richardson 		int ret = 0;
90599a2dd95SBruce Richardson 
906741b499eSNaga Harish K S V 		nb_queues = txa->txa_ethdev[port_id].nb_queues;
90799a2dd95SBruce Richardson 		if (nb_queues == 0)
90899a2dd95SBruce Richardson 			return 0;
90999a2dd95SBruce Richardson 
91099a2dd95SBruce Richardson 		i = 0;
91199a2dd95SBruce Richardson 		q = 0;
91299a2dd95SBruce Richardson 		tqi = txa->txa_ethdev[port_id].queues;
91399a2dd95SBruce Richardson 
91499a2dd95SBruce Richardson 		while (i < nb_queues) {
91599a2dd95SBruce Richardson 
91699a2dd95SBruce Richardson 			if (tqi[q].added) {
91799a2dd95SBruce Richardson 				ret = txa_service_queue_del(id, dev, q);
91899a2dd95SBruce Richardson 				if (ret != 0)
91999a2dd95SBruce Richardson 					break;
92099a2dd95SBruce Richardson 			}
92199a2dd95SBruce Richardson 			i++;
92299a2dd95SBruce Richardson 			q++;
92399a2dd95SBruce Richardson 		}
92499a2dd95SBruce Richardson 		return ret;
92599a2dd95SBruce Richardson 	}
92699a2dd95SBruce Richardson 
92799a2dd95SBruce Richardson 	txa = txa_service_id_to_data(id);
92899a2dd95SBruce Richardson 
929881d4b4dSNaga Harish K S V 	rte_spinlock_lock(&txa->tx_lock);
93099a2dd95SBruce Richardson 	tqi = txa_service_queue(txa, port_id, tx_queue_id);
93199a2dd95SBruce Richardson 	if (tqi == NULL || !tqi->added)
932881d4b4dSNaga Harish K S V 		goto ret_unlock;
93399a2dd95SBruce Richardson 
93499a2dd95SBruce Richardson 	tb = tqi->tx_buf;
93599a2dd95SBruce Richardson 	tqi->added = 0;
93699a2dd95SBruce Richardson 	tqi->tx_buf = NULL;
93799a2dd95SBruce Richardson 	rte_free(tb);
93899a2dd95SBruce Richardson 	txa->nb_queues--;
93999a2dd95SBruce Richardson 	txa->txa_ethdev[port_id].nb_queues--;
94099a2dd95SBruce Richardson 
94199a2dd95SBruce Richardson 	txa_service_queue_array_free(txa, port_id);
942881d4b4dSNaga Harish K S V 
943881d4b4dSNaga Harish K S V ret_unlock:
944881d4b4dSNaga Harish K S V 	rte_spinlock_unlock(&txa->tx_lock);
94599a2dd95SBruce Richardson 	return 0;
94699a2dd95SBruce Richardson }
94799a2dd95SBruce Richardson 
94899a2dd95SBruce Richardson static int
94999a2dd95SBruce Richardson txa_service_id_get(uint8_t id, uint32_t *service_id)
95099a2dd95SBruce Richardson {
95199a2dd95SBruce Richardson 	struct txa_service_data *txa;
95299a2dd95SBruce Richardson 
95399a2dd95SBruce Richardson 	txa = txa_service_id_to_data(id);
95499a2dd95SBruce Richardson 	if (txa->service_id == TXA_INVALID_SERVICE_ID)
95599a2dd95SBruce Richardson 		return -ESRCH;
95699a2dd95SBruce Richardson 
95799a2dd95SBruce Richardson 	if (service_id == NULL)
95899a2dd95SBruce Richardson 		return -EINVAL;
95999a2dd95SBruce Richardson 
96099a2dd95SBruce Richardson 	*service_id = txa->service_id;
96199a2dd95SBruce Richardson 	return 0;
96299a2dd95SBruce Richardson }
96399a2dd95SBruce Richardson 
96499a2dd95SBruce Richardson static int
96599a2dd95SBruce Richardson txa_service_start(uint8_t id)
96699a2dd95SBruce Richardson {
96799a2dd95SBruce Richardson 	return txa_service_ctrl(id, 1);
96899a2dd95SBruce Richardson }
96999a2dd95SBruce Richardson 
97099a2dd95SBruce Richardson static int
97199a2dd95SBruce Richardson txa_service_stats_get(uint8_t id,
97299a2dd95SBruce Richardson 		struct rte_event_eth_tx_adapter_stats *stats)
97399a2dd95SBruce Richardson {
97499a2dd95SBruce Richardson 	struct txa_service_data *txa;
97599a2dd95SBruce Richardson 
97699a2dd95SBruce Richardson 	txa = txa_service_id_to_data(id);
97799a2dd95SBruce Richardson 	*stats = txa->stats;
97899a2dd95SBruce Richardson 	return 0;
97999a2dd95SBruce Richardson }
98099a2dd95SBruce Richardson 
98199a2dd95SBruce Richardson static int
98299a2dd95SBruce Richardson txa_service_stats_reset(uint8_t id)
98399a2dd95SBruce Richardson {
98499a2dd95SBruce Richardson 	struct txa_service_data *txa;
98599a2dd95SBruce Richardson 
98699a2dd95SBruce Richardson 	txa = txa_service_id_to_data(id);
98799a2dd95SBruce Richardson 	memset(&txa->stats, 0, sizeof(txa->stats));
98899a2dd95SBruce Richardson 	return 0;
98999a2dd95SBruce Richardson }
99099a2dd95SBruce Richardson 
99199a2dd95SBruce Richardson static int
99299a2dd95SBruce Richardson txa_service_stop(uint8_t id)
99399a2dd95SBruce Richardson {
99499a2dd95SBruce Richardson 	return txa_service_ctrl(id, 0);
99599a2dd95SBruce Richardson }
99699a2dd95SBruce Richardson 
99799a2dd95SBruce Richardson 
99899a2dd95SBruce Richardson int
99999a2dd95SBruce Richardson rte_event_eth_tx_adapter_create(uint8_t id, uint8_t dev_id,
100099a2dd95SBruce Richardson 				struct rte_event_port_conf *port_conf)
100199a2dd95SBruce Richardson {
100299a2dd95SBruce Richardson 	struct rte_eventdev *dev;
100399a2dd95SBruce Richardson 	int ret;
100499a2dd95SBruce Richardson 
100599a2dd95SBruce Richardson 	if (port_conf == NULL)
100699a2dd95SBruce Richardson 		return -EINVAL;
100799a2dd95SBruce Richardson 
100899a2dd95SBruce Richardson 	RTE_EVENT_ETH_TX_ADAPTER_ID_VALID_OR_ERR_RET(id, -EINVAL);
100999a2dd95SBruce Richardson 	RTE_EVENTDEV_VALID_DEVID_OR_ERR_RET(dev_id, -EINVAL);
101099a2dd95SBruce Richardson 
101199a2dd95SBruce Richardson 	dev = &rte_eventdevs[dev_id];
101299a2dd95SBruce Richardson 
101399a2dd95SBruce Richardson 	ret = txa_init();
101499a2dd95SBruce Richardson 	if (ret != 0)
101599a2dd95SBruce Richardson 		return ret;
101699a2dd95SBruce Richardson 
101799a2dd95SBruce Richardson 	if (txa_adapter_exist(id))
101899a2dd95SBruce Richardson 		return -EEXIST;
101999a2dd95SBruce Richardson 
102099a2dd95SBruce Richardson 	txa_dev_id_array[id] = dev_id;
102199a2dd95SBruce Richardson 	if (txa_dev_adapter_create(id))
102299a2dd95SBruce Richardson 		ret = txa_dev_adapter_create(id)(id, dev);
102399a2dd95SBruce Richardson 
102499a2dd95SBruce Richardson 	if (ret != 0) {
102599a2dd95SBruce Richardson 		txa_dev_id_array[id] = TXA_INVALID_DEV_ID;
102699a2dd95SBruce Richardson 		return ret;
102799a2dd95SBruce Richardson 	}
102899a2dd95SBruce Richardson 
102999a2dd95SBruce Richardson 	ret = txa_service_adapter_create(id, dev, port_conf);
103099a2dd95SBruce Richardson 	if (ret != 0) {
103199a2dd95SBruce Richardson 		if (txa_dev_adapter_free(id))
103299a2dd95SBruce Richardson 			txa_dev_adapter_free(id)(id, dev);
103399a2dd95SBruce Richardson 		txa_dev_id_array[id] = TXA_INVALID_DEV_ID;
103499a2dd95SBruce Richardson 		return ret;
103599a2dd95SBruce Richardson 	}
103699a2dd95SBruce Richardson 	rte_eventdev_trace_eth_tx_adapter_create(id, dev_id, NULL, port_conf,
103799a2dd95SBruce Richardson 		ret);
103899a2dd95SBruce Richardson 	txa_dev_id_array[id] = dev_id;
103999a2dd95SBruce Richardson 	return 0;
104099a2dd95SBruce Richardson }
104199a2dd95SBruce Richardson 
104299a2dd95SBruce Richardson int
104399a2dd95SBruce Richardson rte_event_eth_tx_adapter_create_ext(uint8_t id, uint8_t dev_id,
104499a2dd95SBruce Richardson 				rte_event_eth_tx_adapter_conf_cb conf_cb,
104599a2dd95SBruce Richardson 				void *conf_arg)
104699a2dd95SBruce Richardson {
104799a2dd95SBruce Richardson 	struct rte_eventdev *dev;
104899a2dd95SBruce Richardson 	int ret;
104999a2dd95SBruce Richardson 
105099a2dd95SBruce Richardson 	RTE_EVENT_ETH_TX_ADAPTER_ID_VALID_OR_ERR_RET(id, -EINVAL);
105199a2dd95SBruce Richardson 	RTE_EVENTDEV_VALID_DEVID_OR_ERR_RET(dev_id, -EINVAL);
105299a2dd95SBruce Richardson 
105399a2dd95SBruce Richardson 	ret = txa_init();
105499a2dd95SBruce Richardson 	if (ret != 0)
105599a2dd95SBruce Richardson 		return ret;
105699a2dd95SBruce Richardson 
105799a2dd95SBruce Richardson 	if (txa_adapter_exist(id))
105899a2dd95SBruce Richardson 		return -EINVAL;
105999a2dd95SBruce Richardson 
106099a2dd95SBruce Richardson 	dev = &rte_eventdevs[dev_id];
106199a2dd95SBruce Richardson 
106299a2dd95SBruce Richardson 	txa_dev_id_array[id] = dev_id;
106399a2dd95SBruce Richardson 	if (txa_dev_adapter_create_ext(id))
106499a2dd95SBruce Richardson 		ret = txa_dev_adapter_create_ext(id)(id, dev);
106599a2dd95SBruce Richardson 
106699a2dd95SBruce Richardson 	if (ret != 0) {
106799a2dd95SBruce Richardson 		txa_dev_id_array[id] = TXA_INVALID_DEV_ID;
106899a2dd95SBruce Richardson 		return ret;
106999a2dd95SBruce Richardson 	}
107099a2dd95SBruce Richardson 
107199a2dd95SBruce Richardson 	ret = txa_service_adapter_create_ext(id, dev, conf_cb, conf_arg);
107299a2dd95SBruce Richardson 	if (ret != 0) {
107399a2dd95SBruce Richardson 		if (txa_dev_adapter_free(id))
107499a2dd95SBruce Richardson 			txa_dev_adapter_free(id)(id, dev);
107599a2dd95SBruce Richardson 		txa_dev_id_array[id] = TXA_INVALID_DEV_ID;
107699a2dd95SBruce Richardson 		return ret;
107799a2dd95SBruce Richardson 	}
107899a2dd95SBruce Richardson 
107999a2dd95SBruce Richardson 	rte_eventdev_trace_eth_tx_adapter_create(id, dev_id, conf_cb, conf_arg,
108099a2dd95SBruce Richardson 		ret);
108199a2dd95SBruce Richardson 	txa_dev_id_array[id] = dev_id;
108299a2dd95SBruce Richardson 	return 0;
108399a2dd95SBruce Richardson }
108499a2dd95SBruce Richardson 
108599a2dd95SBruce Richardson 
108699a2dd95SBruce Richardson int
108799a2dd95SBruce Richardson rte_event_eth_tx_adapter_event_port_get(uint8_t id, uint8_t *event_port_id)
108899a2dd95SBruce Richardson {
108999a2dd95SBruce Richardson 	TXA_CHECK_OR_ERR_RET(id);
109099a2dd95SBruce Richardson 
109199a2dd95SBruce Richardson 	return txa_service_event_port_get(id, event_port_id);
109299a2dd95SBruce Richardson }
109399a2dd95SBruce Richardson 
109499a2dd95SBruce Richardson int
109599a2dd95SBruce Richardson rte_event_eth_tx_adapter_free(uint8_t id)
109699a2dd95SBruce Richardson {
109799a2dd95SBruce Richardson 	int ret;
109899a2dd95SBruce Richardson 
109999a2dd95SBruce Richardson 	TXA_CHECK_OR_ERR_RET(id);
110099a2dd95SBruce Richardson 
110199a2dd95SBruce Richardson 	ret = txa_dev_adapter_free(id) ?
110299a2dd95SBruce Richardson 		txa_dev_adapter_free(id)(id, txa_evdev(id)) :
110399a2dd95SBruce Richardson 		0;
110499a2dd95SBruce Richardson 
110599a2dd95SBruce Richardson 	if (ret == 0)
110699a2dd95SBruce Richardson 		ret = txa_service_adapter_free(id);
110799a2dd95SBruce Richardson 	txa_dev_id_array[id] = TXA_INVALID_DEV_ID;
110899a2dd95SBruce Richardson 
110999a2dd95SBruce Richardson 	rte_eventdev_trace_eth_tx_adapter_free(id, ret);
111099a2dd95SBruce Richardson 	return ret;
111199a2dd95SBruce Richardson }
111299a2dd95SBruce Richardson 
111399a2dd95SBruce Richardson int
111499a2dd95SBruce Richardson rte_event_eth_tx_adapter_queue_add(uint8_t id,
111599a2dd95SBruce Richardson 				uint16_t eth_dev_id,
111699a2dd95SBruce Richardson 				int32_t queue)
111799a2dd95SBruce Richardson {
111899a2dd95SBruce Richardson 	struct rte_eth_dev *eth_dev;
111999a2dd95SBruce Richardson 	int ret;
112099a2dd95SBruce Richardson 	uint32_t caps;
112199a2dd95SBruce Richardson 
112299a2dd95SBruce Richardson 	RTE_ETH_VALID_PORTID_OR_ERR_RET(eth_dev_id, -EINVAL);
112399a2dd95SBruce Richardson 	TXA_CHECK_OR_ERR_RET(id);
112499a2dd95SBruce Richardson 
112599a2dd95SBruce Richardson 	eth_dev = &rte_eth_devices[eth_dev_id];
112699a2dd95SBruce Richardson 	TXA_CHECK_TXQ(eth_dev, queue);
112799a2dd95SBruce Richardson 
112899a2dd95SBruce Richardson 	caps = 0;
112999a2dd95SBruce Richardson 	if (txa_dev_caps_get(id))
113099a2dd95SBruce Richardson 		txa_dev_caps_get(id)(txa_evdev(id), eth_dev, &caps);
113199a2dd95SBruce Richardson 
113299a2dd95SBruce Richardson 	if (caps & RTE_EVENT_ETH_TX_ADAPTER_CAP_INTERNAL_PORT)
113399a2dd95SBruce Richardson 		ret =  txa_dev_queue_add(id) ?
113499a2dd95SBruce Richardson 					txa_dev_queue_add(id)(id,
113599a2dd95SBruce Richardson 							txa_evdev(id),
113699a2dd95SBruce Richardson 							eth_dev,
113799a2dd95SBruce Richardson 							queue) : 0;
113899a2dd95SBruce Richardson 	else
113999a2dd95SBruce Richardson 		ret = txa_service_queue_add(id, txa_evdev(id), eth_dev, queue);
114099a2dd95SBruce Richardson 
114199a2dd95SBruce Richardson 	rte_eventdev_trace_eth_tx_adapter_queue_add(id, eth_dev_id, queue,
114299a2dd95SBruce Richardson 		ret);
114399a2dd95SBruce Richardson 	return ret;
114499a2dd95SBruce Richardson }
114599a2dd95SBruce Richardson 
114699a2dd95SBruce Richardson int
114799a2dd95SBruce Richardson rte_event_eth_tx_adapter_queue_del(uint8_t id,
114899a2dd95SBruce Richardson 				uint16_t eth_dev_id,
114999a2dd95SBruce Richardson 				int32_t queue)
115099a2dd95SBruce Richardson {
115199a2dd95SBruce Richardson 	struct rte_eth_dev *eth_dev;
115299a2dd95SBruce Richardson 	int ret;
115399a2dd95SBruce Richardson 	uint32_t caps;
115499a2dd95SBruce Richardson 
115599a2dd95SBruce Richardson 	RTE_ETH_VALID_PORTID_OR_ERR_RET(eth_dev_id, -EINVAL);
115699a2dd95SBruce Richardson 	TXA_CHECK_OR_ERR_RET(id);
115799a2dd95SBruce Richardson 
115899a2dd95SBruce Richardson 	eth_dev = &rte_eth_devices[eth_dev_id];
115999a2dd95SBruce Richardson 
116099a2dd95SBruce Richardson 	caps = 0;
116199a2dd95SBruce Richardson 
116299a2dd95SBruce Richardson 	if (txa_dev_caps_get(id))
116399a2dd95SBruce Richardson 		txa_dev_caps_get(id)(txa_evdev(id), eth_dev, &caps);
116499a2dd95SBruce Richardson 
116599a2dd95SBruce Richardson 	if (caps & RTE_EVENT_ETH_TX_ADAPTER_CAP_INTERNAL_PORT)
116699a2dd95SBruce Richardson 		ret =  txa_dev_queue_del(id) ?
116799a2dd95SBruce Richardson 					txa_dev_queue_del(id)(id, txa_evdev(id),
116899a2dd95SBruce Richardson 							eth_dev,
116999a2dd95SBruce Richardson 							queue) : 0;
117099a2dd95SBruce Richardson 	else
117199a2dd95SBruce Richardson 		ret = txa_service_queue_del(id, eth_dev, queue);
117299a2dd95SBruce Richardson 
117399a2dd95SBruce Richardson 	rte_eventdev_trace_eth_tx_adapter_queue_del(id, eth_dev_id, queue,
117499a2dd95SBruce Richardson 		ret);
117599a2dd95SBruce Richardson 	return ret;
117699a2dd95SBruce Richardson }
117799a2dd95SBruce Richardson 
117899a2dd95SBruce Richardson int
117999a2dd95SBruce Richardson rte_event_eth_tx_adapter_service_id_get(uint8_t id, uint32_t *service_id)
118099a2dd95SBruce Richardson {
118199a2dd95SBruce Richardson 	TXA_CHECK_OR_ERR_RET(id);
118299a2dd95SBruce Richardson 
118399a2dd95SBruce Richardson 	return txa_service_id_get(id, service_id);
118499a2dd95SBruce Richardson }
118599a2dd95SBruce Richardson 
118699a2dd95SBruce Richardson int
118799a2dd95SBruce Richardson rte_event_eth_tx_adapter_start(uint8_t id)
118899a2dd95SBruce Richardson {
118999a2dd95SBruce Richardson 	int ret;
119099a2dd95SBruce Richardson 
119199a2dd95SBruce Richardson 	TXA_CHECK_OR_ERR_RET(id);
119299a2dd95SBruce Richardson 
119399a2dd95SBruce Richardson 	ret = txa_dev_start(id) ? txa_dev_start(id)(id, txa_evdev(id)) : 0;
119499a2dd95SBruce Richardson 	if (ret == 0)
119599a2dd95SBruce Richardson 		ret = txa_service_start(id);
119699a2dd95SBruce Richardson 	rte_eventdev_trace_eth_tx_adapter_start(id, ret);
119799a2dd95SBruce Richardson 	return ret;
119899a2dd95SBruce Richardson }
119999a2dd95SBruce Richardson 
120099a2dd95SBruce Richardson int
120199a2dd95SBruce Richardson rte_event_eth_tx_adapter_stats_get(uint8_t id,
120299a2dd95SBruce Richardson 				struct rte_event_eth_tx_adapter_stats *stats)
120399a2dd95SBruce Richardson {
120499a2dd95SBruce Richardson 	int ret;
120599a2dd95SBruce Richardson 
120699a2dd95SBruce Richardson 	TXA_CHECK_OR_ERR_RET(id);
120799a2dd95SBruce Richardson 
120899a2dd95SBruce Richardson 	if (stats == NULL)
120999a2dd95SBruce Richardson 		return -EINVAL;
121099a2dd95SBruce Richardson 
121199a2dd95SBruce Richardson 	*stats = (struct rte_event_eth_tx_adapter_stats){0};
121299a2dd95SBruce Richardson 
121399a2dd95SBruce Richardson 	ret = txa_dev_stats_get(id) ?
121499a2dd95SBruce Richardson 			txa_dev_stats_get(id)(id, txa_evdev(id), stats) : 0;
121599a2dd95SBruce Richardson 
121699a2dd95SBruce Richardson 	if (ret == 0 && txa_service_id_get(id, NULL) != ESRCH) {
121799a2dd95SBruce Richardson 		if (txa_dev_stats_get(id)) {
121899a2dd95SBruce Richardson 			struct rte_event_eth_tx_adapter_stats service_stats;
121999a2dd95SBruce Richardson 
122099a2dd95SBruce Richardson 			ret = txa_service_stats_get(id, &service_stats);
122199a2dd95SBruce Richardson 			if (ret == 0) {
122299a2dd95SBruce Richardson 				stats->tx_retry += service_stats.tx_retry;
122399a2dd95SBruce Richardson 				stats->tx_packets += service_stats.tx_packets;
122499a2dd95SBruce Richardson 				stats->tx_dropped += service_stats.tx_dropped;
122599a2dd95SBruce Richardson 			}
122699a2dd95SBruce Richardson 		} else
122799a2dd95SBruce Richardson 			ret = txa_service_stats_get(id, stats);
122899a2dd95SBruce Richardson 	}
122999a2dd95SBruce Richardson 
123099a2dd95SBruce Richardson 	return ret;
123199a2dd95SBruce Richardson }
123299a2dd95SBruce Richardson 
123399a2dd95SBruce Richardson int
123499a2dd95SBruce Richardson rte_event_eth_tx_adapter_stats_reset(uint8_t id)
123599a2dd95SBruce Richardson {
123699a2dd95SBruce Richardson 	int ret;
123799a2dd95SBruce Richardson 
123899a2dd95SBruce Richardson 	TXA_CHECK_OR_ERR_RET(id);
123999a2dd95SBruce Richardson 
124099a2dd95SBruce Richardson 	ret = txa_dev_stats_reset(id) ?
124199a2dd95SBruce Richardson 		txa_dev_stats_reset(id)(id, txa_evdev(id)) : 0;
124299a2dd95SBruce Richardson 	if (ret == 0)
124399a2dd95SBruce Richardson 		ret = txa_service_stats_reset(id);
124499a2dd95SBruce Richardson 	return ret;
124599a2dd95SBruce Richardson }
124699a2dd95SBruce Richardson 
124799a2dd95SBruce Richardson int
124899a2dd95SBruce Richardson rte_event_eth_tx_adapter_stop(uint8_t id)
124999a2dd95SBruce Richardson {
125099a2dd95SBruce Richardson 	int ret;
125199a2dd95SBruce Richardson 
125299a2dd95SBruce Richardson 	TXA_CHECK_OR_ERR_RET(id);
125399a2dd95SBruce Richardson 
125499a2dd95SBruce Richardson 	ret = txa_dev_stop(id) ? txa_dev_stop(id)(id,  txa_evdev(id)) : 0;
125599a2dd95SBruce Richardson 	if (ret == 0)
125699a2dd95SBruce Richardson 		ret = txa_service_stop(id);
125799a2dd95SBruce Richardson 	rte_eventdev_trace_eth_tx_adapter_stop(id, ret);
125899a2dd95SBruce Richardson 	return ret;
125999a2dd95SBruce Richardson }
1260b2963cbdSGanapati Kundapura 
1261b2963cbdSGanapati Kundapura int
1262b2963cbdSGanapati Kundapura rte_event_eth_tx_adapter_instance_get(uint16_t eth_dev_id,
1263b2963cbdSGanapati Kundapura 				      uint16_t tx_queue_id,
1264b2963cbdSGanapati Kundapura 				      uint8_t *txa_inst_id)
1265b2963cbdSGanapati Kundapura {
1266b2963cbdSGanapati Kundapura 	uint8_t id;
1267b2963cbdSGanapati Kundapura 	int ret = -EINVAL;
1268b2963cbdSGanapati Kundapura 	uint32_t caps;
1269b2963cbdSGanapati Kundapura 	struct txa_service_data *txa;
1270b2963cbdSGanapati Kundapura 
1271b2963cbdSGanapati Kundapura 	if (txa_lookup())
1272b2963cbdSGanapati Kundapura 		return -ENOMEM;
1273b2963cbdSGanapati Kundapura 
1274b2963cbdSGanapati Kundapura 	if (eth_dev_id >= rte_eth_dev_count_avail()) {
1275b2963cbdSGanapati Kundapura 		RTE_EDEV_LOG_ERR("Invalid ethernet port id %u", eth_dev_id);
1276b2963cbdSGanapati Kundapura 		return -EINVAL;
1277b2963cbdSGanapati Kundapura 	}
1278b2963cbdSGanapati Kundapura 
1279b2963cbdSGanapati Kundapura 	if (tx_queue_id >= rte_eth_devices[eth_dev_id].data->nb_tx_queues) {
1280b2963cbdSGanapati Kundapura 		RTE_EDEV_LOG_ERR("Invalid tx queue id %u", tx_queue_id);
1281b2963cbdSGanapati Kundapura 		return -EINVAL;
1282b2963cbdSGanapati Kundapura 	}
1283b2963cbdSGanapati Kundapura 
1284b2963cbdSGanapati Kundapura 	if (txa_inst_id == NULL) {
1285b2963cbdSGanapati Kundapura 		RTE_EDEV_LOG_ERR("txa_instance_id cannot be NULL");
1286b2963cbdSGanapati Kundapura 		return -EINVAL;
1287b2963cbdSGanapati Kundapura 	}
1288b2963cbdSGanapati Kundapura 
1289b2963cbdSGanapati Kundapura 	/* Iterate through all Tx adapter instances */
1290b2963cbdSGanapati Kundapura 	for (id = 0; id < RTE_EVENT_ETH_TX_ADAPTER_MAX_INSTANCE; id++) {
1291b2963cbdSGanapati Kundapura 		txa = txa_service_id_to_data(id);
1292b2963cbdSGanapati Kundapura 		if (!txa)
1293b2963cbdSGanapati Kundapura 			continue;
1294b2963cbdSGanapati Kundapura 
1295b2963cbdSGanapati Kundapura 		caps = 0;
1296b2963cbdSGanapati Kundapura 		if (rte_event_eth_tx_adapter_caps_get(txa->eventdev_id,
1297b2963cbdSGanapati Kundapura 						      eth_dev_id,
1298b2963cbdSGanapati Kundapura 						      &caps))
1299b2963cbdSGanapati Kundapura 			continue;
1300b2963cbdSGanapati Kundapura 
1301b2963cbdSGanapati Kundapura 		if (caps & RTE_EVENT_ETH_TX_ADAPTER_CAP_INTERNAL_PORT) {
1302b2963cbdSGanapati Kundapura 			ret = txa_dev_instance_get(id) ?
1303b2963cbdSGanapati Kundapura 					txa_dev_instance_get(id)(eth_dev_id,
1304b2963cbdSGanapati Kundapura 								 tx_queue_id,
1305b2963cbdSGanapati Kundapura 								 txa_inst_id)
1306b2963cbdSGanapati Kundapura 							: -EINVAL;
1307b2963cbdSGanapati Kundapura 			if (ret == 0)
1308b2963cbdSGanapati Kundapura 				return ret;
1309b2963cbdSGanapati Kundapura 		} else {
1310b2963cbdSGanapati Kundapura 			struct rte_eth_dev *eth_dev;
1311b2963cbdSGanapati Kundapura 
1312b2963cbdSGanapati Kundapura 			eth_dev = &rte_eth_devices[eth_dev_id];
1313b2963cbdSGanapati Kundapura 
1314b2963cbdSGanapati Kundapura 			if (txa_service_is_queue_added(txa, eth_dev,
1315b2963cbdSGanapati Kundapura 						       tx_queue_id)) {
1316b2963cbdSGanapati Kundapura 				*txa_inst_id = txa->id;
1317b2963cbdSGanapati Kundapura 				return 0;
1318b2963cbdSGanapati Kundapura 			}
1319b2963cbdSGanapati Kundapura 		}
1320b2963cbdSGanapati Kundapura 	}
1321b2963cbdSGanapati Kundapura 
1322b2963cbdSGanapati Kundapura 	return -EINVAL;
1323b2963cbdSGanapati Kundapura }
1324