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