xref: /dpdk/lib/ethdev/ethdev_private.c (revision 41f2f055)
199a2dd95SBruce Richardson /* SPDX-License-Identifier: BSD-3-Clause
299a2dd95SBruce Richardson  * Copyright(c) 2018 Gaëtan Rivet
399a2dd95SBruce Richardson  */
499a2dd95SBruce Richardson 
5*41f2f055SDavid Marchand #include <rte_debug.h>
699a2dd95SBruce Richardson #include "rte_ethdev.h"
799a2dd95SBruce Richardson #include "ethdev_driver.h"
899a2dd95SBruce Richardson #include "ethdev_private.h"
999a2dd95SBruce Richardson 
1099a2dd95SBruce Richardson uint16_t
1199a2dd95SBruce Richardson eth_dev_to_id(const struct rte_eth_dev *dev)
1299a2dd95SBruce Richardson {
1399a2dd95SBruce Richardson 	if (dev == NULL)
1499a2dd95SBruce Richardson 		return RTE_MAX_ETHPORTS;
1599a2dd95SBruce Richardson 	return dev - rte_eth_devices;
1699a2dd95SBruce Richardson }
1799a2dd95SBruce Richardson 
1899a2dd95SBruce Richardson struct rte_eth_dev *
1999a2dd95SBruce Richardson eth_find_device(const struct rte_eth_dev *start, rte_eth_cmp_t cmp,
2099a2dd95SBruce Richardson 		const void *data)
2199a2dd95SBruce Richardson {
2299a2dd95SBruce Richardson 	struct rte_eth_dev *edev;
2399a2dd95SBruce Richardson 	ptrdiff_t idx;
2499a2dd95SBruce Richardson 
2599a2dd95SBruce Richardson 	/* Avoid Undefined Behaviour */
2699a2dd95SBruce Richardson 	if (start != NULL &&
2799a2dd95SBruce Richardson 	    (start < &rte_eth_devices[0] ||
2899a2dd95SBruce Richardson 	     start > &rte_eth_devices[RTE_MAX_ETHPORTS]))
2999a2dd95SBruce Richardson 		return NULL;
3099a2dd95SBruce Richardson 	if (start != NULL)
3199a2dd95SBruce Richardson 		idx = eth_dev_to_id(start) + 1;
3299a2dd95SBruce Richardson 	else
3399a2dd95SBruce Richardson 		idx = 0;
3499a2dd95SBruce Richardson 	for (; idx < RTE_MAX_ETHPORTS; idx++) {
3599a2dd95SBruce Richardson 		edev = &rte_eth_devices[idx];
3699a2dd95SBruce Richardson 		if (cmp(edev, data) == 0)
3799a2dd95SBruce Richardson 			return edev;
3899a2dd95SBruce Richardson 	}
3999a2dd95SBruce Richardson 	return NULL;
4099a2dd95SBruce Richardson }
4199a2dd95SBruce Richardson 
4299a2dd95SBruce Richardson /* Put new value into list. */
4399a2dd95SBruce Richardson static int
4499a2dd95SBruce Richardson rte_eth_devargs_enlist(uint16_t *list, uint16_t *len_list,
4599a2dd95SBruce Richardson 		       const uint16_t max_list, uint16_t val)
4699a2dd95SBruce Richardson {
4799a2dd95SBruce Richardson 	uint16_t i;
4899a2dd95SBruce Richardson 
4999a2dd95SBruce Richardson 	for (i = 0; i < *len_list; i++) {
5099a2dd95SBruce Richardson 		if (list[i] == val)
5199a2dd95SBruce Richardson 			return 0;
5299a2dd95SBruce Richardson 	}
5399a2dd95SBruce Richardson 	if (*len_list >= max_list)
5499a2dd95SBruce Richardson 		return -1;
5599a2dd95SBruce Richardson 	list[(*len_list)++] = val;
5699a2dd95SBruce Richardson 	return 0;
5799a2dd95SBruce Richardson }
5899a2dd95SBruce Richardson 
5999a2dd95SBruce Richardson /* Parse and enlist a range expression of "min-max" or a single value. */
6099a2dd95SBruce Richardson static char *
6199a2dd95SBruce Richardson rte_eth_devargs_process_range(char *str, uint16_t *list, uint16_t *len_list,
6299a2dd95SBruce Richardson 	const uint16_t max_list)
6399a2dd95SBruce Richardson {
6499a2dd95SBruce Richardson 	uint16_t lo, hi, val;
6599a2dd95SBruce Richardson 	int result, n = 0;
6699a2dd95SBruce Richardson 	char *pos = str;
6799a2dd95SBruce Richardson 
6899a2dd95SBruce Richardson 	result = sscanf(str, "%hu%n-%hu%n", &lo, &n, &hi, &n);
6999a2dd95SBruce Richardson 	if (result == 1) {
7099a2dd95SBruce Richardson 		if (rte_eth_devargs_enlist(list, len_list, max_list, lo) != 0)
7199a2dd95SBruce Richardson 			return NULL;
7299a2dd95SBruce Richardson 	} else if (result == 2) {
7399a2dd95SBruce Richardson 		if (lo > hi)
7499a2dd95SBruce Richardson 			return NULL;
7599a2dd95SBruce Richardson 		for (val = lo; val <= hi; val++) {
7699a2dd95SBruce Richardson 			if (rte_eth_devargs_enlist(list, len_list, max_list,
7799a2dd95SBruce Richardson 						   val) != 0)
7899a2dd95SBruce Richardson 				return NULL;
7999a2dd95SBruce Richardson 		}
8099a2dd95SBruce Richardson 	} else
8199a2dd95SBruce Richardson 		return NULL;
8299a2dd95SBruce Richardson 	return pos + n;
8399a2dd95SBruce Richardson }
8499a2dd95SBruce Richardson 
8599a2dd95SBruce Richardson /*
8699a2dd95SBruce Richardson  * Parse list of values separated by ",".
8799a2dd95SBruce Richardson  * Each value could be a range [min-max] or single number.
8899a2dd95SBruce Richardson  * Examples:
8999a2dd95SBruce Richardson  *  2               - single
9099a2dd95SBruce Richardson  *  [1,2,3]         - single list
9199a2dd95SBruce Richardson  *  [1,3-5,7,9-11]  - list with singles and ranges
9299a2dd95SBruce Richardson  */
9399a2dd95SBruce Richardson static char *
9499a2dd95SBruce Richardson rte_eth_devargs_process_list(char *str, uint16_t *list, uint16_t *len_list,
9599a2dd95SBruce Richardson 	const uint16_t max_list)
9699a2dd95SBruce Richardson {
9799a2dd95SBruce Richardson 	char *pos = str;
9899a2dd95SBruce Richardson 
9999a2dd95SBruce Richardson 	if (*pos == '[')
10099a2dd95SBruce Richardson 		pos++;
10199a2dd95SBruce Richardson 	while (1) {
10299a2dd95SBruce Richardson 		pos = rte_eth_devargs_process_range(pos, list, len_list,
10399a2dd95SBruce Richardson 						    max_list);
10499a2dd95SBruce Richardson 		if (pos == NULL)
10599a2dd95SBruce Richardson 			return NULL;
10699a2dd95SBruce Richardson 		if (*pos != ',') /* end of list */
10799a2dd95SBruce Richardson 			break;
10899a2dd95SBruce Richardson 		pos++;
10999a2dd95SBruce Richardson 	}
11099a2dd95SBruce Richardson 	if (*str == '[' && *pos != ']')
11199a2dd95SBruce Richardson 		return NULL;
11299a2dd95SBruce Richardson 	if (*pos == ']')
11399a2dd95SBruce Richardson 		pos++;
11499a2dd95SBruce Richardson 	return pos;
11599a2dd95SBruce Richardson }
11699a2dd95SBruce Richardson 
11799a2dd95SBruce Richardson /*
11899a2dd95SBruce Richardson  * Parse representor ports from a single value or lists.
11999a2dd95SBruce Richardson  *
12099a2dd95SBruce Richardson  * Representor format:
12199a2dd95SBruce Richardson  *   #: range or single number of VF representor - legacy
12299a2dd95SBruce Richardson  *   [[c#]pf#]vf#: VF port representor/s
12399a2dd95SBruce Richardson  *   [[c#]pf#]sf#: SF port representor/s
12499a2dd95SBruce Richardson  *   [c#]pf#:      PF port representor/s
12599a2dd95SBruce Richardson  *
12699a2dd95SBruce Richardson  * Examples of #:
12799a2dd95SBruce Richardson  *  2               - single
12899a2dd95SBruce Richardson  *  [1,2,3]         - single list
12999a2dd95SBruce Richardson  *  [1,3-5,7,9-11]  - list with singles and ranges
13099a2dd95SBruce Richardson  */
13199a2dd95SBruce Richardson int
13299a2dd95SBruce Richardson rte_eth_devargs_parse_representor_ports(char *str, void *data)
13399a2dd95SBruce Richardson {
13499a2dd95SBruce Richardson 	struct rte_eth_devargs *eth_da = data;
13599a2dd95SBruce Richardson 
13699a2dd95SBruce Richardson 	if (str[0] == 'c') {
13799a2dd95SBruce Richardson 		str += 1;
13899a2dd95SBruce Richardson 		str = rte_eth_devargs_process_list(str, eth_da->mh_controllers,
13999a2dd95SBruce Richardson 				&eth_da->nb_mh_controllers,
14099a2dd95SBruce Richardson 				RTE_DIM(eth_da->mh_controllers));
14199a2dd95SBruce Richardson 		if (str == NULL)
14299a2dd95SBruce Richardson 			goto done;
14399a2dd95SBruce Richardson 	}
14499a2dd95SBruce Richardson 	if (str[0] == 'p' && str[1] == 'f') {
14599a2dd95SBruce Richardson 		eth_da->type = RTE_ETH_REPRESENTOR_PF;
14699a2dd95SBruce Richardson 		str += 2;
14799a2dd95SBruce Richardson 		str = rte_eth_devargs_process_list(str, eth_da->ports,
14899a2dd95SBruce Richardson 				&eth_da->nb_ports, RTE_DIM(eth_da->ports));
14999a2dd95SBruce Richardson 		if (str == NULL || str[0] == '\0')
15099a2dd95SBruce Richardson 			goto done;
15199a2dd95SBruce Richardson 	} else if (eth_da->nb_mh_controllers > 0) {
15299a2dd95SBruce Richardson 		/* 'c' must followed by 'pf'. */
15399a2dd95SBruce Richardson 		str = NULL;
15499a2dd95SBruce Richardson 		goto done;
15599a2dd95SBruce Richardson 	}
15699a2dd95SBruce Richardson 	if (str[0] == 'v' && str[1] == 'f') {
15799a2dd95SBruce Richardson 		eth_da->type = RTE_ETH_REPRESENTOR_VF;
15899a2dd95SBruce Richardson 		str += 2;
15999a2dd95SBruce Richardson 	} else if (str[0] == 's' && str[1] == 'f') {
16099a2dd95SBruce Richardson 		eth_da->type = RTE_ETH_REPRESENTOR_SF;
16199a2dd95SBruce Richardson 		str += 2;
16299a2dd95SBruce Richardson 	} else {
16399a2dd95SBruce Richardson 		/* 'pf' must followed by 'vf' or 'sf'. */
16499a2dd95SBruce Richardson 		if (eth_da->type == RTE_ETH_REPRESENTOR_PF) {
16599a2dd95SBruce Richardson 			str = NULL;
16699a2dd95SBruce Richardson 			goto done;
16799a2dd95SBruce Richardson 		}
16899a2dd95SBruce Richardson 		eth_da->type = RTE_ETH_REPRESENTOR_VF;
16999a2dd95SBruce Richardson 	}
17099a2dd95SBruce Richardson 	str = rte_eth_devargs_process_list(str, eth_da->representor_ports,
17199a2dd95SBruce Richardson 		&eth_da->nb_representor_ports,
17299a2dd95SBruce Richardson 		RTE_DIM(eth_da->representor_ports));
17399a2dd95SBruce Richardson done:
17499a2dd95SBruce Richardson 	if (str == NULL)
17599a2dd95SBruce Richardson 		RTE_LOG(ERR, EAL, "wrong representor format: %s\n", str);
17699a2dd95SBruce Richardson 	return str == NULL ? -1 : 0;
17799a2dd95SBruce Richardson }
178c87d435aSKonstantin Ananyev 
179*41f2f055SDavid Marchand struct dummy_queue {
180*41f2f055SDavid Marchand 	bool rx_warn_once;
181*41f2f055SDavid Marchand 	bool tx_warn_once;
182*41f2f055SDavid Marchand };
183*41f2f055SDavid Marchand static struct dummy_queue *dummy_queues_array[RTE_MAX_ETHPORTS][RTE_MAX_QUEUES_PER_PORT];
184*41f2f055SDavid Marchand static struct dummy_queue per_port_queues[RTE_MAX_ETHPORTS];
185*41f2f055SDavid Marchand RTE_INIT(dummy_queue_init)
186*41f2f055SDavid Marchand {
187*41f2f055SDavid Marchand 	uint16_t port_id;
188*41f2f055SDavid Marchand 
189*41f2f055SDavid Marchand 	for (port_id = 0; port_id < RTE_DIM(per_port_queues); port_id++) {
190*41f2f055SDavid Marchand 		unsigned int q;
191*41f2f055SDavid Marchand 
192*41f2f055SDavid Marchand 		for (q = 0; q < RTE_DIM(dummy_queues_array[port_id]); q++)
193*41f2f055SDavid Marchand 			dummy_queues_array[port_id][q] = &per_port_queues[port_id];
194*41f2f055SDavid Marchand 	}
195*41f2f055SDavid Marchand }
196*41f2f055SDavid Marchand 
197c87d435aSKonstantin Ananyev static uint16_t
198*41f2f055SDavid Marchand dummy_eth_rx_burst(void *rxq,
199c87d435aSKonstantin Ananyev 		__rte_unused struct rte_mbuf **rx_pkts,
200c87d435aSKonstantin Ananyev 		__rte_unused uint16_t nb_pkts)
201c87d435aSKonstantin Ananyev {
202*41f2f055SDavid Marchand 	struct dummy_queue *queue = rxq;
203*41f2f055SDavid Marchand 	uintptr_t port_id;
204*41f2f055SDavid Marchand 
205*41f2f055SDavid Marchand 	port_id = queue - per_port_queues;
206*41f2f055SDavid Marchand 	if (port_id < RTE_DIM(per_port_queues) && !queue->rx_warn_once) {
207*41f2f055SDavid Marchand 		RTE_ETHDEV_LOG(ERR, "lcore %u called rx_pkt_burst for not ready port %"PRIuPTR"\n",
208*41f2f055SDavid Marchand 			rte_lcore_id(), port_id);
209*41f2f055SDavid Marchand 		rte_dump_stack();
210*41f2f055SDavid Marchand 		queue->rx_warn_once = true;
211*41f2f055SDavid Marchand 	}
212c87d435aSKonstantin Ananyev 	rte_errno = ENOTSUP;
213c87d435aSKonstantin Ananyev 	return 0;
214c87d435aSKonstantin Ananyev }
215c87d435aSKonstantin Ananyev 
216c87d435aSKonstantin Ananyev static uint16_t
217*41f2f055SDavid Marchand dummy_eth_tx_burst(void *txq,
218c87d435aSKonstantin Ananyev 		__rte_unused struct rte_mbuf **tx_pkts,
219c87d435aSKonstantin Ananyev 		__rte_unused uint16_t nb_pkts)
220c87d435aSKonstantin Ananyev {
221*41f2f055SDavid Marchand 	struct dummy_queue *queue = txq;
222*41f2f055SDavid Marchand 	uintptr_t port_id;
223*41f2f055SDavid Marchand 
224*41f2f055SDavid Marchand 	port_id = queue - per_port_queues;
225*41f2f055SDavid Marchand 	if (port_id < RTE_DIM(per_port_queues) && !queue->tx_warn_once) {
226*41f2f055SDavid Marchand 		RTE_ETHDEV_LOG(ERR, "lcore %u called tx_pkt_burst for not ready port %"PRIuPTR"\n",
227*41f2f055SDavid Marchand 			rte_lcore_id(), port_id);
228*41f2f055SDavid Marchand 		rte_dump_stack();
229*41f2f055SDavid Marchand 		queue->tx_warn_once = true;
230*41f2f055SDavid Marchand 	}
231c87d435aSKonstantin Ananyev 	rte_errno = ENOTSUP;
232c87d435aSKonstantin Ananyev 	return 0;
233c87d435aSKonstantin Ananyev }
234c87d435aSKonstantin Ananyev 
235c87d435aSKonstantin Ananyev void
236c87d435aSKonstantin Ananyev eth_dev_fp_ops_reset(struct rte_eth_fp_ops *fpo)
237c87d435aSKonstantin Ananyev {
238c87d435aSKonstantin Ananyev 	static void *dummy_data[RTE_MAX_QUEUES_PER_PORT];
239*41f2f055SDavid Marchand 	uintptr_t port_id = fpo - rte_eth_fp_ops;
240*41f2f055SDavid Marchand 
241*41f2f055SDavid Marchand 	per_port_queues[port_id].rx_warn_once = false;
242*41f2f055SDavid Marchand 	per_port_queues[port_id].tx_warn_once = false;
243*41f2f055SDavid Marchand 	*fpo = (struct rte_eth_fp_ops) {
244c87d435aSKonstantin Ananyev 		.rx_pkt_burst = dummy_eth_rx_burst,
245c87d435aSKonstantin Ananyev 		.tx_pkt_burst = dummy_eth_tx_burst,
246*41f2f055SDavid Marchand 		.rxq = {
247*41f2f055SDavid Marchand 			.data = (void **)&dummy_queues_array[port_id],
248*41f2f055SDavid Marchand 			.clbk = dummy_data,
249*41f2f055SDavid Marchand 		},
250*41f2f055SDavid Marchand 		.txq = {
251*41f2f055SDavid Marchand 			.data = (void **)&dummy_queues_array[port_id],
252*41f2f055SDavid Marchand 			.clbk = dummy_data,
253*41f2f055SDavid Marchand 		},
254c87d435aSKonstantin Ananyev 	};
255c87d435aSKonstantin Ananyev }
256c87d435aSKonstantin Ananyev 
257c87d435aSKonstantin Ananyev void
258c87d435aSKonstantin Ananyev eth_dev_fp_ops_setup(struct rte_eth_fp_ops *fpo,
259c87d435aSKonstantin Ananyev 		const struct rte_eth_dev *dev)
260c87d435aSKonstantin Ananyev {
261c87d435aSKonstantin Ananyev 	fpo->rx_pkt_burst = dev->rx_pkt_burst;
262c87d435aSKonstantin Ananyev 	fpo->tx_pkt_burst = dev->tx_pkt_burst;
263c87d435aSKonstantin Ananyev 	fpo->tx_pkt_prepare = dev->tx_pkt_prepare;
264c87d435aSKonstantin Ananyev 	fpo->rx_queue_count = dev->rx_queue_count;
265c87d435aSKonstantin Ananyev 	fpo->rx_descriptor_status = dev->rx_descriptor_status;
266c87d435aSKonstantin Ananyev 	fpo->tx_descriptor_status = dev->tx_descriptor_status;
267c87d435aSKonstantin Ananyev 
268c87d435aSKonstantin Ananyev 	fpo->rxq.data = dev->data->rx_queues;
269c87d435aSKonstantin Ananyev 	fpo->rxq.clbk = (void **)(uintptr_t)dev->post_rx_burst_cbs;
270c87d435aSKonstantin Ananyev 
271c87d435aSKonstantin Ananyev 	fpo->txq.data = dev->data->tx_queues;
272c87d435aSKonstantin Ananyev 	fpo->txq.clbk = (void **)(uintptr_t)dev->pre_tx_burst_cbs;
273c87d435aSKonstantin Ananyev }
2747a093523SKonstantin Ananyev 
2757a093523SKonstantin Ananyev uint16_t
2767a093523SKonstantin Ananyev rte_eth_call_rx_callbacks(uint16_t port_id, uint16_t queue_id,
2777a093523SKonstantin Ananyev 	struct rte_mbuf **rx_pkts, uint16_t nb_rx, uint16_t nb_pkts,
2787a093523SKonstantin Ananyev 	void *opaque)
2797a093523SKonstantin Ananyev {
2807a093523SKonstantin Ananyev 	const struct rte_eth_rxtx_callback *cb = opaque;
2817a093523SKonstantin Ananyev 
2827a093523SKonstantin Ananyev 	while (cb != NULL) {
2837a093523SKonstantin Ananyev 		nb_rx = cb->fn.rx(port_id, queue_id, rx_pkts, nb_rx,
2847a093523SKonstantin Ananyev 				nb_pkts, cb->param);
2857a093523SKonstantin Ananyev 		cb = cb->next;
2867a093523SKonstantin Ananyev 	}
2877a093523SKonstantin Ananyev 
2887a093523SKonstantin Ananyev 	return nb_rx;
2897a093523SKonstantin Ananyev }
2907a093523SKonstantin Ananyev 
2917a093523SKonstantin Ananyev uint16_t
2927a093523SKonstantin Ananyev rte_eth_call_tx_callbacks(uint16_t port_id, uint16_t queue_id,
2937a093523SKonstantin Ananyev 	struct rte_mbuf **tx_pkts, uint16_t nb_pkts, void *opaque)
2947a093523SKonstantin Ananyev {
2957a093523SKonstantin Ananyev 	const struct rte_eth_rxtx_callback *cb = opaque;
2967a093523SKonstantin Ananyev 
2977a093523SKonstantin Ananyev 	while (cb != NULL) {
2987a093523SKonstantin Ananyev 		nb_pkts = cb->fn.tx(port_id, queue_id, tx_pkts, nb_pkts,
2997a093523SKonstantin Ananyev 				cb->param);
3007a093523SKonstantin Ananyev 		cb = cb->next;
3017a093523SKonstantin Ananyev 	}
3027a093523SKonstantin Ananyev 
3037a093523SKonstantin Ananyev 	return nb_pkts;
3047a093523SKonstantin Ananyev }
305