xref: /dpdk/lib/ethdev/ethdev_private.c (revision 72c00ae9dba7fc3f8c892b0354b956e885a25770)
1 /* SPDX-License-Identifier: BSD-3-Clause
2  * Copyright(c) 2018 Gaëtan Rivet
3  */
4 
5 #include <rte_debug.h>
6 #include "rte_ethdev.h"
7 #include "ethdev_driver.h"
8 #include "ethdev_private.h"
9 
10 uint16_t
11 eth_dev_to_id(const struct rte_eth_dev *dev)
12 {
13 	if (dev == NULL)
14 		return RTE_MAX_ETHPORTS;
15 	return dev - rte_eth_devices;
16 }
17 
18 struct rte_eth_dev *
19 eth_find_device(const struct rte_eth_dev *start, rte_eth_cmp_t cmp,
20 		const void *data)
21 {
22 	struct rte_eth_dev *edev;
23 	ptrdiff_t idx;
24 
25 	/* Avoid Undefined Behaviour */
26 	if (start != NULL &&
27 	    (start < &rte_eth_devices[0] ||
28 	     start > &rte_eth_devices[RTE_MAX_ETHPORTS]))
29 		return NULL;
30 	if (start != NULL)
31 		idx = eth_dev_to_id(start) + 1;
32 	else
33 		idx = 0;
34 	for (; idx < RTE_MAX_ETHPORTS; idx++) {
35 		edev = &rte_eth_devices[idx];
36 		if (cmp(edev, data) == 0)
37 			return edev;
38 	}
39 	return NULL;
40 }
41 
42 /* Put new value into list. */
43 static int
44 rte_eth_devargs_enlist(uint16_t *list, uint16_t *len_list,
45 		       const uint16_t max_list, uint16_t val)
46 {
47 	uint16_t i;
48 
49 	for (i = 0; i < *len_list; i++) {
50 		if (list[i] == val)
51 			return 0;
52 	}
53 	if (*len_list >= max_list)
54 		return -1;
55 	list[(*len_list)++] = val;
56 	return 0;
57 }
58 
59 /* Parse and enlist a range expression of "min-max" or a single value. */
60 static char *
61 rte_eth_devargs_process_range(char *str, uint16_t *list, uint16_t *len_list,
62 	const uint16_t max_list)
63 {
64 	uint16_t lo, hi, val;
65 	int result, n = 0;
66 	char *pos = str;
67 
68 	result = sscanf(str, "%hu%n-%hu%n", &lo, &n, &hi, &n);
69 	if (result == 1) {
70 		if (rte_eth_devargs_enlist(list, len_list, max_list, lo) != 0)
71 			return NULL;
72 	} else if (result == 2) {
73 		if (lo > hi)
74 			return NULL;
75 		for (val = lo; val <= hi; val++) {
76 			if (rte_eth_devargs_enlist(list, len_list, max_list,
77 						   val) != 0)
78 				return NULL;
79 		}
80 	} else
81 		return NULL;
82 	return pos + n;
83 }
84 
85 /*
86  * Parse list of values separated by ",".
87  * Each value could be a range [min-max] or single number.
88  * Examples:
89  *  2               - single
90  *  [1,2,3]         - single list
91  *  [1,3-5,7,9-11]  - list with singles and ranges
92  */
93 static char *
94 rte_eth_devargs_process_list(char *str, uint16_t *list, uint16_t *len_list,
95 	const uint16_t max_list)
96 {
97 	char *pos = str;
98 
99 	if (*pos == '[')
100 		pos++;
101 	while (1) {
102 		pos = rte_eth_devargs_process_range(pos, list, len_list,
103 						    max_list);
104 		if (pos == NULL)
105 			return NULL;
106 		if (*pos != ',') /* end of list */
107 			break;
108 		pos++;
109 	}
110 	if (*str == '[' && *pos != ']')
111 		return NULL;
112 	if (*pos == ']')
113 		pos++;
114 	return pos;
115 }
116 
117 /*
118  * Parse representor ports from a single value or lists.
119  *
120  * Representor format:
121  *   #: range or single number of VF representor - legacy
122  *   [[c#]pf#]vf#: VF port representor/s
123  *   [[c#]pf#]sf#: SF port representor/s
124  *   [c#]pf#:      PF port representor/s
125  *
126  * Examples of #:
127  *  2               - single
128  *  [1,2,3]         - single list
129  *  [1,3-5,7,9-11]  - list with singles and ranges
130  */
131 int
132 rte_eth_devargs_parse_representor_ports(char *str, void *data)
133 {
134 	struct rte_eth_devargs *eth_da = data;
135 
136 	if (str[0] == 'c') {
137 		str += 1;
138 		str = rte_eth_devargs_process_list(str, eth_da->mh_controllers,
139 				&eth_da->nb_mh_controllers,
140 				RTE_DIM(eth_da->mh_controllers));
141 		if (str == NULL)
142 			goto done;
143 	}
144 	if (str[0] == 'p' && str[1] == 'f') {
145 		eth_da->type = RTE_ETH_REPRESENTOR_PF;
146 		str += 2;
147 		str = rte_eth_devargs_process_list(str, eth_da->ports,
148 				&eth_da->nb_ports, RTE_DIM(eth_da->ports));
149 		if (str == NULL || str[0] == '\0')
150 			goto done;
151 	} else if (eth_da->nb_mh_controllers > 0) {
152 		/* 'c' must followed by 'pf'. */
153 		str = NULL;
154 		goto done;
155 	}
156 	if (str[0] == 'v' && str[1] == 'f') {
157 		eth_da->type = RTE_ETH_REPRESENTOR_VF;
158 		str += 2;
159 	} else if (str[0] == 's' && str[1] == 'f') {
160 		eth_da->type = RTE_ETH_REPRESENTOR_SF;
161 		str += 2;
162 	} else {
163 		/* 'pf' must followed by 'vf' or 'sf'. */
164 		if (eth_da->type == RTE_ETH_REPRESENTOR_PF) {
165 			str = NULL;
166 			goto done;
167 		}
168 		eth_da->type = RTE_ETH_REPRESENTOR_VF;
169 	}
170 	str = rte_eth_devargs_process_list(str, eth_da->representor_ports,
171 		&eth_da->nb_representor_ports,
172 		RTE_DIM(eth_da->representor_ports));
173 done:
174 	if (str == NULL)
175 		RTE_LOG(ERR, EAL, "wrong representor format: %s\n", str);
176 	return str == NULL ? -1 : 0;
177 }
178 
179 struct dummy_queue {
180 	bool rx_warn_once;
181 	bool tx_warn_once;
182 };
183 static struct dummy_queue *dummy_queues_array[RTE_MAX_ETHPORTS][RTE_MAX_QUEUES_PER_PORT];
184 static struct dummy_queue per_port_queues[RTE_MAX_ETHPORTS];
185 RTE_INIT(dummy_queue_init)
186 {
187 	uint16_t port_id;
188 
189 	for (port_id = 0; port_id < RTE_DIM(per_port_queues); port_id++) {
190 		unsigned int q;
191 
192 		for (q = 0; q < RTE_DIM(dummy_queues_array[port_id]); q++)
193 			dummy_queues_array[port_id][q] = &per_port_queues[port_id];
194 	}
195 }
196 
197 static uint16_t
198 dummy_eth_rx_burst(void *rxq,
199 		__rte_unused struct rte_mbuf **rx_pkts,
200 		__rte_unused uint16_t nb_pkts)
201 {
202 	struct dummy_queue *queue = rxq;
203 	uintptr_t port_id;
204 
205 	port_id = queue - per_port_queues;
206 	if (port_id < RTE_DIM(per_port_queues) && !queue->rx_warn_once) {
207 		RTE_ETHDEV_LOG(ERR, "lcore %u called rx_pkt_burst for not ready port %"PRIuPTR"\n",
208 			rte_lcore_id(), port_id);
209 		rte_dump_stack();
210 		queue->rx_warn_once = true;
211 	}
212 	rte_errno = ENOTSUP;
213 	return 0;
214 }
215 
216 static uint16_t
217 dummy_eth_tx_burst(void *txq,
218 		__rte_unused struct rte_mbuf **tx_pkts,
219 		__rte_unused uint16_t nb_pkts)
220 {
221 	struct dummy_queue *queue = txq;
222 	uintptr_t port_id;
223 
224 	port_id = queue - per_port_queues;
225 	if (port_id < RTE_DIM(per_port_queues) && !queue->tx_warn_once) {
226 		RTE_ETHDEV_LOG(ERR, "lcore %u called tx_pkt_burst for not ready port %"PRIuPTR"\n",
227 			rte_lcore_id(), port_id);
228 		rte_dump_stack();
229 		queue->tx_warn_once = true;
230 	}
231 	rte_errno = ENOTSUP;
232 	return 0;
233 }
234 
235 void
236 eth_dev_fp_ops_reset(struct rte_eth_fp_ops *fpo)
237 {
238 	static void *dummy_data[RTE_MAX_QUEUES_PER_PORT];
239 	uintptr_t port_id = fpo - rte_eth_fp_ops;
240 
241 	per_port_queues[port_id].rx_warn_once = false;
242 	per_port_queues[port_id].tx_warn_once = false;
243 	*fpo = (struct rte_eth_fp_ops) {
244 		.rx_pkt_burst = dummy_eth_rx_burst,
245 		.tx_pkt_burst = dummy_eth_tx_burst,
246 		.rxq = {
247 			.data = (void **)&dummy_queues_array[port_id],
248 			.clbk = dummy_data,
249 		},
250 		.txq = {
251 			.data = (void **)&dummy_queues_array[port_id],
252 			.clbk = dummy_data,
253 		},
254 	};
255 }
256 
257 void
258 eth_dev_fp_ops_setup(struct rte_eth_fp_ops *fpo,
259 		const struct rte_eth_dev *dev)
260 {
261 	fpo->rx_pkt_burst = dev->rx_pkt_burst;
262 	fpo->tx_pkt_burst = dev->tx_pkt_burst;
263 	fpo->tx_pkt_prepare = dev->tx_pkt_prepare;
264 	fpo->rx_queue_count = dev->rx_queue_count;
265 	fpo->rx_descriptor_status = dev->rx_descriptor_status;
266 	fpo->tx_descriptor_status = dev->tx_descriptor_status;
267 
268 	fpo->rxq.data = dev->data->rx_queues;
269 	fpo->rxq.clbk = (void **)(uintptr_t)dev->post_rx_burst_cbs;
270 
271 	fpo->txq.data = dev->data->tx_queues;
272 	fpo->txq.clbk = (void **)(uintptr_t)dev->pre_tx_burst_cbs;
273 }
274 
275 uint16_t
276 rte_eth_call_rx_callbacks(uint16_t port_id, uint16_t queue_id,
277 	struct rte_mbuf **rx_pkts, uint16_t nb_rx, uint16_t nb_pkts,
278 	void *opaque)
279 {
280 	const struct rte_eth_rxtx_callback *cb = opaque;
281 
282 	while (cb != NULL) {
283 		nb_rx = cb->fn.rx(port_id, queue_id, rx_pkts, nb_rx,
284 				nb_pkts, cb->param);
285 		cb = cb->next;
286 	}
287 
288 	return nb_rx;
289 }
290 
291 uint16_t
292 rte_eth_call_tx_callbacks(uint16_t port_id, uint16_t queue_id,
293 	struct rte_mbuf **tx_pkts, uint16_t nb_pkts, void *opaque)
294 {
295 	const struct rte_eth_rxtx_callback *cb = opaque;
296 
297 	while (cb != NULL) {
298 		nb_pkts = cb->fn.tx(port_id, queue_id, tx_pkts, nb_pkts,
299 				cb->param);
300 		cb = cb->next;
301 	}
302 
303 	return nb_pkts;
304 }
305