xref: /dpdk/lib/ethdev/ethdev_private.c (revision e075ca1d2a22552a4ee6e2f2fa8d847b9e305c8e)
199a2dd95SBruce Richardson /* SPDX-License-Identifier: BSD-3-Clause
299a2dd95SBruce Richardson  * Copyright(c) 2018 Gaëtan Rivet
399a2dd95SBruce Richardson  */
499a2dd95SBruce Richardson 
541f2f055SDavid Marchand #include <rte_debug.h>
64b4f810eSFerruh Yigit 
799a2dd95SBruce Richardson #include "rte_ethdev.h"
86679cf21SAnkur Dwivedi #include "rte_ethdev_trace_fp.h"
999a2dd95SBruce Richardson #include "ethdev_driver.h"
1099a2dd95SBruce Richardson #include "ethdev_private.h"
1199a2dd95SBruce Richardson 
124b4f810eSFerruh Yigit static const char *MZ_RTE_ETH_DEV_DATA = "rte_eth_dev_data";
134b4f810eSFerruh Yigit 
1436c46e73SDavid Marchand static const struct rte_memzone *eth_dev_shared_mz;
154b4f810eSFerruh Yigit struct eth_dev_shared *eth_dev_shared_data;
164b4f810eSFerruh Yigit 
174b4f810eSFerruh Yigit /* spinlock for eth device callbacks */
184b4f810eSFerruh Yigit rte_spinlock_t eth_dev_cb_lock = RTE_SPINLOCK_INITIALIZER;
194b4f810eSFerruh Yigit 
2099a2dd95SBruce Richardson uint16_t
2199a2dd95SBruce Richardson eth_dev_to_id(const struct rte_eth_dev *dev)
2299a2dd95SBruce Richardson {
2399a2dd95SBruce Richardson 	if (dev == NULL)
2499a2dd95SBruce Richardson 		return RTE_MAX_ETHPORTS;
2599a2dd95SBruce Richardson 	return dev - rte_eth_devices;
2699a2dd95SBruce Richardson }
2799a2dd95SBruce Richardson 
2899a2dd95SBruce Richardson struct rte_eth_dev *
2999a2dd95SBruce Richardson eth_find_device(const struct rte_eth_dev *start, rte_eth_cmp_t cmp,
3099a2dd95SBruce Richardson 		const void *data)
3199a2dd95SBruce Richardson {
3299a2dd95SBruce Richardson 	struct rte_eth_dev *edev;
3399a2dd95SBruce Richardson 	ptrdiff_t idx;
3499a2dd95SBruce Richardson 
3599a2dd95SBruce Richardson 	/* Avoid Undefined Behaviour */
3699a2dd95SBruce Richardson 	if (start != NULL &&
3799a2dd95SBruce Richardson 	    (start < &rte_eth_devices[0] ||
3899a2dd95SBruce Richardson 	     start > &rte_eth_devices[RTE_MAX_ETHPORTS]))
3999a2dd95SBruce Richardson 		return NULL;
4099a2dd95SBruce Richardson 	if (start != NULL)
4199a2dd95SBruce Richardson 		idx = eth_dev_to_id(start) + 1;
4299a2dd95SBruce Richardson 	else
4399a2dd95SBruce Richardson 		idx = 0;
4499a2dd95SBruce Richardson 	for (; idx < RTE_MAX_ETHPORTS; idx++) {
4599a2dd95SBruce Richardson 		edev = &rte_eth_devices[idx];
4699a2dd95SBruce Richardson 		if (cmp(edev, data) == 0)
4799a2dd95SBruce Richardson 			return edev;
4899a2dd95SBruce Richardson 	}
4999a2dd95SBruce Richardson 	return NULL;
5099a2dd95SBruce Richardson }
5199a2dd95SBruce Richardson 
5299a2dd95SBruce Richardson /* Put new value into list. */
5399a2dd95SBruce Richardson static int
5499a2dd95SBruce Richardson rte_eth_devargs_enlist(uint16_t *list, uint16_t *len_list,
5599a2dd95SBruce Richardson 		       const uint16_t max_list, uint16_t val)
5699a2dd95SBruce Richardson {
5799a2dd95SBruce Richardson 	uint16_t i;
5899a2dd95SBruce Richardson 
5999a2dd95SBruce Richardson 	for (i = 0; i < *len_list; i++) {
6099a2dd95SBruce Richardson 		if (list[i] == val)
6199a2dd95SBruce Richardson 			return 0;
6299a2dd95SBruce Richardson 	}
6399a2dd95SBruce Richardson 	if (*len_list >= max_list)
6499a2dd95SBruce Richardson 		return -1;
6599a2dd95SBruce Richardson 	list[(*len_list)++] = val;
6699a2dd95SBruce Richardson 	return 0;
6799a2dd95SBruce Richardson }
6899a2dd95SBruce Richardson 
6999a2dd95SBruce Richardson /* Parse and enlist a range expression of "min-max" or a single value. */
7099a2dd95SBruce Richardson static char *
7199a2dd95SBruce Richardson rte_eth_devargs_process_range(char *str, uint16_t *list, uint16_t *len_list,
7299a2dd95SBruce Richardson 	const uint16_t max_list)
7399a2dd95SBruce Richardson {
7499a2dd95SBruce Richardson 	uint16_t lo, hi, val;
7599a2dd95SBruce Richardson 	int result, n = 0;
7699a2dd95SBruce Richardson 	char *pos = str;
7799a2dd95SBruce Richardson 
7899a2dd95SBruce Richardson 	result = sscanf(str, "%hu%n-%hu%n", &lo, &n, &hi, &n);
7999a2dd95SBruce Richardson 	if (result == 1) {
8099a2dd95SBruce Richardson 		if (rte_eth_devargs_enlist(list, len_list, max_list, lo) != 0)
8199a2dd95SBruce Richardson 			return NULL;
8299a2dd95SBruce Richardson 	} else if (result == 2) {
8399a2dd95SBruce Richardson 		if (lo > hi)
8499a2dd95SBruce Richardson 			return NULL;
8599a2dd95SBruce Richardson 		for (val = lo; val <= hi; val++) {
8699a2dd95SBruce Richardson 			if (rte_eth_devargs_enlist(list, len_list, max_list,
8799a2dd95SBruce Richardson 						   val) != 0)
8899a2dd95SBruce Richardson 				return NULL;
8999a2dd95SBruce Richardson 		}
9099a2dd95SBruce Richardson 	} else
9199a2dd95SBruce Richardson 		return NULL;
9299a2dd95SBruce Richardson 	return pos + n;
9399a2dd95SBruce Richardson }
9499a2dd95SBruce Richardson 
9599a2dd95SBruce Richardson /*
9699a2dd95SBruce Richardson  * Parse list of values separated by ",".
9799a2dd95SBruce Richardson  * Each value could be a range [min-max] or single number.
9899a2dd95SBruce Richardson  * Examples:
9999a2dd95SBruce Richardson  *  2               - single
10099a2dd95SBruce Richardson  *  [1,2,3]         - single list
10199a2dd95SBruce Richardson  *  [1,3-5,7,9-11]  - list with singles and ranges
10299a2dd95SBruce Richardson  */
10399a2dd95SBruce Richardson static char *
10499a2dd95SBruce Richardson rte_eth_devargs_process_list(char *str, uint16_t *list, uint16_t *len_list,
10599a2dd95SBruce Richardson 	const uint16_t max_list)
10699a2dd95SBruce Richardson {
10799a2dd95SBruce Richardson 	char *pos = str;
10899a2dd95SBruce Richardson 
10999a2dd95SBruce Richardson 	if (*pos == '[')
11099a2dd95SBruce Richardson 		pos++;
11199a2dd95SBruce Richardson 	while (1) {
11299a2dd95SBruce Richardson 		pos = rte_eth_devargs_process_range(pos, list, len_list,
11399a2dd95SBruce Richardson 						    max_list);
11499a2dd95SBruce Richardson 		if (pos == NULL)
11599a2dd95SBruce Richardson 			return NULL;
11699a2dd95SBruce Richardson 		if (*pos != ',') /* end of list */
11799a2dd95SBruce Richardson 			break;
11899a2dd95SBruce Richardson 		pos++;
11999a2dd95SBruce Richardson 	}
12099a2dd95SBruce Richardson 	if (*str == '[' && *pos != ']')
12199a2dd95SBruce Richardson 		return NULL;
12299a2dd95SBruce Richardson 	if (*pos == ']')
12399a2dd95SBruce Richardson 		pos++;
12499a2dd95SBruce Richardson 	return pos;
12599a2dd95SBruce Richardson }
12699a2dd95SBruce Richardson 
12799a2dd95SBruce Richardson /*
12899a2dd95SBruce Richardson  * Parse representor ports from a single value or lists.
12999a2dd95SBruce Richardson  *
13099a2dd95SBruce Richardson  * Representor format:
13199a2dd95SBruce Richardson  *   #: range or single number of VF representor - legacy
13299a2dd95SBruce Richardson  *   [[c#]pf#]vf#: VF port representor/s
13399a2dd95SBruce Richardson  *   [[c#]pf#]sf#: SF port representor/s
13499a2dd95SBruce Richardson  *   [c#]pf#:      PF port representor/s
13599a2dd95SBruce Richardson  *
13699a2dd95SBruce Richardson  * Examples of #:
13799a2dd95SBruce Richardson  *  2               - single
13899a2dd95SBruce Richardson  *  [1,2,3]         - single list
13999a2dd95SBruce Richardson  *  [1,3-5,7,9-11]  - list with singles and ranges
14099a2dd95SBruce Richardson  */
14199a2dd95SBruce Richardson int
14299a2dd95SBruce Richardson rte_eth_devargs_parse_representor_ports(char *str, void *data)
14399a2dd95SBruce Richardson {
14499a2dd95SBruce Richardson 	struct rte_eth_devargs *eth_da = data;
14599a2dd95SBruce Richardson 
14699a2dd95SBruce Richardson 	if (str[0] == 'c') {
14799a2dd95SBruce Richardson 		str += 1;
14899a2dd95SBruce Richardson 		str = rte_eth_devargs_process_list(str, eth_da->mh_controllers,
14999a2dd95SBruce Richardson 				&eth_da->nb_mh_controllers,
15099a2dd95SBruce Richardson 				RTE_DIM(eth_da->mh_controllers));
15199a2dd95SBruce Richardson 		if (str == NULL)
15299a2dd95SBruce Richardson 			goto done;
15399a2dd95SBruce Richardson 	}
15499a2dd95SBruce Richardson 	if (str[0] == 'p' && str[1] == 'f') {
15599a2dd95SBruce Richardson 		eth_da->type = RTE_ETH_REPRESENTOR_PF;
15699a2dd95SBruce Richardson 		str += 2;
15799a2dd95SBruce Richardson 		str = rte_eth_devargs_process_list(str, eth_da->ports,
15899a2dd95SBruce Richardson 				&eth_da->nb_ports, RTE_DIM(eth_da->ports));
15999a2dd95SBruce Richardson 		if (str == NULL || str[0] == '\0')
16099a2dd95SBruce Richardson 			goto done;
16199a2dd95SBruce Richardson 	} else if (eth_da->nb_mh_controllers > 0) {
16299a2dd95SBruce Richardson 		/* 'c' must followed by 'pf'. */
16399a2dd95SBruce Richardson 		str = NULL;
16499a2dd95SBruce Richardson 		goto done;
16599a2dd95SBruce Richardson 	}
16699a2dd95SBruce Richardson 	if (str[0] == 'v' && str[1] == 'f') {
16799a2dd95SBruce Richardson 		eth_da->type = RTE_ETH_REPRESENTOR_VF;
16899a2dd95SBruce Richardson 		str += 2;
16999a2dd95SBruce Richardson 	} else if (str[0] == 's' && str[1] == 'f') {
17099a2dd95SBruce Richardson 		eth_da->type = RTE_ETH_REPRESENTOR_SF;
17199a2dd95SBruce Richardson 		str += 2;
17299a2dd95SBruce Richardson 	} else {
17399a2dd95SBruce Richardson 		/* 'pf' must followed by 'vf' or 'sf'. */
17499a2dd95SBruce Richardson 		if (eth_da->type == RTE_ETH_REPRESENTOR_PF) {
17599a2dd95SBruce Richardson 			str = NULL;
17699a2dd95SBruce Richardson 			goto done;
17799a2dd95SBruce Richardson 		}
17899a2dd95SBruce Richardson 		eth_da->type = RTE_ETH_REPRESENTOR_VF;
17999a2dd95SBruce Richardson 	}
18099a2dd95SBruce Richardson 	str = rte_eth_devargs_process_list(str, eth_da->representor_ports,
18199a2dd95SBruce Richardson 		&eth_da->nb_representor_ports,
18299a2dd95SBruce Richardson 		RTE_DIM(eth_da->representor_ports));
18399a2dd95SBruce Richardson done:
18499a2dd95SBruce Richardson 	if (str == NULL)
1850e21c7c0SDavid Marchand 		RTE_ETHDEV_LOG_LINE(ERR, "wrong representor format: %s", str);
18699a2dd95SBruce Richardson 	return str == NULL ? -1 : 0;
18799a2dd95SBruce Richardson }
188c87d435aSKonstantin Ananyev 
18941f2f055SDavid Marchand struct dummy_queue {
19041f2f055SDavid Marchand 	bool rx_warn_once;
19141f2f055SDavid Marchand 	bool tx_warn_once;
19241f2f055SDavid Marchand };
19341f2f055SDavid Marchand static struct dummy_queue *dummy_queues_array[RTE_MAX_ETHPORTS][RTE_MAX_QUEUES_PER_PORT];
19441f2f055SDavid Marchand static struct dummy_queue per_port_queues[RTE_MAX_ETHPORTS];
19541f2f055SDavid Marchand RTE_INIT(dummy_queue_init)
19641f2f055SDavid Marchand {
19741f2f055SDavid Marchand 	uint16_t port_id;
19841f2f055SDavid Marchand 
19941f2f055SDavid Marchand 	for (port_id = 0; port_id < RTE_DIM(per_port_queues); port_id++) {
20041f2f055SDavid Marchand 		unsigned int q;
20141f2f055SDavid Marchand 
20241f2f055SDavid Marchand 		for (q = 0; q < RTE_DIM(dummy_queues_array[port_id]); q++)
20341f2f055SDavid Marchand 			dummy_queues_array[port_id][q] = &per_port_queues[port_id];
20441f2f055SDavid Marchand 	}
20541f2f055SDavid Marchand }
20641f2f055SDavid Marchand 
207c87d435aSKonstantin Ananyev static uint16_t
20841f2f055SDavid Marchand dummy_eth_rx_burst(void *rxq,
209c87d435aSKonstantin Ananyev 		__rte_unused struct rte_mbuf **rx_pkts,
210c87d435aSKonstantin Ananyev 		__rte_unused uint16_t nb_pkts)
211c87d435aSKonstantin Ananyev {
21241f2f055SDavid Marchand 	struct dummy_queue *queue = rxq;
21341f2f055SDavid Marchand 	uintptr_t port_id;
21441f2f055SDavid Marchand 
21541f2f055SDavid Marchand 	port_id = queue - per_port_queues;
21641f2f055SDavid Marchand 	if (port_id < RTE_DIM(per_port_queues) && !queue->rx_warn_once) {
2170e21c7c0SDavid Marchand 		RTE_ETHDEV_LOG_LINE(ERR, "lcore %u called rx_pkt_burst for not ready port %"PRIuPTR,
21841f2f055SDavid Marchand 			rte_lcore_id(), port_id);
21941f2f055SDavid Marchand 		rte_dump_stack();
22041f2f055SDavid Marchand 		queue->rx_warn_once = true;
22141f2f055SDavid Marchand 	}
222c87d435aSKonstantin Ananyev 	rte_errno = ENOTSUP;
223c87d435aSKonstantin Ananyev 	return 0;
224c87d435aSKonstantin Ananyev }
225c87d435aSKonstantin Ananyev 
226c87d435aSKonstantin Ananyev static uint16_t
22741f2f055SDavid Marchand dummy_eth_tx_burst(void *txq,
228c87d435aSKonstantin Ananyev 		__rte_unused struct rte_mbuf **tx_pkts,
229c87d435aSKonstantin Ananyev 		__rte_unused uint16_t nb_pkts)
230c87d435aSKonstantin Ananyev {
23141f2f055SDavid Marchand 	struct dummy_queue *queue = txq;
23241f2f055SDavid Marchand 	uintptr_t port_id;
23341f2f055SDavid Marchand 
23441f2f055SDavid Marchand 	port_id = queue - per_port_queues;
23541f2f055SDavid Marchand 	if (port_id < RTE_DIM(per_port_queues) && !queue->tx_warn_once) {
2360e21c7c0SDavid Marchand 		RTE_ETHDEV_LOG_LINE(ERR, "lcore %u called tx_pkt_burst for not ready port %"PRIuPTR,
23741f2f055SDavid Marchand 			rte_lcore_id(), port_id);
23841f2f055SDavid Marchand 		rte_dump_stack();
23941f2f055SDavid Marchand 		queue->tx_warn_once = true;
24041f2f055SDavid Marchand 	}
241c87d435aSKonstantin Ananyev 	rte_errno = ENOTSUP;
242c87d435aSKonstantin Ananyev 	return 0;
243c87d435aSKonstantin Ananyev }
244c87d435aSKonstantin Ananyev 
245c87d435aSKonstantin Ananyev void
246c87d435aSKonstantin Ananyev eth_dev_fp_ops_reset(struct rte_eth_fp_ops *fpo)
247c87d435aSKonstantin Ananyev {
248f7053f01STyler Retzlaff 	static RTE_ATOMIC(void *) dummy_data[RTE_MAX_QUEUES_PER_PORT];
24941f2f055SDavid Marchand 	uintptr_t port_id = fpo - rte_eth_fp_ops;
25041f2f055SDavid Marchand 
25141f2f055SDavid Marchand 	per_port_queues[port_id].rx_warn_once = false;
25241f2f055SDavid Marchand 	per_port_queues[port_id].tx_warn_once = false;
25341f2f055SDavid Marchand 	*fpo = (struct rte_eth_fp_ops) {
254c87d435aSKonstantin Ananyev 		.rx_pkt_burst = dummy_eth_rx_burst,
255c87d435aSKonstantin Ananyev 		.tx_pkt_burst = dummy_eth_tx_burst,
25641f2f055SDavid Marchand 		.rxq = {
25741f2f055SDavid Marchand 			.data = (void **)&dummy_queues_array[port_id],
25841f2f055SDavid Marchand 			.clbk = dummy_data,
25941f2f055SDavid Marchand 		},
26041f2f055SDavid Marchand 		.txq = {
26141f2f055SDavid Marchand 			.data = (void **)&dummy_queues_array[port_id],
26241f2f055SDavid Marchand 			.clbk = dummy_data,
26341f2f055SDavid Marchand 		},
264c87d435aSKonstantin Ananyev 	};
265c87d435aSKonstantin Ananyev }
266c87d435aSKonstantin Ananyev 
267c87d435aSKonstantin Ananyev void
268c87d435aSKonstantin Ananyev eth_dev_fp_ops_setup(struct rte_eth_fp_ops *fpo,
269c87d435aSKonstantin Ananyev 		const struct rte_eth_dev *dev)
270c87d435aSKonstantin Ananyev {
271c87d435aSKonstantin Ananyev 	fpo->rx_pkt_burst = dev->rx_pkt_burst;
272c87d435aSKonstantin Ananyev 	fpo->tx_pkt_burst = dev->tx_pkt_burst;
273c87d435aSKonstantin Ananyev 	fpo->tx_pkt_prepare = dev->tx_pkt_prepare;
274c87d435aSKonstantin Ananyev 	fpo->rx_queue_count = dev->rx_queue_count;
275c87d435aSKonstantin Ananyev 	fpo->rx_descriptor_status = dev->rx_descriptor_status;
276d4b9235fSJerin Jacob 	fpo->tx_queue_count = dev->tx_queue_count;
277c87d435aSKonstantin Ananyev 	fpo->tx_descriptor_status = dev->tx_descriptor_status;
278e43d2b89SFeifei Wang 	fpo->recycle_tx_mbufs_reuse = dev->recycle_tx_mbufs_reuse;
279e43d2b89SFeifei Wang 	fpo->recycle_rx_descriptors_refill = dev->recycle_rx_descriptors_refill;
280c87d435aSKonstantin Ananyev 
281c87d435aSKonstantin Ananyev 	fpo->rxq.data = dev->data->rx_queues;
282f7053f01STyler Retzlaff 	fpo->rxq.clbk = (void * __rte_atomic *)(uintptr_t)dev->post_rx_burst_cbs;
283c87d435aSKonstantin Ananyev 
284c87d435aSKonstantin Ananyev 	fpo->txq.data = dev->data->tx_queues;
285f7053f01STyler Retzlaff 	fpo->txq.clbk = (void * __rte_atomic *)(uintptr_t)dev->pre_tx_burst_cbs;
286c87d435aSKonstantin Ananyev }
2877a093523SKonstantin Ananyev 
2887a093523SKonstantin Ananyev uint16_t
2897a093523SKonstantin Ananyev rte_eth_call_rx_callbacks(uint16_t port_id, uint16_t queue_id,
2907a093523SKonstantin Ananyev 	struct rte_mbuf **rx_pkts, uint16_t nb_rx, uint16_t nb_pkts,
2917a093523SKonstantin Ananyev 	void *opaque)
2927a093523SKonstantin Ananyev {
2937a093523SKonstantin Ananyev 	const struct rte_eth_rxtx_callback *cb = opaque;
2947a093523SKonstantin Ananyev 
2957a093523SKonstantin Ananyev 	while (cb != NULL) {
2967a093523SKonstantin Ananyev 		nb_rx = cb->fn.rx(port_id, queue_id, rx_pkts, nb_rx,
2977a093523SKonstantin Ananyev 				nb_pkts, cb->param);
2987a093523SKonstantin Ananyev 		cb = cb->next;
2997a093523SKonstantin Ananyev 	}
3007a093523SKonstantin Ananyev 
301*e075ca1dSAdel Belkhiri 	if (unlikely(nb_rx))
302*e075ca1dSAdel Belkhiri 		rte_eth_trace_call_rx_callbacks_nonempty(port_id, queue_id, (void **)rx_pkts,
3036679cf21SAnkur Dwivedi 						nb_rx, nb_pkts);
304*e075ca1dSAdel Belkhiri 	else
305*e075ca1dSAdel Belkhiri 		rte_eth_trace_call_rx_callbacks_empty(port_id, queue_id, (void **)rx_pkts,
306*e075ca1dSAdel Belkhiri 						nb_pkts);
3076679cf21SAnkur Dwivedi 
3087a093523SKonstantin Ananyev 	return nb_rx;
3097a093523SKonstantin Ananyev }
3107a093523SKonstantin Ananyev 
3117a093523SKonstantin Ananyev uint16_t
3127a093523SKonstantin Ananyev rte_eth_call_tx_callbacks(uint16_t port_id, uint16_t queue_id,
3137a093523SKonstantin Ananyev 	struct rte_mbuf **tx_pkts, uint16_t nb_pkts, void *opaque)
3147a093523SKonstantin Ananyev {
3157a093523SKonstantin Ananyev 	const struct rte_eth_rxtx_callback *cb = opaque;
3167a093523SKonstantin Ananyev 
3177a093523SKonstantin Ananyev 	while (cb != NULL) {
3187a093523SKonstantin Ananyev 		nb_pkts = cb->fn.tx(port_id, queue_id, tx_pkts, nb_pkts,
3197a093523SKonstantin Ananyev 				cb->param);
3207a093523SKonstantin Ananyev 		cb = cb->next;
3217a093523SKonstantin Ananyev 	}
3227a093523SKonstantin Ananyev 
3236679cf21SAnkur Dwivedi 	rte_eth_trace_call_tx_callbacks(port_id, queue_id, (void **)tx_pkts,
3246679cf21SAnkur Dwivedi 					nb_pkts);
3256679cf21SAnkur Dwivedi 
3267a093523SKonstantin Ananyev 	return nb_pkts;
3277a093523SKonstantin Ananyev }
3284b4f810eSFerruh Yigit 
3297fe371ebSDavid Marchand void *
3304b4f810eSFerruh Yigit eth_dev_shared_data_prepare(void)
3314b4f810eSFerruh Yigit {
3324b4f810eSFerruh Yigit 	const struct rte_memzone *mz;
3334b4f810eSFerruh Yigit 
3344b4f810eSFerruh Yigit 	if (rte_eal_process_type() == RTE_PROC_PRIMARY) {
335a9d4039bSDavid Marchand 		const unsigned int flags = 0;
336a9d4039bSDavid Marchand 
337a9d4039bSDavid Marchand 		if (eth_dev_shared_mz != NULL)
338a9d4039bSDavid Marchand 			goto out;
339a9d4039bSDavid Marchand 
3404b4f810eSFerruh Yigit 		/* Allocate port data and ownership shared memory. */
3414b4f810eSFerruh Yigit 		mz = rte_memzone_reserve(MZ_RTE_ETH_DEV_DATA,
3424b4f810eSFerruh Yigit 				sizeof(*eth_dev_shared_data),
3434b4f810eSFerruh Yigit 				rte_socket_id(), flags);
3447fe371ebSDavid Marchand 		if (mz == NULL) {
3450e21c7c0SDavid Marchand 			RTE_ETHDEV_LOG_LINE(ERR, "Cannot allocate ethdev shared data");
3467fe371ebSDavid Marchand 			goto out;
3477fe371ebSDavid Marchand 		}
3484b4f810eSFerruh Yigit 
34936c46e73SDavid Marchand 		eth_dev_shared_mz = mz;
3504b4f810eSFerruh Yigit 		eth_dev_shared_data = mz->addr;
35136c46e73SDavid Marchand 		eth_dev_shared_data->allocated_owners = 0;
3524b4f810eSFerruh Yigit 		eth_dev_shared_data->next_owner_id =
3534b4f810eSFerruh Yigit 			RTE_ETH_DEV_NO_OWNER + 1;
35436c46e73SDavid Marchand 		eth_dev_shared_data->allocated_ports = 0;
3554b4f810eSFerruh Yigit 		memset(eth_dev_shared_data->data, 0,
3564b4f810eSFerruh Yigit 		       sizeof(eth_dev_shared_data->data));
357a9d4039bSDavid Marchand 	} else {
358a9d4039bSDavid Marchand 		mz = rte_memzone_lookup(MZ_RTE_ETH_DEV_DATA);
359a9d4039bSDavid Marchand 		if (mz == NULL) {
360a9d4039bSDavid Marchand 			/* Clean remaining any traces of a previous shared mem */
361a9d4039bSDavid Marchand 			eth_dev_shared_mz = NULL;
362a9d4039bSDavid Marchand 			eth_dev_shared_data = NULL;
3630e21c7c0SDavid Marchand 			RTE_ETHDEV_LOG_LINE(ERR, "Cannot lookup ethdev shared data");
364a9d4039bSDavid Marchand 			goto out;
3654b4f810eSFerruh Yigit 		}
366a9d4039bSDavid Marchand 		if (mz == eth_dev_shared_mz && mz->addr == eth_dev_shared_data)
367a9d4039bSDavid Marchand 			goto out;
368a9d4039bSDavid Marchand 
369a9d4039bSDavid Marchand 		/* Shared mem changed in primary process, refresh pointers */
370a9d4039bSDavid Marchand 		eth_dev_shared_mz = mz;
371a9d4039bSDavid Marchand 		eth_dev_shared_data = mz->addr;
3724b4f810eSFerruh Yigit 	}
3737fe371ebSDavid Marchand out:
3747fe371ebSDavid Marchand 	return eth_dev_shared_data;
3754b4f810eSFerruh Yigit }
3764b4f810eSFerruh Yigit 
3774b4f810eSFerruh Yigit void
37836c46e73SDavid Marchand eth_dev_shared_data_release(void)
37936c46e73SDavid Marchand {
38036c46e73SDavid Marchand 	RTE_ASSERT(rte_eal_process_type() == RTE_PROC_PRIMARY);
38136c46e73SDavid Marchand 
38236c46e73SDavid Marchand 	if (eth_dev_shared_data->allocated_ports != 0)
38336c46e73SDavid Marchand 		return;
38436c46e73SDavid Marchand 	if (eth_dev_shared_data->allocated_owners != 0)
38536c46e73SDavid Marchand 		return;
38636c46e73SDavid Marchand 
38736c46e73SDavid Marchand 	rte_memzone_free(eth_dev_shared_mz);
38836c46e73SDavid Marchand 	eth_dev_shared_mz = NULL;
38936c46e73SDavid Marchand 	eth_dev_shared_data = NULL;
39036c46e73SDavid Marchand }
39136c46e73SDavid Marchand 
39236c46e73SDavid Marchand void
3934b4f810eSFerruh Yigit eth_dev_rxq_release(struct rte_eth_dev *dev, uint16_t qid)
3944b4f810eSFerruh Yigit {
3954b4f810eSFerruh Yigit 	void **rxq = dev->data->rx_queues;
3964b4f810eSFerruh Yigit 
3974b4f810eSFerruh Yigit 	if (rxq[qid] == NULL)
3984b4f810eSFerruh Yigit 		return;
3994b4f810eSFerruh Yigit 
4004b4f810eSFerruh Yigit 	if (dev->dev_ops->rx_queue_release != NULL)
4014b4f810eSFerruh Yigit 		(*dev->dev_ops->rx_queue_release)(dev, qid);
4024b4f810eSFerruh Yigit 	rxq[qid] = NULL;
4034b4f810eSFerruh Yigit }
4044b4f810eSFerruh Yigit 
4054b4f810eSFerruh Yigit void
4064b4f810eSFerruh Yigit eth_dev_txq_release(struct rte_eth_dev *dev, uint16_t qid)
4074b4f810eSFerruh Yigit {
4084b4f810eSFerruh Yigit 	void **txq = dev->data->tx_queues;
4094b4f810eSFerruh Yigit 
4104b4f810eSFerruh Yigit 	if (txq[qid] == NULL)
4114b4f810eSFerruh Yigit 		return;
4124b4f810eSFerruh Yigit 
4134b4f810eSFerruh Yigit 	if (dev->dev_ops->tx_queue_release != NULL)
4144b4f810eSFerruh Yigit 		(*dev->dev_ops->tx_queue_release)(dev, qid);
4154b4f810eSFerruh Yigit 	txq[qid] = NULL;
4164b4f810eSFerruh Yigit }
4174b4f810eSFerruh Yigit 
4184b4f810eSFerruh Yigit int
4194b4f810eSFerruh Yigit eth_dev_rx_queue_config(struct rte_eth_dev *dev, uint16_t nb_queues)
4204b4f810eSFerruh Yigit {
4214b4f810eSFerruh Yigit 	uint16_t old_nb_queues = dev->data->nb_rx_queues;
4224b4f810eSFerruh Yigit 	unsigned int i;
4234b4f810eSFerruh Yigit 
4244b4f810eSFerruh Yigit 	if (dev->data->rx_queues == NULL && nb_queues != 0) { /* first time configuration */
4254b4f810eSFerruh Yigit 		dev->data->rx_queues = rte_zmalloc("ethdev->rx_queues",
4264b4f810eSFerruh Yigit 				sizeof(dev->data->rx_queues[0]) *
4274b4f810eSFerruh Yigit 				RTE_MAX_QUEUES_PER_PORT,
4284b4f810eSFerruh Yigit 				RTE_CACHE_LINE_SIZE);
4294b4f810eSFerruh Yigit 		if (dev->data->rx_queues == NULL) {
4304b4f810eSFerruh Yigit 			dev->data->nb_rx_queues = 0;
4314b4f810eSFerruh Yigit 			return -(ENOMEM);
4324b4f810eSFerruh Yigit 		}
4334b4f810eSFerruh Yigit 	} else if (dev->data->rx_queues != NULL && nb_queues != 0) { /* re-configure */
4344b4f810eSFerruh Yigit 		for (i = nb_queues; i < old_nb_queues; i++)
4354b4f810eSFerruh Yigit 			eth_dev_rxq_release(dev, i);
4364b4f810eSFerruh Yigit 
4374b4f810eSFerruh Yigit 	} else if (dev->data->rx_queues != NULL && nb_queues == 0) {
4384b4f810eSFerruh Yigit 		for (i = nb_queues; i < old_nb_queues; i++)
4394b4f810eSFerruh Yigit 			eth_dev_rxq_release(dev, i);
4404b4f810eSFerruh Yigit 
4414b4f810eSFerruh Yigit 		rte_free(dev->data->rx_queues);
4424b4f810eSFerruh Yigit 		dev->data->rx_queues = NULL;
4434b4f810eSFerruh Yigit 	}
4444b4f810eSFerruh Yigit 	dev->data->nb_rx_queues = nb_queues;
4454b4f810eSFerruh Yigit 	return 0;
4464b4f810eSFerruh Yigit }
4474b4f810eSFerruh Yigit 
4484b4f810eSFerruh Yigit int
4494b4f810eSFerruh Yigit eth_dev_tx_queue_config(struct rte_eth_dev *dev, uint16_t nb_queues)
4504b4f810eSFerruh Yigit {
4514b4f810eSFerruh Yigit 	uint16_t old_nb_queues = dev->data->nb_tx_queues;
4524b4f810eSFerruh Yigit 	unsigned int i;
4534b4f810eSFerruh Yigit 
4544b4f810eSFerruh Yigit 	if (dev->data->tx_queues == NULL && nb_queues != 0) { /* first time configuration */
4554b4f810eSFerruh Yigit 		dev->data->tx_queues = rte_zmalloc("ethdev->tx_queues",
4564b4f810eSFerruh Yigit 				sizeof(dev->data->tx_queues[0]) *
4574b4f810eSFerruh Yigit 				RTE_MAX_QUEUES_PER_PORT,
4584b4f810eSFerruh Yigit 				RTE_CACHE_LINE_SIZE);
4594b4f810eSFerruh Yigit 		if (dev->data->tx_queues == NULL) {
4604b4f810eSFerruh Yigit 			dev->data->nb_tx_queues = 0;
4614b4f810eSFerruh Yigit 			return -(ENOMEM);
4624b4f810eSFerruh Yigit 		}
4634b4f810eSFerruh Yigit 	} else if (dev->data->tx_queues != NULL && nb_queues != 0) { /* re-configure */
4644b4f810eSFerruh Yigit 		for (i = nb_queues; i < old_nb_queues; i++)
4654b4f810eSFerruh Yigit 			eth_dev_txq_release(dev, i);
4664b4f810eSFerruh Yigit 
4674b4f810eSFerruh Yigit 	} else if (dev->data->tx_queues != NULL && nb_queues == 0) {
4684b4f810eSFerruh Yigit 		for (i = nb_queues; i < old_nb_queues; i++)
4694b4f810eSFerruh Yigit 			eth_dev_txq_release(dev, i);
4704b4f810eSFerruh Yigit 
4714b4f810eSFerruh Yigit 		rte_free(dev->data->tx_queues);
4724b4f810eSFerruh Yigit 		dev->data->tx_queues = NULL;
4734b4f810eSFerruh Yigit 	}
4744b4f810eSFerruh Yigit 	dev->data->nb_tx_queues = nb_queues;
4754b4f810eSFerruh Yigit 	return 0;
4764b4f810eSFerruh Yigit }
477