xref: /dpdk/lib/port/rte_port_eventdev.c (revision ae67895b507bb6af22263c79ba0d5c374b396485)
199a2dd95SBruce Richardson /* SPDX-License-Identifier: BSD-3-Clause
299a2dd95SBruce Richardson  * Copyright(c) 2019 Intel Corporation
399a2dd95SBruce Richardson  */
499a2dd95SBruce Richardson 
599a2dd95SBruce Richardson #include <string.h>
699a2dd95SBruce Richardson #include <stdint.h>
799a2dd95SBruce Richardson 
899a2dd95SBruce Richardson #include <rte_mbuf.h>
999a2dd95SBruce Richardson #include <rte_malloc.h>
1099a2dd95SBruce Richardson 
1199a2dd95SBruce Richardson #include "rte_port_eventdev.h"
1299a2dd95SBruce Richardson 
13*ae67895bSDavid Marchand #include "port_log.h"
14*ae67895bSDavid Marchand 
1599a2dd95SBruce Richardson /*
1699a2dd95SBruce Richardson  * Port EVENTDEV Reader
1799a2dd95SBruce Richardson  */
1899a2dd95SBruce Richardson #ifdef RTE_PORT_STATS_COLLECT
1999a2dd95SBruce Richardson 
2099a2dd95SBruce Richardson #define RTE_PORT_EVENTDEV_READER_STATS_PKTS_IN_ADD(port, val) \
2199a2dd95SBruce Richardson 	do {port->stats.n_pkts_in += val;} while (0)
2299a2dd95SBruce Richardson #define RTE_PORT_EVENTDEV_READER_STATS_PKTS_DROP_ADD(port, val) \
2399a2dd95SBruce Richardson 	do {port->stats.n_pkts_drop += val;} while (0)
2499a2dd95SBruce Richardson 
2599a2dd95SBruce Richardson #else
2699a2dd95SBruce Richardson 
2799a2dd95SBruce Richardson #define RTE_PORT_EVENTDEV_READER_STATS_PKTS_IN_ADD(port, val)
2899a2dd95SBruce Richardson #define RTE_PORT_EVENTDEV_READER_STATS_PKTS_DROP_ADD(port, val)
2999a2dd95SBruce Richardson 
3099a2dd95SBruce Richardson #endif
3199a2dd95SBruce Richardson 
3299a2dd95SBruce Richardson struct rte_port_eventdev_reader {
3399a2dd95SBruce Richardson 	struct rte_port_in_stats stats;
3499a2dd95SBruce Richardson 
3599a2dd95SBruce Richardson 	uint8_t  eventdev_id;
3699a2dd95SBruce Richardson 	uint16_t port_id;
3799a2dd95SBruce Richardson 
3899a2dd95SBruce Richardson 	struct rte_event ev[RTE_PORT_IN_BURST_SIZE_MAX];
3999a2dd95SBruce Richardson };
4099a2dd95SBruce Richardson 
4199a2dd95SBruce Richardson static void *
rte_port_eventdev_reader_create(void * params,int socket_id)4299a2dd95SBruce Richardson rte_port_eventdev_reader_create(void *params, int socket_id)
4399a2dd95SBruce Richardson {
4499a2dd95SBruce Richardson 	struct rte_port_eventdev_reader_params *conf =
4599a2dd95SBruce Richardson 			params;
4699a2dd95SBruce Richardson 	struct rte_port_eventdev_reader *port;
4799a2dd95SBruce Richardson 
4899a2dd95SBruce Richardson 	/* Check input parameters */
4999a2dd95SBruce Richardson 	if (conf == NULL) {
50*ae67895bSDavid Marchand 		PORT_LOG(ERR, "%s: params is NULL", __func__);
5199a2dd95SBruce Richardson 		return NULL;
5299a2dd95SBruce Richardson 	}
5399a2dd95SBruce Richardson 
5499a2dd95SBruce Richardson 	/* Memory allocation */
5599a2dd95SBruce Richardson 	port = rte_zmalloc_socket("PORT", sizeof(*port),
5699a2dd95SBruce Richardson 		RTE_CACHE_LINE_SIZE, socket_id);
5799a2dd95SBruce Richardson 	if (port == NULL) {
58*ae67895bSDavid Marchand 		PORT_LOG(ERR, "%s: Failed to allocate port", __func__);
5999a2dd95SBruce Richardson 		return NULL;
6099a2dd95SBruce Richardson 	}
6199a2dd95SBruce Richardson 
6299a2dd95SBruce Richardson 	/* Initialization */
6399a2dd95SBruce Richardson 	port->eventdev_id = conf->eventdev_id;
6499a2dd95SBruce Richardson 	port->port_id = conf->port_id;
6599a2dd95SBruce Richardson 
6699a2dd95SBruce Richardson 	return port;
6799a2dd95SBruce Richardson }
6899a2dd95SBruce Richardson 
6999a2dd95SBruce Richardson static int
rte_port_eventdev_reader_rx(void * port,struct rte_mbuf ** pkts,uint32_t n_pkts)7099a2dd95SBruce Richardson rte_port_eventdev_reader_rx(void *port, struct rte_mbuf **pkts, uint32_t n_pkts)
7199a2dd95SBruce Richardson {
7299a2dd95SBruce Richardson 	struct rte_port_eventdev_reader *p = port;
7399a2dd95SBruce Richardson 	uint16_t rx_evts_cnt, i;
7499a2dd95SBruce Richardson 
7599a2dd95SBruce Richardson 	rx_evts_cnt = rte_event_dequeue_burst(p->eventdev_id, p->port_id,
7699a2dd95SBruce Richardson 			p->ev, n_pkts, 0);
7799a2dd95SBruce Richardson 
7899a2dd95SBruce Richardson 	for (i = 0; i < rx_evts_cnt; i++)
7999a2dd95SBruce Richardson 		pkts[i] = p->ev[i].mbuf;
8099a2dd95SBruce Richardson 
8199a2dd95SBruce Richardson 	RTE_PORT_EVENTDEV_READER_STATS_PKTS_IN_ADD(p, rx_evts_cnt);
8299a2dd95SBruce Richardson 
8399a2dd95SBruce Richardson 	return rx_evts_cnt;
8499a2dd95SBruce Richardson }
8599a2dd95SBruce Richardson 
8699a2dd95SBruce Richardson static int
rte_port_eventdev_reader_free(void * port)8799a2dd95SBruce Richardson rte_port_eventdev_reader_free(void *port)
8899a2dd95SBruce Richardson {
8999a2dd95SBruce Richardson 	if (port == NULL) {
90*ae67895bSDavid Marchand 		PORT_LOG(ERR, "%s: port is NULL", __func__);
9199a2dd95SBruce Richardson 		return -EINVAL;
9299a2dd95SBruce Richardson 	}
9399a2dd95SBruce Richardson 
9499a2dd95SBruce Richardson 	rte_free(port);
9599a2dd95SBruce Richardson 
9699a2dd95SBruce Richardson 	return 0;
9799a2dd95SBruce Richardson }
9899a2dd95SBruce Richardson 
rte_port_eventdev_reader_stats_read(void * port,struct rte_port_in_stats * stats,int clear)9999a2dd95SBruce Richardson static int rte_port_eventdev_reader_stats_read(void *port,
10099a2dd95SBruce Richardson 	struct rte_port_in_stats *stats, int clear)
10199a2dd95SBruce Richardson {
10299a2dd95SBruce Richardson 	struct rte_port_eventdev_reader *p =
10399a2dd95SBruce Richardson 			port;
10499a2dd95SBruce Richardson 
10599a2dd95SBruce Richardson 	if (stats != NULL)
10699a2dd95SBruce Richardson 		memcpy(stats, &p->stats, sizeof(p->stats));
10799a2dd95SBruce Richardson 
10899a2dd95SBruce Richardson 	if (clear)
10999a2dd95SBruce Richardson 		memset(&p->stats, 0, sizeof(p->stats));
11099a2dd95SBruce Richardson 
11199a2dd95SBruce Richardson 	return 0;
11299a2dd95SBruce Richardson }
11399a2dd95SBruce Richardson 
11499a2dd95SBruce Richardson /*
11599a2dd95SBruce Richardson  * Port EVENTDEV Writer
11699a2dd95SBruce Richardson  */
11799a2dd95SBruce Richardson #ifdef RTE_PORT_STATS_COLLECT
11899a2dd95SBruce Richardson 
11999a2dd95SBruce Richardson #define RTE_PORT_EVENTDEV_WRITER_STATS_PKTS_IN_ADD(port, val) \
12099a2dd95SBruce Richardson 	do {port->stats.n_pkts_in += val;} while (0)
12199a2dd95SBruce Richardson #define RTE_PORT_EVENTDEV_WRITER_STATS_PKTS_DROP_ADD(port, val) \
12299a2dd95SBruce Richardson 	do {port->stats.n_pkts_drop += val;} while (0)
12399a2dd95SBruce Richardson 
12499a2dd95SBruce Richardson #else
12599a2dd95SBruce Richardson 
12699a2dd95SBruce Richardson #define RTE_PORT_EVENTDEV_WRITER_STATS_PKTS_IN_ADD(port, val)
12799a2dd95SBruce Richardson #define RTE_PORT_EVENTDEV_WRITER_STATS_PKTS_DROP_ADD(port, val)
12899a2dd95SBruce Richardson 
12999a2dd95SBruce Richardson #endif
13099a2dd95SBruce Richardson 
13199a2dd95SBruce Richardson struct rte_port_eventdev_writer {
13299a2dd95SBruce Richardson 	struct rte_port_out_stats stats;
13399a2dd95SBruce Richardson 
13499a2dd95SBruce Richardson 	struct rte_event ev[2 * RTE_PORT_IN_BURST_SIZE_MAX];
13599a2dd95SBruce Richardson 
13699a2dd95SBruce Richardson 	uint32_t enq_burst_sz;
13799a2dd95SBruce Richardson 	uint32_t enq_buf_count;
13899a2dd95SBruce Richardson 	uint64_t bsz_mask;
13999a2dd95SBruce Richardson 
14099a2dd95SBruce Richardson 	uint8_t eventdev_id;
14199a2dd95SBruce Richardson 	uint8_t port_id;
14299a2dd95SBruce Richardson 	uint8_t queue_id;
14399a2dd95SBruce Richardson 	uint8_t sched_type;
14499a2dd95SBruce Richardson 	uint8_t evt_op;
14599a2dd95SBruce Richardson };
14699a2dd95SBruce Richardson 
14799a2dd95SBruce Richardson static void *
rte_port_eventdev_writer_create(void * params,int socket_id)14899a2dd95SBruce Richardson rte_port_eventdev_writer_create(void *params, int socket_id)
14999a2dd95SBruce Richardson {
15099a2dd95SBruce Richardson 	struct rte_port_eventdev_writer_params *conf =
15199a2dd95SBruce Richardson 			params;
15299a2dd95SBruce Richardson 	struct rte_port_eventdev_writer *port;
15399a2dd95SBruce Richardson 	unsigned int i;
15499a2dd95SBruce Richardson 
15599a2dd95SBruce Richardson 	/* Check input parameters */
15699a2dd95SBruce Richardson 	if ((conf == NULL) ||
15799a2dd95SBruce Richardson 		(conf->enq_burst_sz == 0) ||
15899a2dd95SBruce Richardson 		(conf->enq_burst_sz > RTE_PORT_IN_BURST_SIZE_MAX) ||
15999a2dd95SBruce Richardson 		(!rte_is_power_of_2(conf->enq_burst_sz))) {
160*ae67895bSDavid Marchand 		PORT_LOG(ERR, "%s: Invalid input parameters", __func__);
16199a2dd95SBruce Richardson 		return NULL;
16299a2dd95SBruce Richardson 	}
16399a2dd95SBruce Richardson 
16499a2dd95SBruce Richardson 	/* Memory allocation */
16599a2dd95SBruce Richardson 	port = rte_zmalloc_socket("PORT", sizeof(*port),
16699a2dd95SBruce Richardson 		RTE_CACHE_LINE_SIZE, socket_id);
16799a2dd95SBruce Richardson 	if (port == NULL) {
168*ae67895bSDavid Marchand 		PORT_LOG(ERR, "%s: Failed to allocate port", __func__);
16999a2dd95SBruce Richardson 		return NULL;
17099a2dd95SBruce Richardson 	}
17199a2dd95SBruce Richardson 
17299a2dd95SBruce Richardson 	/* Initialization */
17399a2dd95SBruce Richardson 	port->enq_burst_sz = conf->enq_burst_sz;
17499a2dd95SBruce Richardson 	port->enq_buf_count = 0;
17599a2dd95SBruce Richardson 	port->bsz_mask = 1LLU << (conf->enq_burst_sz - 1);
17699a2dd95SBruce Richardson 
17799a2dd95SBruce Richardson 	port->eventdev_id = conf->eventdev_id;
17899a2dd95SBruce Richardson 	port->port_id = conf->port_id;
17999a2dd95SBruce Richardson 	port->queue_id = conf->queue_id;
18099a2dd95SBruce Richardson 	port->sched_type = conf->sched_type;
18199a2dd95SBruce Richardson 	port->evt_op = conf->evt_op;
18299a2dd95SBruce Richardson 	memset(&port->ev, 0, sizeof(port->ev));
18399a2dd95SBruce Richardson 
18499a2dd95SBruce Richardson 	for (i = 0; i < RTE_DIM(port->ev); i++) {
18599a2dd95SBruce Richardson 		port->ev[i].queue_id = port->queue_id;
18699a2dd95SBruce Richardson 		port->ev[i].sched_type = port->sched_type;
18799a2dd95SBruce Richardson 		port->ev[i].op = port->evt_op;
18899a2dd95SBruce Richardson 	}
18999a2dd95SBruce Richardson 
19099a2dd95SBruce Richardson 	return port;
19199a2dd95SBruce Richardson }
19299a2dd95SBruce Richardson 
19399a2dd95SBruce Richardson static inline void
send_burst(struct rte_port_eventdev_writer * p)19499a2dd95SBruce Richardson send_burst(struct rte_port_eventdev_writer *p)
19599a2dd95SBruce Richardson {
19699a2dd95SBruce Richardson 	uint32_t nb_enq;
19799a2dd95SBruce Richardson 
19899a2dd95SBruce Richardson 	nb_enq = rte_event_enqueue_burst(p->eventdev_id, p->port_id,
19999a2dd95SBruce Richardson 			p->ev, p->enq_buf_count);
20099a2dd95SBruce Richardson 
20199a2dd95SBruce Richardson 	RTE_PORT_EVENTDEV_WRITER_STATS_PKTS_DROP_ADD(p, p->enq_buf_count -
20299a2dd95SBruce Richardson 			nb_enq);
20399a2dd95SBruce Richardson 
20499a2dd95SBruce Richardson 	for (; nb_enq < p->enq_buf_count; nb_enq++)
20599a2dd95SBruce Richardson 		rte_pktmbuf_free(p->ev[nb_enq].mbuf);
20699a2dd95SBruce Richardson 
20799a2dd95SBruce Richardson 	p->enq_buf_count = 0;
20899a2dd95SBruce Richardson }
20999a2dd95SBruce Richardson 
21099a2dd95SBruce Richardson static int
rte_port_eventdev_writer_tx(void * port,struct rte_mbuf * pkt)21199a2dd95SBruce Richardson rte_port_eventdev_writer_tx(void *port, struct rte_mbuf *pkt)
21299a2dd95SBruce Richardson {
21399a2dd95SBruce Richardson 	struct rte_port_eventdev_writer *p = port;
21499a2dd95SBruce Richardson 
21599a2dd95SBruce Richardson 	p->ev[p->enq_buf_count++].mbuf  = pkt;
21699a2dd95SBruce Richardson 	RTE_PORT_EVENTDEV_WRITER_STATS_PKTS_IN_ADD(p, 1);
21799a2dd95SBruce Richardson 	if (p->enq_buf_count >= p->enq_burst_sz)
21899a2dd95SBruce Richardson 		send_burst(p);
21999a2dd95SBruce Richardson 
22099a2dd95SBruce Richardson 	return 0;
22199a2dd95SBruce Richardson }
22299a2dd95SBruce Richardson 
22399a2dd95SBruce Richardson static int
rte_port_eventdev_writer_tx_bulk(void * port,struct rte_mbuf ** pkts,uint64_t pkts_mask)22499a2dd95SBruce Richardson rte_port_eventdev_writer_tx_bulk(void *port,
22599a2dd95SBruce Richardson 	struct rte_mbuf **pkts,
22699a2dd95SBruce Richardson 	uint64_t pkts_mask)
22799a2dd95SBruce Richardson {
22899a2dd95SBruce Richardson 	struct rte_port_eventdev_writer *p =
22999a2dd95SBruce Richardson 			port;
23099a2dd95SBruce Richardson 	uint64_t bsz_mask = p->bsz_mask;
23199a2dd95SBruce Richardson 	uint32_t enq_buf_count = p->enq_buf_count;
23299a2dd95SBruce Richardson 	uint64_t expr = (pkts_mask & (pkts_mask + 1)) |
23399a2dd95SBruce Richardson 					((pkts_mask & bsz_mask) ^ bsz_mask);
23499a2dd95SBruce Richardson 
23599a2dd95SBruce Richardson 	if (expr == 0) {
2363d4e27fdSDavid Marchand 		uint64_t n_pkts = rte_popcount64(pkts_mask);
23799a2dd95SBruce Richardson 		uint32_t i, n_enq_ok;
23899a2dd95SBruce Richardson 
23999a2dd95SBruce Richardson 		if (enq_buf_count)
24099a2dd95SBruce Richardson 			send_burst(p);
24199a2dd95SBruce Richardson 
24299a2dd95SBruce Richardson 		RTE_PORT_EVENTDEV_WRITER_STATS_PKTS_IN_ADD(p, n_pkts);
24399a2dd95SBruce Richardson 
24499a2dd95SBruce Richardson 		struct rte_event events[2 * RTE_PORT_IN_BURST_SIZE_MAX] = {};
24599a2dd95SBruce Richardson 		for (i = 0; i < n_pkts; i++) {
24699a2dd95SBruce Richardson 			events[i].mbuf = pkts[i];
24799a2dd95SBruce Richardson 			events[i].queue_id = p->queue_id;
24899a2dd95SBruce Richardson 			events[i].sched_type = p->sched_type;
24999a2dd95SBruce Richardson 			events[i].op = p->evt_op;
25099a2dd95SBruce Richardson 		}
25199a2dd95SBruce Richardson 
25299a2dd95SBruce Richardson 		n_enq_ok = rte_event_enqueue_burst(p->eventdev_id, p->port_id,
25399a2dd95SBruce Richardson 				events, n_pkts);
25499a2dd95SBruce Richardson 
25599a2dd95SBruce Richardson 		RTE_PORT_EVENTDEV_WRITER_STATS_PKTS_DROP_ADD(p,
25699a2dd95SBruce Richardson 				n_pkts - n_enq_ok);
25799a2dd95SBruce Richardson 		for (; n_enq_ok < n_pkts; n_enq_ok++)
25899a2dd95SBruce Richardson 			rte_pktmbuf_free(pkts[n_enq_ok]);
25999a2dd95SBruce Richardson 
26099a2dd95SBruce Richardson 	} else {
26199a2dd95SBruce Richardson 		for (; pkts_mask;) {
2623d4e27fdSDavid Marchand 			uint32_t pkt_index = rte_ctz64(pkts_mask);
26399a2dd95SBruce Richardson 			uint64_t pkt_mask = 1LLU << pkt_index;
26499a2dd95SBruce Richardson 
26599a2dd95SBruce Richardson 			p->ev[enq_buf_count++].mbuf = pkts[pkt_index];
26699a2dd95SBruce Richardson 
26799a2dd95SBruce Richardson 			RTE_PORT_EVENTDEV_WRITER_STATS_PKTS_IN_ADD(p, 1);
26899a2dd95SBruce Richardson 			pkts_mask &= ~pkt_mask;
26999a2dd95SBruce Richardson 		}
27099a2dd95SBruce Richardson 
27199a2dd95SBruce Richardson 		p->enq_buf_count = enq_buf_count;
27299a2dd95SBruce Richardson 		if (enq_buf_count >= p->enq_burst_sz)
27399a2dd95SBruce Richardson 			send_burst(p);
27499a2dd95SBruce Richardson 	}
27599a2dd95SBruce Richardson 
27699a2dd95SBruce Richardson 	return 0;
27799a2dd95SBruce Richardson }
27899a2dd95SBruce Richardson 
27999a2dd95SBruce Richardson static int
rte_port_eventdev_writer_flush(void * port)28099a2dd95SBruce Richardson rte_port_eventdev_writer_flush(void *port)
28199a2dd95SBruce Richardson {
28299a2dd95SBruce Richardson 	struct rte_port_eventdev_writer *p =
28399a2dd95SBruce Richardson 			port;
28499a2dd95SBruce Richardson 
28599a2dd95SBruce Richardson 	if (p->enq_buf_count > 0)
28699a2dd95SBruce Richardson 		send_burst(p);
28799a2dd95SBruce Richardson 
28899a2dd95SBruce Richardson 	return 0;
28999a2dd95SBruce Richardson }
29099a2dd95SBruce Richardson 
29199a2dd95SBruce Richardson static int
rte_port_eventdev_writer_free(void * port)29299a2dd95SBruce Richardson rte_port_eventdev_writer_free(void *port)
29399a2dd95SBruce Richardson {
29499a2dd95SBruce Richardson 	if (port == NULL) {
295*ae67895bSDavid Marchand 		PORT_LOG(ERR, "%s: Port is NULL", __func__);
29699a2dd95SBruce Richardson 		return -EINVAL;
29799a2dd95SBruce Richardson 	}
29899a2dd95SBruce Richardson 
29999a2dd95SBruce Richardson 	rte_port_eventdev_writer_flush(port);
30099a2dd95SBruce Richardson 	rte_free(port);
30199a2dd95SBruce Richardson 
30299a2dd95SBruce Richardson 	return 0;
30399a2dd95SBruce Richardson }
30499a2dd95SBruce Richardson 
rte_port_eventdev_writer_stats_read(void * port,struct rte_port_out_stats * stats,int clear)30599a2dd95SBruce Richardson static int rte_port_eventdev_writer_stats_read(void *port,
30699a2dd95SBruce Richardson 	struct rte_port_out_stats *stats, int clear)
30799a2dd95SBruce Richardson {
30899a2dd95SBruce Richardson 	struct rte_port_eventdev_writer *p =
30999a2dd95SBruce Richardson 			port;
31099a2dd95SBruce Richardson 
31199a2dd95SBruce Richardson 	if (stats != NULL)
31299a2dd95SBruce Richardson 		memcpy(stats, &p->stats, sizeof(p->stats));
31399a2dd95SBruce Richardson 
31499a2dd95SBruce Richardson 	if (clear)
31599a2dd95SBruce Richardson 		memset(&p->stats, 0, sizeof(p->stats));
31699a2dd95SBruce Richardson 
31799a2dd95SBruce Richardson 	return 0;
31899a2dd95SBruce Richardson }
31999a2dd95SBruce Richardson 
32099a2dd95SBruce Richardson /*
32199a2dd95SBruce Richardson  * Port EVENTDEV Writer Nodrop
32299a2dd95SBruce Richardson  */
32399a2dd95SBruce Richardson #ifdef RTE_PORT_STATS_COLLECT
32499a2dd95SBruce Richardson 
32599a2dd95SBruce Richardson #define RTE_PORT_EVENTDEV_WRITER_NODROP_STATS_PKTS_IN_ADD(port, val) \
32699a2dd95SBruce Richardson 	do {port->stats.n_pkts_in += val;} while (0)
32799a2dd95SBruce Richardson #define RTE_PORT_EVENTDEV_WRITER_NODROP_STATS_PKTS_DROP_ADD(port, val) \
32899a2dd95SBruce Richardson 	do {port->stats.n_pkts_drop += val;} while (0)
32999a2dd95SBruce Richardson 
33099a2dd95SBruce Richardson #else
33199a2dd95SBruce Richardson 
33299a2dd95SBruce Richardson #define RTE_PORT_EVENTDEV_WRITER_NODROP_STATS_PKTS_IN_ADD(port, val)
33399a2dd95SBruce Richardson #define RTE_PORT_EVENTDEV_WRITER_NODROP_STATS_PKTS_DROP_ADD(port, val)
33499a2dd95SBruce Richardson 
33599a2dd95SBruce Richardson #endif
33699a2dd95SBruce Richardson 
33799a2dd95SBruce Richardson struct rte_port_eventdev_writer_nodrop {
33899a2dd95SBruce Richardson 	struct rte_port_out_stats stats;
33999a2dd95SBruce Richardson 
34099a2dd95SBruce Richardson 	struct rte_event ev[2 * RTE_PORT_IN_BURST_SIZE_MAX];
34199a2dd95SBruce Richardson 
34299a2dd95SBruce Richardson 	uint32_t enq_burst_sz;
34399a2dd95SBruce Richardson 	uint32_t enq_buf_count;
34499a2dd95SBruce Richardson 	uint64_t bsz_mask;
34599a2dd95SBruce Richardson 	uint64_t n_retries;
34699a2dd95SBruce Richardson 	uint8_t eventdev_id;
34799a2dd95SBruce Richardson 	uint8_t port_id;
34899a2dd95SBruce Richardson 	uint8_t queue_id;
34999a2dd95SBruce Richardson 	uint8_t sched_type;
35099a2dd95SBruce Richardson 	uint8_t evt_op;
35199a2dd95SBruce Richardson };
35299a2dd95SBruce Richardson 
35399a2dd95SBruce Richardson 
35499a2dd95SBruce Richardson static void *
rte_port_eventdev_writer_nodrop_create(void * params,int socket_id)35599a2dd95SBruce Richardson rte_port_eventdev_writer_nodrop_create(void *params, int socket_id)
35699a2dd95SBruce Richardson {
35799a2dd95SBruce Richardson 	struct rte_port_eventdev_writer_nodrop_params *conf =
35899a2dd95SBruce Richardson 			params;
35999a2dd95SBruce Richardson 	struct rte_port_eventdev_writer_nodrop *port;
36099a2dd95SBruce Richardson 	unsigned int i;
36199a2dd95SBruce Richardson 
36299a2dd95SBruce Richardson 	/* Check input parameters */
36399a2dd95SBruce Richardson 	if ((conf == NULL) ||
36499a2dd95SBruce Richardson 		(conf->enq_burst_sz == 0) ||
36599a2dd95SBruce Richardson 		(conf->enq_burst_sz > RTE_PORT_IN_BURST_SIZE_MAX) ||
36699a2dd95SBruce Richardson 		(!rte_is_power_of_2(conf->enq_burst_sz))) {
367*ae67895bSDavid Marchand 		PORT_LOG(ERR, "%s: Invalid input parameters", __func__);
36899a2dd95SBruce Richardson 		return NULL;
36999a2dd95SBruce Richardson 	}
37099a2dd95SBruce Richardson 
37199a2dd95SBruce Richardson 	/* Memory allocation */
37299a2dd95SBruce Richardson 	port = rte_zmalloc_socket("PORT", sizeof(*port),
37399a2dd95SBruce Richardson 		RTE_CACHE_LINE_SIZE, socket_id);
37499a2dd95SBruce Richardson 	if (port == NULL) {
375*ae67895bSDavid Marchand 		PORT_LOG(ERR, "%s: Failed to allocate port", __func__);
37699a2dd95SBruce Richardson 		return NULL;
37799a2dd95SBruce Richardson 	}
37899a2dd95SBruce Richardson 
37999a2dd95SBruce Richardson 	/* Initialization */
38099a2dd95SBruce Richardson 	port->enq_burst_sz = conf->enq_burst_sz;
38199a2dd95SBruce Richardson 	port->enq_buf_count = 0;
38299a2dd95SBruce Richardson 	port->bsz_mask = 1LLU << (conf->enq_burst_sz - 1);
38399a2dd95SBruce Richardson 
38499a2dd95SBruce Richardson 	port->eventdev_id = conf->eventdev_id;
38599a2dd95SBruce Richardson 	port->port_id = conf->port_id;
38699a2dd95SBruce Richardson 	port->queue_id = conf->queue_id;
38799a2dd95SBruce Richardson 	port->sched_type = conf->sched_type;
38899a2dd95SBruce Richardson 	port->evt_op = conf->evt_op;
38999a2dd95SBruce Richardson 	memset(&port->ev, 0, sizeof(port->ev));
39099a2dd95SBruce Richardson 
39199a2dd95SBruce Richardson 	for (i = 0; i < RTE_DIM(port->ev); i++) {
39299a2dd95SBruce Richardson 		port->ev[i].queue_id = port->queue_id;
39399a2dd95SBruce Richardson 		port->ev[i].sched_type = port->sched_type;
39499a2dd95SBruce Richardson 		port->ev[i].op = port->evt_op;
39599a2dd95SBruce Richardson 	}
39699a2dd95SBruce Richardson 	/*
39799a2dd95SBruce Richardson 	 * When n_retries is 0 it means that we should wait for every event to
39899a2dd95SBruce Richardson 	 * send no matter how many retries should it take. To limit number of
39999a2dd95SBruce Richardson 	 * branches in fast path, we use UINT64_MAX instead of branching.
40099a2dd95SBruce Richardson 	 */
40199a2dd95SBruce Richardson 	port->n_retries = (conf->n_retries == 0) ? UINT64_MAX : conf->n_retries;
40299a2dd95SBruce Richardson 
40399a2dd95SBruce Richardson 	return port;
40499a2dd95SBruce Richardson }
40599a2dd95SBruce Richardson 
40699a2dd95SBruce Richardson static inline void
send_burst_nodrop(struct rte_port_eventdev_writer_nodrop * p)40799a2dd95SBruce Richardson send_burst_nodrop(struct rte_port_eventdev_writer_nodrop *p)
40899a2dd95SBruce Richardson {
40999a2dd95SBruce Richardson 	uint32_t nb_enq, i;
41099a2dd95SBruce Richardson 
41199a2dd95SBruce Richardson 	nb_enq = rte_event_enqueue_burst(p->eventdev_id, p->port_id,
41299a2dd95SBruce Richardson 			p->ev, p->enq_buf_count);
41399a2dd95SBruce Richardson 
41499a2dd95SBruce Richardson 	/* We sent all the packets in a first try */
41599a2dd95SBruce Richardson 	if (nb_enq >= p->enq_buf_count) {
41699a2dd95SBruce Richardson 		p->enq_buf_count = 0;
41799a2dd95SBruce Richardson 		return;
41899a2dd95SBruce Richardson 	}
41999a2dd95SBruce Richardson 
42099a2dd95SBruce Richardson 	for (i = 0; i < p->n_retries; i++) {
42199a2dd95SBruce Richardson 		nb_enq += rte_event_enqueue_burst(p->eventdev_id, p->port_id,
42299a2dd95SBruce Richardson 							p->ev + nb_enq,
42399a2dd95SBruce Richardson 							p->enq_buf_count - nb_enq);
42499a2dd95SBruce Richardson 
42599a2dd95SBruce Richardson 		/* We sent all the events in more than one try */
42699a2dd95SBruce Richardson 		if (nb_enq >= p->enq_buf_count) {
42799a2dd95SBruce Richardson 			p->enq_buf_count = 0;
42899a2dd95SBruce Richardson 			return;
42999a2dd95SBruce Richardson 		}
43099a2dd95SBruce Richardson 	}
43199a2dd95SBruce Richardson 	/* We didn't send the events in maximum allowed attempts */
43299a2dd95SBruce Richardson 	RTE_PORT_EVENTDEV_WRITER_NODROP_STATS_PKTS_DROP_ADD(p,
43399a2dd95SBruce Richardson 			p->enq_buf_count - nb_enq);
43499a2dd95SBruce Richardson 	for (; nb_enq < p->enq_buf_count; nb_enq++)
43599a2dd95SBruce Richardson 		rte_pktmbuf_free(p->ev[nb_enq].mbuf);
43699a2dd95SBruce Richardson 
43799a2dd95SBruce Richardson 	p->enq_buf_count = 0;
43899a2dd95SBruce Richardson }
43999a2dd95SBruce Richardson 
44099a2dd95SBruce Richardson static int
rte_port_eventdev_writer_nodrop_tx(void * port,struct rte_mbuf * pkt)44199a2dd95SBruce Richardson rte_port_eventdev_writer_nodrop_tx(void *port, struct rte_mbuf *pkt)
44299a2dd95SBruce Richardson {
44399a2dd95SBruce Richardson 	struct rte_port_eventdev_writer_nodrop *p = port;
44499a2dd95SBruce Richardson 
44599a2dd95SBruce Richardson 	p->ev[p->enq_buf_count++].mbuf = pkt;
44699a2dd95SBruce Richardson 
44799a2dd95SBruce Richardson 	RTE_PORT_EVENTDEV_WRITER_NODROP_STATS_PKTS_IN_ADD(p, 1);
44899a2dd95SBruce Richardson 	if (p->enq_buf_count >= p->enq_burst_sz)
44999a2dd95SBruce Richardson 		send_burst_nodrop(p);
45099a2dd95SBruce Richardson 
45199a2dd95SBruce Richardson 	return 0;
45299a2dd95SBruce Richardson }
45399a2dd95SBruce Richardson 
45499a2dd95SBruce Richardson static int
rte_port_eventdev_writer_nodrop_tx_bulk(void * port,struct rte_mbuf ** pkts,uint64_t pkts_mask)45599a2dd95SBruce Richardson rte_port_eventdev_writer_nodrop_tx_bulk(void *port,
45699a2dd95SBruce Richardson 	struct rte_mbuf **pkts,
45799a2dd95SBruce Richardson 	uint64_t pkts_mask)
45899a2dd95SBruce Richardson {
45999a2dd95SBruce Richardson 	struct rte_port_eventdev_writer_nodrop *p =
46099a2dd95SBruce Richardson 			port;
46199a2dd95SBruce Richardson 
46299a2dd95SBruce Richardson 	uint64_t bsz_mask = p->bsz_mask;
46399a2dd95SBruce Richardson 	uint32_t enq_buf_count = p->enq_buf_count;
46499a2dd95SBruce Richardson 	uint64_t expr = (pkts_mask & (pkts_mask + 1)) |
46599a2dd95SBruce Richardson 					((pkts_mask & bsz_mask) ^ bsz_mask);
46699a2dd95SBruce Richardson 
46799a2dd95SBruce Richardson 	if (expr == 0) {
4683d4e27fdSDavid Marchand 		uint64_t n_pkts = rte_popcount64(pkts_mask);
46999a2dd95SBruce Richardson 		uint32_t i, n_enq_ok;
47099a2dd95SBruce Richardson 
47199a2dd95SBruce Richardson 		if (enq_buf_count)
47299a2dd95SBruce Richardson 			send_burst_nodrop(p);
47399a2dd95SBruce Richardson 
47499a2dd95SBruce Richardson 		RTE_PORT_EVENTDEV_WRITER_NODROP_STATS_PKTS_IN_ADD(p, n_pkts);
47599a2dd95SBruce Richardson 
47699a2dd95SBruce Richardson 		struct rte_event events[RTE_PORT_IN_BURST_SIZE_MAX] = {};
47799a2dd95SBruce Richardson 
47899a2dd95SBruce Richardson 		for (i = 0; i < n_pkts; i++) {
47999a2dd95SBruce Richardson 			events[i].mbuf = pkts[i];
48099a2dd95SBruce Richardson 			events[i].queue_id = p->queue_id;
48199a2dd95SBruce Richardson 			events[i].sched_type = p->sched_type;
48299a2dd95SBruce Richardson 			events[i].op = p->evt_op;
48399a2dd95SBruce Richardson 		}
48499a2dd95SBruce Richardson 
48599a2dd95SBruce Richardson 		n_enq_ok = rte_event_enqueue_burst(p->eventdev_id, p->port_id,
48699a2dd95SBruce Richardson 				events, n_pkts);
48799a2dd95SBruce Richardson 
48899a2dd95SBruce Richardson 		if (n_enq_ok >= n_pkts)
48999a2dd95SBruce Richardson 			return 0;
49099a2dd95SBruce Richardson 
49199a2dd95SBruce Richardson 		/*
49299a2dd95SBruce Richardson 		 * If we did not manage to enqueue all events in single burst,
49399a2dd95SBruce Richardson 		 * move remaining events to the buffer and call send burst.
49499a2dd95SBruce Richardson 		 */
49599a2dd95SBruce Richardson 		for (; n_enq_ok < n_pkts; n_enq_ok++) {
49699a2dd95SBruce Richardson 			struct rte_mbuf *pkt = pkts[n_enq_ok];
49799a2dd95SBruce Richardson 			p->ev[p->enq_buf_count++].mbuf = pkt;
49899a2dd95SBruce Richardson 		}
49999a2dd95SBruce Richardson 		send_burst_nodrop(p);
50099a2dd95SBruce Richardson 	} else {
50199a2dd95SBruce Richardson 		for (; pkts_mask;) {
5023d4e27fdSDavid Marchand 			uint32_t pkt_index = rte_ctz64(pkts_mask);
50399a2dd95SBruce Richardson 			uint64_t pkt_mask = 1LLU << pkt_index;
50499a2dd95SBruce Richardson 
50599a2dd95SBruce Richardson 			p->ev[enq_buf_count++].mbuf = pkts[pkt_index];
50699a2dd95SBruce Richardson 
50799a2dd95SBruce Richardson 			RTE_PORT_EVENTDEV_WRITER_STATS_PKTS_IN_ADD(p, 1);
50899a2dd95SBruce Richardson 			pkts_mask &= ~pkt_mask;
50999a2dd95SBruce Richardson 		}
51099a2dd95SBruce Richardson 
51199a2dd95SBruce Richardson 		p->enq_buf_count = enq_buf_count;
51299a2dd95SBruce Richardson 		if (enq_buf_count >= p->enq_burst_sz)
51399a2dd95SBruce Richardson 			send_burst_nodrop(p);
51499a2dd95SBruce Richardson 	}
51599a2dd95SBruce Richardson 
51699a2dd95SBruce Richardson 	return 0;
51799a2dd95SBruce Richardson }
51899a2dd95SBruce Richardson 
51999a2dd95SBruce Richardson static int
rte_port_eventdev_writer_nodrop_flush(void * port)52099a2dd95SBruce Richardson rte_port_eventdev_writer_nodrop_flush(void *port)
52199a2dd95SBruce Richardson {
52299a2dd95SBruce Richardson 	struct rte_port_eventdev_writer_nodrop *p =
52399a2dd95SBruce Richardson 			port;
52499a2dd95SBruce Richardson 
52599a2dd95SBruce Richardson 	if (p->enq_buf_count > 0)
52699a2dd95SBruce Richardson 		send_burst_nodrop(p);
52799a2dd95SBruce Richardson 
52899a2dd95SBruce Richardson 	return 0;
52999a2dd95SBruce Richardson }
53099a2dd95SBruce Richardson 
53199a2dd95SBruce Richardson static int
rte_port_eventdev_writer_nodrop_free(void * port)53299a2dd95SBruce Richardson rte_port_eventdev_writer_nodrop_free(void *port)
53399a2dd95SBruce Richardson {
53499a2dd95SBruce Richardson 	if (port == NULL) {
535*ae67895bSDavid Marchand 		PORT_LOG(ERR, "%s: Port is NULL", __func__);
53699a2dd95SBruce Richardson 		return -EINVAL;
53799a2dd95SBruce Richardson 	}
53899a2dd95SBruce Richardson 
53999a2dd95SBruce Richardson 	rte_port_eventdev_writer_nodrop_flush(port);
54099a2dd95SBruce Richardson 	rte_free(port);
54199a2dd95SBruce Richardson 
54299a2dd95SBruce Richardson 	return 0;
54399a2dd95SBruce Richardson }
54499a2dd95SBruce Richardson 
rte_port_eventdev_writer_nodrop_stats_read(void * port,struct rte_port_out_stats * stats,int clear)54599a2dd95SBruce Richardson static int rte_port_eventdev_writer_nodrop_stats_read(void *port,
54699a2dd95SBruce Richardson 	struct rte_port_out_stats *stats, int clear)
54799a2dd95SBruce Richardson {
54899a2dd95SBruce Richardson 	struct rte_port_eventdev_writer_nodrop *p =
54999a2dd95SBruce Richardson 			port;
55099a2dd95SBruce Richardson 
55199a2dd95SBruce Richardson 	if (stats != NULL)
55299a2dd95SBruce Richardson 		memcpy(stats, &p->stats, sizeof(p->stats));
55399a2dd95SBruce Richardson 
55499a2dd95SBruce Richardson 	if (clear)
55599a2dd95SBruce Richardson 		memset(&p->stats, 0, sizeof(p->stats));
55699a2dd95SBruce Richardson 
55799a2dd95SBruce Richardson 	return 0;
55899a2dd95SBruce Richardson }
55999a2dd95SBruce Richardson 
56099a2dd95SBruce Richardson /*
56199a2dd95SBruce Richardson  * Summary of port operations
56299a2dd95SBruce Richardson  */
56399a2dd95SBruce Richardson struct rte_port_in_ops rte_port_eventdev_reader_ops = {
56499a2dd95SBruce Richardson 	.f_create = rte_port_eventdev_reader_create,
56599a2dd95SBruce Richardson 	.f_free = rte_port_eventdev_reader_free,
56699a2dd95SBruce Richardson 	.f_rx = rte_port_eventdev_reader_rx,
56799a2dd95SBruce Richardson 	.f_stats = rte_port_eventdev_reader_stats_read,
56899a2dd95SBruce Richardson };
56999a2dd95SBruce Richardson 
57099a2dd95SBruce Richardson struct rte_port_out_ops rte_port_eventdev_writer_ops = {
57199a2dd95SBruce Richardson 	.f_create = rte_port_eventdev_writer_create,
57299a2dd95SBruce Richardson 	.f_free = rte_port_eventdev_writer_free,
57399a2dd95SBruce Richardson 	.f_tx = rte_port_eventdev_writer_tx,
57499a2dd95SBruce Richardson 	.f_tx_bulk = rte_port_eventdev_writer_tx_bulk,
57599a2dd95SBruce Richardson 	.f_flush = rte_port_eventdev_writer_flush,
57699a2dd95SBruce Richardson 	.f_stats = rte_port_eventdev_writer_stats_read,
57799a2dd95SBruce Richardson };
57899a2dd95SBruce Richardson 
57999a2dd95SBruce Richardson struct rte_port_out_ops rte_port_eventdev_writer_nodrop_ops = {
58099a2dd95SBruce Richardson 	.f_create = rte_port_eventdev_writer_nodrop_create,
58199a2dd95SBruce Richardson 	.f_free = rte_port_eventdev_writer_nodrop_free,
58299a2dd95SBruce Richardson 	.f_tx = rte_port_eventdev_writer_nodrop_tx,
58399a2dd95SBruce Richardson 	.f_tx_bulk = rte_port_eventdev_writer_nodrop_tx_bulk,
58499a2dd95SBruce Richardson 	.f_flush = rte_port_eventdev_writer_nodrop_flush,
58599a2dd95SBruce Richardson 	.f_stats = rte_port_eventdev_writer_nodrop_stats_read,
58699a2dd95SBruce Richardson };
587