xref: /dpdk/lib/ethdev/ethdev_private.c (revision 99a2dd95)
1*99a2dd95SBruce Richardson /* SPDX-License-Identifier: BSD-3-Clause
2*99a2dd95SBruce Richardson  * Copyright(c) 2018 Gaëtan Rivet
3*99a2dd95SBruce Richardson  */
4*99a2dd95SBruce Richardson 
5*99a2dd95SBruce Richardson #include "rte_ethdev.h"
6*99a2dd95SBruce Richardson #include "ethdev_driver.h"
7*99a2dd95SBruce Richardson #include "ethdev_private.h"
8*99a2dd95SBruce Richardson 
9*99a2dd95SBruce Richardson uint16_t
10*99a2dd95SBruce Richardson eth_dev_to_id(const struct rte_eth_dev *dev)
11*99a2dd95SBruce Richardson {
12*99a2dd95SBruce Richardson 	if (dev == NULL)
13*99a2dd95SBruce Richardson 		return RTE_MAX_ETHPORTS;
14*99a2dd95SBruce Richardson 	return dev - rte_eth_devices;
15*99a2dd95SBruce Richardson }
16*99a2dd95SBruce Richardson 
17*99a2dd95SBruce Richardson struct rte_eth_dev *
18*99a2dd95SBruce Richardson eth_find_device(const struct rte_eth_dev *start, rte_eth_cmp_t cmp,
19*99a2dd95SBruce Richardson 		const void *data)
20*99a2dd95SBruce Richardson {
21*99a2dd95SBruce Richardson 	struct rte_eth_dev *edev;
22*99a2dd95SBruce Richardson 	ptrdiff_t idx;
23*99a2dd95SBruce Richardson 
24*99a2dd95SBruce Richardson 	/* Avoid Undefined Behaviour */
25*99a2dd95SBruce Richardson 	if (start != NULL &&
26*99a2dd95SBruce Richardson 	    (start < &rte_eth_devices[0] ||
27*99a2dd95SBruce Richardson 	     start > &rte_eth_devices[RTE_MAX_ETHPORTS]))
28*99a2dd95SBruce Richardson 		return NULL;
29*99a2dd95SBruce Richardson 	if (start != NULL)
30*99a2dd95SBruce Richardson 		idx = eth_dev_to_id(start) + 1;
31*99a2dd95SBruce Richardson 	else
32*99a2dd95SBruce Richardson 		idx = 0;
33*99a2dd95SBruce Richardson 	for (; idx < RTE_MAX_ETHPORTS; idx++) {
34*99a2dd95SBruce Richardson 		edev = &rte_eth_devices[idx];
35*99a2dd95SBruce Richardson 		if (cmp(edev, data) == 0)
36*99a2dd95SBruce Richardson 			return edev;
37*99a2dd95SBruce Richardson 	}
38*99a2dd95SBruce Richardson 	return NULL;
39*99a2dd95SBruce Richardson }
40*99a2dd95SBruce Richardson 
41*99a2dd95SBruce Richardson /* Put new value into list. */
42*99a2dd95SBruce Richardson static int
43*99a2dd95SBruce Richardson rte_eth_devargs_enlist(uint16_t *list, uint16_t *len_list,
44*99a2dd95SBruce Richardson 		       const uint16_t max_list, uint16_t val)
45*99a2dd95SBruce Richardson {
46*99a2dd95SBruce Richardson 	uint16_t i;
47*99a2dd95SBruce Richardson 
48*99a2dd95SBruce Richardson 	for (i = 0; i < *len_list; i++) {
49*99a2dd95SBruce Richardson 		if (list[i] == val)
50*99a2dd95SBruce Richardson 			return 0;
51*99a2dd95SBruce Richardson 	}
52*99a2dd95SBruce Richardson 	if (*len_list >= max_list)
53*99a2dd95SBruce Richardson 		return -1;
54*99a2dd95SBruce Richardson 	list[(*len_list)++] = val;
55*99a2dd95SBruce Richardson 	return 0;
56*99a2dd95SBruce Richardson }
57*99a2dd95SBruce Richardson 
58*99a2dd95SBruce Richardson /* Parse and enlist a range expression of "min-max" or a single value. */
59*99a2dd95SBruce Richardson static char *
60*99a2dd95SBruce Richardson rte_eth_devargs_process_range(char *str, uint16_t *list, uint16_t *len_list,
61*99a2dd95SBruce Richardson 	const uint16_t max_list)
62*99a2dd95SBruce Richardson {
63*99a2dd95SBruce Richardson 	uint16_t lo, hi, val;
64*99a2dd95SBruce Richardson 	int result, n = 0;
65*99a2dd95SBruce Richardson 	char *pos = str;
66*99a2dd95SBruce Richardson 
67*99a2dd95SBruce Richardson 	result = sscanf(str, "%hu%n-%hu%n", &lo, &n, &hi, &n);
68*99a2dd95SBruce Richardson 	if (result == 1) {
69*99a2dd95SBruce Richardson 		if (rte_eth_devargs_enlist(list, len_list, max_list, lo) != 0)
70*99a2dd95SBruce Richardson 			return NULL;
71*99a2dd95SBruce Richardson 	} else if (result == 2) {
72*99a2dd95SBruce Richardson 		if (lo > hi)
73*99a2dd95SBruce Richardson 			return NULL;
74*99a2dd95SBruce Richardson 		for (val = lo; val <= hi; val++) {
75*99a2dd95SBruce Richardson 			if (rte_eth_devargs_enlist(list, len_list, max_list,
76*99a2dd95SBruce Richardson 						   val) != 0)
77*99a2dd95SBruce Richardson 				return NULL;
78*99a2dd95SBruce Richardson 		}
79*99a2dd95SBruce Richardson 	} else
80*99a2dd95SBruce Richardson 		return NULL;
81*99a2dd95SBruce Richardson 	return pos + n;
82*99a2dd95SBruce Richardson }
83*99a2dd95SBruce Richardson 
84*99a2dd95SBruce Richardson /*
85*99a2dd95SBruce Richardson  * Parse list of values separated by ",".
86*99a2dd95SBruce Richardson  * Each value could be a range [min-max] or single number.
87*99a2dd95SBruce Richardson  * Examples:
88*99a2dd95SBruce Richardson  *  2               - single
89*99a2dd95SBruce Richardson  *  [1,2,3]         - single list
90*99a2dd95SBruce Richardson  *  [1,3-5,7,9-11]  - list with singles and ranges
91*99a2dd95SBruce Richardson  */
92*99a2dd95SBruce Richardson static char *
93*99a2dd95SBruce Richardson rte_eth_devargs_process_list(char *str, uint16_t *list, uint16_t *len_list,
94*99a2dd95SBruce Richardson 	const uint16_t max_list)
95*99a2dd95SBruce Richardson {
96*99a2dd95SBruce Richardson 	char *pos = str;
97*99a2dd95SBruce Richardson 
98*99a2dd95SBruce Richardson 	if (*pos == '[')
99*99a2dd95SBruce Richardson 		pos++;
100*99a2dd95SBruce Richardson 	while (1) {
101*99a2dd95SBruce Richardson 		pos = rte_eth_devargs_process_range(pos, list, len_list,
102*99a2dd95SBruce Richardson 						    max_list);
103*99a2dd95SBruce Richardson 		if (pos == NULL)
104*99a2dd95SBruce Richardson 			return NULL;
105*99a2dd95SBruce Richardson 		if (*pos != ',') /* end of list */
106*99a2dd95SBruce Richardson 			break;
107*99a2dd95SBruce Richardson 		pos++;
108*99a2dd95SBruce Richardson 	}
109*99a2dd95SBruce Richardson 	if (*str == '[' && *pos != ']')
110*99a2dd95SBruce Richardson 		return NULL;
111*99a2dd95SBruce Richardson 	if (*pos == ']')
112*99a2dd95SBruce Richardson 		pos++;
113*99a2dd95SBruce Richardson 	return pos;
114*99a2dd95SBruce Richardson }
115*99a2dd95SBruce Richardson 
116*99a2dd95SBruce Richardson /*
117*99a2dd95SBruce Richardson  * Parse representor ports from a single value or lists.
118*99a2dd95SBruce Richardson  *
119*99a2dd95SBruce Richardson  * Representor format:
120*99a2dd95SBruce Richardson  *   #: range or single number of VF representor - legacy
121*99a2dd95SBruce Richardson  *   [[c#]pf#]vf#: VF port representor/s
122*99a2dd95SBruce Richardson  *   [[c#]pf#]sf#: SF port representor/s
123*99a2dd95SBruce Richardson  *   [c#]pf#:      PF port representor/s
124*99a2dd95SBruce Richardson  *
125*99a2dd95SBruce Richardson  * Examples of #:
126*99a2dd95SBruce Richardson  *  2               - single
127*99a2dd95SBruce Richardson  *  [1,2,3]         - single list
128*99a2dd95SBruce Richardson  *  [1,3-5,7,9-11]  - list with singles and ranges
129*99a2dd95SBruce Richardson  */
130*99a2dd95SBruce Richardson int
131*99a2dd95SBruce Richardson rte_eth_devargs_parse_representor_ports(char *str, void *data)
132*99a2dd95SBruce Richardson {
133*99a2dd95SBruce Richardson 	struct rte_eth_devargs *eth_da = data;
134*99a2dd95SBruce Richardson 
135*99a2dd95SBruce Richardson 	if (str[0] == 'c') {
136*99a2dd95SBruce Richardson 		str += 1;
137*99a2dd95SBruce Richardson 		str = rte_eth_devargs_process_list(str, eth_da->mh_controllers,
138*99a2dd95SBruce Richardson 				&eth_da->nb_mh_controllers,
139*99a2dd95SBruce Richardson 				RTE_DIM(eth_da->mh_controllers));
140*99a2dd95SBruce Richardson 		if (str == NULL)
141*99a2dd95SBruce Richardson 			goto done;
142*99a2dd95SBruce Richardson 	}
143*99a2dd95SBruce Richardson 	if (str[0] == 'p' && str[1] == 'f') {
144*99a2dd95SBruce Richardson 		eth_da->type = RTE_ETH_REPRESENTOR_PF;
145*99a2dd95SBruce Richardson 		str += 2;
146*99a2dd95SBruce Richardson 		str = rte_eth_devargs_process_list(str, eth_da->ports,
147*99a2dd95SBruce Richardson 				&eth_da->nb_ports, RTE_DIM(eth_da->ports));
148*99a2dd95SBruce Richardson 		if (str == NULL || str[0] == '\0')
149*99a2dd95SBruce Richardson 			goto done;
150*99a2dd95SBruce Richardson 	} else if (eth_da->nb_mh_controllers > 0) {
151*99a2dd95SBruce Richardson 		/* 'c' must followed by 'pf'. */
152*99a2dd95SBruce Richardson 		str = NULL;
153*99a2dd95SBruce Richardson 		goto done;
154*99a2dd95SBruce Richardson 	}
155*99a2dd95SBruce Richardson 	if (str[0] == 'v' && str[1] == 'f') {
156*99a2dd95SBruce Richardson 		eth_da->type = RTE_ETH_REPRESENTOR_VF;
157*99a2dd95SBruce Richardson 		str += 2;
158*99a2dd95SBruce Richardson 	} else if (str[0] == 's' && str[1] == 'f') {
159*99a2dd95SBruce Richardson 		eth_da->type = RTE_ETH_REPRESENTOR_SF;
160*99a2dd95SBruce Richardson 		str += 2;
161*99a2dd95SBruce Richardson 	} else {
162*99a2dd95SBruce Richardson 		/* 'pf' must followed by 'vf' or 'sf'. */
163*99a2dd95SBruce Richardson 		if (eth_da->type == RTE_ETH_REPRESENTOR_PF) {
164*99a2dd95SBruce Richardson 			str = NULL;
165*99a2dd95SBruce Richardson 			goto done;
166*99a2dd95SBruce Richardson 		}
167*99a2dd95SBruce Richardson 		eth_da->type = RTE_ETH_REPRESENTOR_VF;
168*99a2dd95SBruce Richardson 	}
169*99a2dd95SBruce Richardson 	str = rte_eth_devargs_process_list(str, eth_da->representor_ports,
170*99a2dd95SBruce Richardson 		&eth_da->nb_representor_ports,
171*99a2dd95SBruce Richardson 		RTE_DIM(eth_da->representor_ports));
172*99a2dd95SBruce Richardson done:
173*99a2dd95SBruce Richardson 	if (str == NULL)
174*99a2dd95SBruce Richardson 		RTE_LOG(ERR, EAL, "wrong representor format: %s\n", str);
175*99a2dd95SBruce Richardson 	return str == NULL ? -1 : 0;
176*99a2dd95SBruce Richardson }
177