Branch data Line data Source code
1 : : /* SPDX-License-Identifier: BSD-3-Clause
2 : : * Copyright(c) 2022 Intel Corporation
3 : : */
4 : :
5 : : #include <ctype.h>
6 : : #include <stdalign.h>
7 : : #include <stdlib.h>
8 : : #include <pthread.h>
9 : :
10 : : #include <eal_export.h>
11 : : #include <rte_kvargs.h>
12 : : #include <rte_malloc.h>
13 : :
14 : : #include "ethdev_driver.h"
15 : : #include "ethdev_private.h"
16 : : #include "rte_flow_driver.h"
17 : :
18 : : /**
19 : : * A set of values to describe the possible states of a switch domain.
20 : : */
21 : : enum rte_eth_switch_domain_state {
22 : : RTE_ETH_SWITCH_DOMAIN_UNUSED = 0,
23 : : RTE_ETH_SWITCH_DOMAIN_ALLOCATED
24 : : };
25 : :
26 : : /**
27 : : * Array of switch domains available for allocation. Array is sized to
28 : : * RTE_MAX_ETHPORTS elements as there cannot be more active switch domains than
29 : : * ethdev ports in a single process.
30 : : */
31 : : static struct rte_eth_dev_switch {
32 : : enum rte_eth_switch_domain_state state;
33 : : } eth_dev_switch_domains[RTE_MAX_ETHPORTS];
34 : :
35 : : static struct rte_eth_dev *
36 : 38 : eth_dev_allocated(const char *name)
37 : : {
38 : : uint16_t i;
39 : :
40 : : RTE_BUILD_BUG_ON(RTE_MAX_ETHPORTS >= UINT16_MAX);
41 : :
42 [ + + ]: 695 : for (i = 0; i < RTE_MAX_ETHPORTS; i++) {
43 [ + + ]: 675 : if (rte_eth_devices[i].data != NULL &&
44 [ + + ]: 40 : strcmp(rte_eth_devices[i].data->name, name) == 0)
45 : 18 : return &rte_eth_devices[i];
46 : : }
47 : : return NULL;
48 : : }
49 : :
50 : : static uint16_t
51 : : eth_dev_find_free_port(void)
52 : : __rte_requires_capability(rte_mcfg_ethdev_get_lock())
53 : : {
54 : : uint16_t i;
55 : :
56 [ + - ]: 36 : for (i = 0; i < RTE_MAX_ETHPORTS; i++) {
57 : : /* Using shared name field to find a free port. */
58 [ + + ]: 36 : if (eth_dev_shared_data->data[i].name[0] == '\0') {
59 : : RTE_ASSERT(rte_eth_devices[i].state ==
60 : : RTE_ETH_DEV_UNUSED);
61 : : return i;
62 : : }
63 : : }
64 : : return RTE_MAX_ETHPORTS;
65 : : }
66 : :
67 : : static struct rte_eth_dev *
68 : : eth_dev_get(uint16_t port_id)
69 : : __rte_requires_capability(rte_mcfg_ethdev_get_lock())
70 : : {
71 : 19 : struct rte_eth_dev *eth_dev = &rte_eth_devices[port_id];
72 : :
73 : 19 : eth_dev->data = ð_dev_shared_data->data[port_id];
74 : :
75 : : return eth_dev;
76 : : }
77 : :
78 : : RTE_EXPORT_INTERNAL_SYMBOL(rte_eth_dev_allocate)
79 : : struct rte_eth_dev *
80 : 19 : rte_eth_dev_allocate(const char *name)
81 : : {
82 : : uint16_t port_id;
83 : : struct rte_eth_dev *eth_dev = NULL;
84 : : size_t name_len;
85 : :
86 : 19 : name_len = strnlen(name, RTE_ETH_NAME_MAX_LEN);
87 [ - + ]: 19 : if (name_len == 0) {
88 : 0 : RTE_ETHDEV_LOG_LINE(ERR, "Zero length Ethernet device name");
89 : 0 : return NULL;
90 : : }
91 : :
92 [ - + ]: 19 : if (name_len >= RTE_ETH_NAME_MAX_LEN) {
93 : 0 : RTE_ETHDEV_LOG_LINE(ERR, "Ethernet device name is too long");
94 : 0 : return NULL;
95 : : }
96 : :
97 : : /* Synchronize port creation between primary and secondary processes. */
98 : 19 : rte_spinlock_lock(rte_mcfg_ethdev_get_lock());
99 : :
100 [ - + ]: 19 : if (eth_dev_shared_data_prepare() == NULL)
101 : 0 : goto unlock;
102 : :
103 [ - + ]: 19 : if (eth_dev_allocated(name) != NULL) {
104 : 0 : RTE_ETHDEV_LOG_LINE(ERR,
105 : : "Ethernet device with name %s already allocated",
106 : : name);
107 : 0 : goto unlock;
108 : : }
109 : :
110 : : port_id = eth_dev_find_free_port();
111 [ - + ]: 19 : if (port_id == RTE_MAX_ETHPORTS) {
112 : 0 : RTE_ETHDEV_LOG_LINE(ERR,
113 : : "Reached maximum number of Ethernet ports");
114 : 0 : goto unlock;
115 : : }
116 : :
117 : 19 : eth_dev = eth_dev_get(port_id);
118 : 19 : eth_dev->flow_fp_ops = &rte_flow_fp_default_ops;
119 : 19 : strlcpy(eth_dev->data->name, name, sizeof(eth_dev->data->name));
120 : 19 : eth_dev->data->port_id = port_id;
121 : 19 : eth_dev->data->backer_port_id = RTE_MAX_ETHPORTS;
122 : 19 : eth_dev->data->mtu = RTE_ETHER_MTU;
123 : 19 : pthread_mutex_init(ð_dev->data->flow_ops_mutex, NULL);
124 : : RTE_ASSERT(rte_eal_process_type() == RTE_PROC_PRIMARY);
125 : 19 : eth_dev_shared_data->allocated_ports++;
126 : :
127 : 19 : unlock:
128 : 19 : rte_spinlock_unlock(rte_mcfg_ethdev_get_lock());
129 : :
130 : 19 : return eth_dev;
131 : : }
132 : :
133 : : RTE_EXPORT_INTERNAL_SYMBOL(rte_eth_dev_allocated)
134 : : struct rte_eth_dev *
135 : 19 : rte_eth_dev_allocated(const char *name)
136 : : {
137 : : struct rte_eth_dev *ethdev;
138 : :
139 : 19 : rte_spinlock_lock(rte_mcfg_ethdev_get_lock());
140 : :
141 [ + - ]: 19 : if (eth_dev_shared_data_prepare() != NULL)
142 : 19 : ethdev = eth_dev_allocated(name);
143 : : else
144 : : ethdev = NULL;
145 : :
146 : 19 : rte_spinlock_unlock(rte_mcfg_ethdev_get_lock());
147 : :
148 : 19 : return ethdev;
149 : : }
150 : :
151 : : /*
152 : : * Attach to a port already registered by the primary process, which
153 : : * makes sure that the same device would have the same port ID both
154 : : * in the primary and secondary process.
155 : : */
156 : : RTE_EXPORT_INTERNAL_SYMBOL(rte_eth_dev_attach_secondary)
157 : : struct rte_eth_dev *
158 : 0 : rte_eth_dev_attach_secondary(const char *name)
159 : : {
160 : : uint16_t i;
161 : : struct rte_eth_dev *eth_dev = NULL;
162 : :
163 : : /* Synchronize port attachment to primary port creation and release. */
164 : 0 : rte_spinlock_lock(rte_mcfg_ethdev_get_lock());
165 : :
166 [ # # ]: 0 : if (eth_dev_shared_data_prepare() == NULL)
167 : 0 : goto unlock;
168 : :
169 [ # # ]: 0 : for (i = 0; i < RTE_MAX_ETHPORTS; i++) {
170 [ # # ]: 0 : if (strcmp(eth_dev_shared_data->data[i].name, name) == 0)
171 : : break;
172 : : }
173 [ # # ]: 0 : if (i == RTE_MAX_ETHPORTS) {
174 : 0 : RTE_ETHDEV_LOG_LINE(ERR,
175 : : "Device %s is not driven by the primary process",
176 : : name);
177 : : } else {
178 : 0 : eth_dev = eth_dev_get(i);
179 : : RTE_ASSERT(eth_dev->data->port_id == i);
180 : : }
181 : :
182 : 0 : unlock:
183 : 0 : rte_spinlock_unlock(rte_mcfg_ethdev_get_lock());
184 : 0 : return eth_dev;
185 : : }
186 : :
187 : : RTE_EXPORT_INTERNAL_SYMBOL(rte_eth_dev_callback_process)
188 : : int
189 : 37 : rte_eth_dev_callback_process(struct rte_eth_dev *dev,
190 : : enum rte_eth_event_type event, void *ret_param)
191 : : {
192 : : struct rte_eth_dev_callback *cb_lst;
193 : : struct rte_eth_dev_callback dev_cb;
194 : : int rc = 0;
195 : :
196 : : rte_spinlock_lock(ð_dev_cb_lock);
197 [ - + ]: 37 : TAILQ_FOREACH(cb_lst, &(dev->link_intr_cbs), next) {
198 [ # # # # ]: 0 : if (cb_lst->cb_fn == NULL || cb_lst->event != event)
199 : 0 : continue;
200 : 0 : dev_cb = *cb_lst;
201 : 0 : cb_lst->active = 1;
202 [ # # ]: 0 : if (ret_param != NULL)
203 : : dev_cb.ret_param = ret_param;
204 : :
205 : : rte_spinlock_unlock(ð_dev_cb_lock);
206 : 0 : rc = dev_cb.cb_fn(dev->data->port_id, dev_cb.event,
207 : : dev_cb.cb_arg, dev_cb.ret_param);
208 : : rte_spinlock_lock(ð_dev_cb_lock);
209 : 0 : cb_lst->active = 0;
210 : : }
211 : : rte_spinlock_unlock(ð_dev_cb_lock);
212 : 37 : return rc;
213 : : }
214 : :
215 : : RTE_EXPORT_INTERNAL_SYMBOL(rte_eth_dev_probing_finish)
216 : : void
217 : 19 : rte_eth_dev_probing_finish(struct rte_eth_dev *dev)
218 : : {
219 [ + - ]: 19 : if (dev == NULL)
220 : : return;
221 : :
222 : : /*
223 : : * for secondary process, at that point we expect device
224 : : * to be already 'usable', so shared data and all function pointers
225 : : * for fast-path devops have to be setup properly inside rte_eth_dev.
226 : : */
227 [ - + ]: 19 : if (rte_eal_process_type() == RTE_PROC_SECONDARY)
228 : 0 : eth_dev_fp_ops_setup(rte_eth_fp_ops + dev->data->port_id, dev);
229 : :
230 : 19 : rte_eth_dev_callback_process(dev, RTE_ETH_EVENT_NEW, NULL);
231 : :
232 : 19 : dev->state = RTE_ETH_DEV_ATTACHED;
233 : : }
234 : :
235 : : RTE_EXPORT_INTERNAL_SYMBOL(rte_eth_dev_release_port)
236 : : int
237 : 18 : rte_eth_dev_release_port(struct rte_eth_dev *eth_dev)
238 : : {
239 : : int ret;
240 : :
241 [ + - ]: 18 : if (eth_dev == NULL)
242 : : return -EINVAL;
243 : :
244 : 18 : rte_spinlock_lock(rte_mcfg_ethdev_get_lock());
245 [ + - ]: 18 : if (eth_dev_shared_data_prepare() == NULL)
246 : : ret = -EINVAL;
247 : : else
248 : : ret = 0;
249 : 18 : rte_spinlock_unlock(rte_mcfg_ethdev_get_lock());
250 [ + - ]: 18 : if (ret != 0)
251 : : return ret;
252 : :
253 [ + - ]: 18 : if (eth_dev->state != RTE_ETH_DEV_UNUSED)
254 : 18 : rte_eth_dev_callback_process(eth_dev,
255 : : RTE_ETH_EVENT_DESTROY, NULL);
256 : :
257 : 18 : eth_dev_fp_ops_reset(rte_eth_fp_ops + eth_dev->data->port_id);
258 : :
259 : 18 : eth_dev->flow_fp_ops = &rte_flow_fp_default_ops;
260 : :
261 : 18 : rte_spinlock_lock(rte_mcfg_ethdev_get_lock());
262 : :
263 : 18 : eth_dev->state = RTE_ETH_DEV_UNUSED;
264 : 18 : eth_dev->device = NULL;
265 : 18 : eth_dev->process_private = NULL;
266 : 18 : eth_dev->intr_handle = NULL;
267 : 18 : eth_dev->rx_pkt_burst = NULL;
268 : 18 : eth_dev->tx_pkt_burst = NULL;
269 : 18 : eth_dev->tx_pkt_prepare = NULL;
270 : 18 : eth_dev->rx_queue_count = NULL;
271 : 18 : eth_dev->rx_descriptor_status = NULL;
272 : 18 : eth_dev->tx_descriptor_status = NULL;
273 : 18 : eth_dev->dev_ops = NULL;
274 : :
275 [ + - ]: 18 : if (rte_eal_process_type() == RTE_PROC_PRIMARY) {
276 : 18 : rte_free(eth_dev->data->rx_queues);
277 : 18 : rte_free(eth_dev->data->tx_queues);
278 : 18 : rte_free(eth_dev->data->mac_addrs);
279 : 18 : rte_free(eth_dev->data->hash_mac_addrs);
280 : 18 : rte_free(eth_dev->data->dev_private);
281 : 18 : pthread_mutex_destroy(ð_dev->data->flow_ops_mutex);
282 : 18 : memset(eth_dev->data, 0, sizeof(struct rte_eth_dev_data));
283 : 18 : eth_dev->data = NULL;
284 : :
285 : 18 : eth_dev_shared_data->allocated_ports--;
286 : 18 : eth_dev_shared_data_release();
287 : : }
288 : :
289 : 18 : rte_spinlock_unlock(rte_mcfg_ethdev_get_lock());
290 : :
291 : 18 : return 0;
292 : : }
293 : :
294 : : RTE_EXPORT_INTERNAL_SYMBOL(rte_eth_dev_create)
295 : : int
296 : 0 : rte_eth_dev_create(struct rte_device *device, const char *name,
297 : : size_t priv_data_size,
298 : : ethdev_bus_specific_init ethdev_bus_specific_init,
299 : : void *bus_init_params,
300 : : ethdev_init_t ethdev_init, void *init_params)
301 : : {
302 : : struct rte_eth_dev *ethdev;
303 : : int retval;
304 : :
305 [ # # ]: 0 : if (*ethdev_init == NULL)
306 : : return -EINVAL;
307 : :
308 [ # # ]: 0 : if (rte_eal_process_type() == RTE_PROC_PRIMARY) {
309 : 0 : ethdev = rte_eth_dev_allocate(name);
310 [ # # ]: 0 : if (!ethdev)
311 : : return -ENODEV;
312 : :
313 [ # # ]: 0 : if (priv_data_size) {
314 : : /* try alloc private data on device-local node. */
315 : 0 : ethdev->data->dev_private = rte_zmalloc_socket(
316 : : name, priv_data_size, RTE_CACHE_LINE_SIZE,
317 : : device->numa_node);
318 : :
319 : : /* fall back to alloc on any socket on failure */
320 [ # # ]: 0 : if (ethdev->data->dev_private == NULL) {
321 : 0 : ethdev->data->dev_private = rte_zmalloc(name,
322 : : priv_data_size, RTE_CACHE_LINE_SIZE);
323 : :
324 [ # # ]: 0 : if (ethdev->data->dev_private == NULL) {
325 : 0 : RTE_ETHDEV_LOG_LINE(ERR, "failed to allocate private data");
326 : : retval = -ENOMEM;
327 : 0 : goto probe_failed;
328 : : }
329 : : /* got memory, but not local, so issue warning */
330 : 0 : RTE_ETHDEV_LOG_LINE(WARNING,
331 : : "Private data for ethdev '%s' not allocated on local NUMA node %d",
332 : : device->name, device->numa_node);
333 : : }
334 : : }
335 : : } else {
336 : 0 : ethdev = rte_eth_dev_attach_secondary(name);
337 [ # # ]: 0 : if (!ethdev) {
338 : 0 : RTE_ETHDEV_LOG_LINE(ERR,
339 : : "secondary process attach failed, ethdev doesn't exist");
340 : 0 : return -ENODEV;
341 : : }
342 : : }
343 : :
344 : 0 : ethdev->device = device;
345 : :
346 [ # # ]: 0 : if (ethdev_bus_specific_init) {
347 : 0 : retval = ethdev_bus_specific_init(ethdev, bus_init_params);
348 [ # # ]: 0 : if (retval) {
349 : 0 : RTE_ETHDEV_LOG_LINE(ERR,
350 : : "ethdev bus specific initialisation failed");
351 : 0 : goto probe_failed;
352 : : }
353 : : }
354 : :
355 : 0 : retval = ethdev_init(ethdev, init_params);
356 [ # # ]: 0 : if (retval) {
357 : 0 : RTE_ETHDEV_LOG_LINE(ERR, "ethdev initialisation failed");
358 : 0 : goto probe_failed;
359 : : }
360 : :
361 : 0 : rte_eth_dev_probing_finish(ethdev);
362 : :
363 : 0 : return retval;
364 : :
365 : 0 : probe_failed:
366 : 0 : rte_eth_dev_release_port(ethdev);
367 : 0 : return retval;
368 : : }
369 : :
370 : : RTE_EXPORT_INTERNAL_SYMBOL(rte_eth_dev_destroy)
371 : : int
372 : 0 : rte_eth_dev_destroy(struct rte_eth_dev *ethdev,
373 : : ethdev_uninit_t ethdev_uninit)
374 : : {
375 : : int ret;
376 : :
377 : 0 : ethdev = rte_eth_dev_allocated(ethdev->data->name);
378 [ # # ]: 0 : if (!ethdev)
379 : : return -ENODEV;
380 : :
381 [ # # ]: 0 : if (*ethdev_uninit == NULL)
382 : : return -EINVAL;
383 : :
384 : 0 : ret = ethdev_uninit(ethdev);
385 [ # # ]: 0 : if (ret)
386 : : return ret;
387 : :
388 : 0 : return rte_eth_dev_release_port(ethdev);
389 : : }
390 : :
391 : : RTE_EXPORT_INTERNAL_SYMBOL(rte_eth_dev_get_by_name)
392 : : struct rte_eth_dev *
393 : 0 : rte_eth_dev_get_by_name(const char *name)
394 : : {
395 : : uint16_t pid;
396 : :
397 [ # # ]: 0 : if (rte_eth_dev_get_port_by_name(name, &pid))
398 : : return NULL;
399 : :
400 : 0 : return &rte_eth_devices[pid];
401 : : }
402 : :
403 : : RTE_EXPORT_INTERNAL_SYMBOL(rte_eth_dev_is_rx_hairpin_queue)
404 : : int
405 : 0 : rte_eth_dev_is_rx_hairpin_queue(struct rte_eth_dev *dev, uint16_t queue_id)
406 : : {
407 [ # # ]: 0 : if (dev->data->rx_queue_state[queue_id] == RTE_ETH_QUEUE_STATE_HAIRPIN)
408 : 0 : return 1;
409 : : return 0;
410 : : }
411 : :
412 : : RTE_EXPORT_INTERNAL_SYMBOL(rte_eth_dev_is_tx_hairpin_queue)
413 : : int
414 : 1 : rte_eth_dev_is_tx_hairpin_queue(struct rte_eth_dev *dev, uint16_t queue_id)
415 : : {
416 [ - + ]: 1 : if (dev->data->tx_queue_state[queue_id] == RTE_ETH_QUEUE_STATE_HAIRPIN)
417 : 0 : return 1;
418 : : return 0;
419 : : }
420 : :
421 : : RTE_EXPORT_INTERNAL_SYMBOL(rte_eth_dev_internal_reset)
422 : : void
423 : 0 : rte_eth_dev_internal_reset(struct rte_eth_dev *dev)
424 : : {
425 [ # # ]: 0 : if (dev->data->dev_started) {
426 : 0 : RTE_ETHDEV_LOG_LINE(ERR, "Port %u must be stopped to allow reset",
427 : : dev->data->port_id);
428 : 0 : return;
429 : : }
430 : :
431 : 0 : eth_dev_rx_queue_config(dev, 0);
432 : 0 : eth_dev_tx_queue_config(dev, 0);
433 : :
434 : 0 : memset(&dev->data->dev_conf, 0, sizeof(dev->data->dev_conf));
435 : : }
436 : :
437 : : static int
438 : 38 : eth_dev_devargs_tokenise(struct rte_kvargs *arglist, const char *str_in)
439 : : {
440 : : int state;
441 : : struct rte_kvargs_pair *pair;
442 : : char *letter;
443 : :
444 : 38 : arglist->str = strdup(str_in);
445 [ + - ]: 38 : if (arglist->str == NULL)
446 : : return -ENOMEM;
447 : :
448 : : letter = arglist->str;
449 : : state = 0;
450 : 38 : arglist->count = 0;
451 : 38 : pair = &arglist->pairs[0];
452 : : while (1) {
453 [ + + + + : 1141 : switch (state) {
- ]
454 : 76 : case 0: /* Initial */
455 [ + - ]: 76 : if (*letter == '=')
456 : : return -EINVAL;
457 [ + + ]: 76 : else if (*letter == '\0')
458 : : return 0;
459 : :
460 : : state = 1;
461 : 42 : pair->key = letter;
462 : : /* fallthrough */
463 : :
464 : 484 : case 1: /* Parsing key */
465 [ + + ]: 484 : if (*letter == '=') {
466 : 39 : *letter = '\0';
467 : 39 : pair->value = letter + 1;
468 : : state = 2;
469 [ + + ]: 445 : } else if (*letter == ',' || *letter == '\0')
470 : : return -EINVAL;
471 : : break;
472 : :
473 : :
474 : 166 : case 2: /* Parsing value */
475 [ + + ]: 166 : if (*letter == '[')
476 : : state = 3;
477 [ + + ]: 121 : else if (*letter == ',') {
478 : 4 : *letter = '\0';
479 : 4 : arglist->count++;
480 : 4 : pair = &arglist->pairs[arglist->count];
481 : : state = 0;
482 [ + + ]: 117 : } else if (*letter == '\0') {
483 : 34 : letter--;
484 : 34 : arglist->count++;
485 : 34 : pair = &arglist->pairs[arglist->count];
486 : : state = 0;
487 : : }
488 : : break;
489 : :
490 : 457 : case 3: /* Parsing list */
491 [ + + ]: 457 : if (*letter == ']') {
492 : : /* For devargs having singles lists move to state 2 once letter
493 : : * becomes ']' so each can be considered as different pair key
494 : : * value. But in nested lists case e.g. multiple representors
495 : : * case i.e. [pf[0-3],pfvf[3,4-6]], complete nested list should
496 : : * be considered as one pair value, hence checking if end of outer
497 : : * list ']' is reached else stay on state 3.
498 : : */
499 [ + - ]: 64 : if ((strcmp("representor", pair->key) == 0) &&
500 [ + + + + ]: 64 : (*(letter + 1) != '\0' && *(letter + 2) != '\0' &&
501 [ + + ]: 33 : *(letter + 3) != '\0') &&
502 [ + + ]: 32 : ((*(letter + 2) == 'p' && *(letter + 3) == 'f') ||
503 [ - + ]: 17 : (*(letter + 2) == 'v' && *(letter + 3) == 'f') ||
504 [ - + ]: 15 : (*(letter + 2) == 's' && *(letter + 3) == 'f') ||
505 [ - - + + ]: 15 : (*(letter + 2) == 'c' && isdigit(*(letter + 3))) ||
506 [ - + ]: 1 : (*(letter + 2) == '[' && isdigit(*(letter + 3))) ||
507 [ + + ]: 14 : (isdigit(*(letter + 2)))))
508 : : state = 3;
509 : : else
510 : : state = 2;
511 [ + + ]: 393 : } else if (*letter == '\0') {
512 : : return -EINVAL;
513 : : }
514 : : break;
515 : : }
516 : 1103 : letter++;
517 : : }
518 : : }
519 : :
520 : : static int
521 : 73 : devargs_parse_representor_ports(struct rte_eth_devargs *eth_devargs, char
522 : : *da_val, unsigned int da_idx, unsigned int nb_da)
523 : : {
524 : : struct rte_eth_devargs *eth_da;
525 : : int result = 0;
526 : :
527 [ - + ]: 73 : if (da_idx + 1 > nb_da) {
528 : 0 : RTE_ETHDEV_LOG_LINE(ERR, "Devargs parsed %d > max array size %d",
529 : : da_idx + 1, nb_da);
530 : : result = -1;
531 : 0 : goto parse_cleanup;
532 : : }
533 : 73 : eth_da = ð_devargs[da_idx];
534 : : memset(eth_da, 0, sizeof(*eth_da));
535 : 73 : RTE_ETHDEV_LOG_LINE(DEBUG, " Devargs idx %d value %s", da_idx, da_val);
536 : 73 : result = rte_eth_devargs_parse_representor_ports(da_val, eth_da);
537 : :
538 : 73 : parse_cleanup:
539 : 73 : return result;
540 : : }
541 : :
542 : : static int
543 : 16 : eth_dev_tokenise_representor_list(char *p_val, struct rte_eth_devargs *eth_devargs,
544 : : unsigned int nb_da)
545 : : {
546 : : char da_val[BUFSIZ], str[BUFSIZ];
547 : : bool is_rep_portid_list = true;
548 : : unsigned int devargs = 0;
549 : : int result = 0, len = 0;
550 : : int i = 0, j = 0;
551 : : char *pos;
552 : :
553 : : pos = p_val;
554 : : /* Length of consolidated list */
555 [ + + ]: 376 : while (*pos++ != '\0') {
556 : 360 : len++;
557 [ + + ]: 360 : if (isalpha(*pos))
558 : : is_rep_portid_list = false;
559 : : }
560 : :
561 : : /* List of representor portIDs i.e.[1,2,3] should be considered as single representor case*/
562 [ + + ]: 16 : if (is_rep_portid_list) {
563 : 3 : result = devargs_parse_representor_ports(eth_devargs, p_val, 0, 1);
564 [ + + ]: 3 : if (result < 0)
565 : : return result;
566 : :
567 : : devargs++;
568 : 2 : return devargs;
569 : : }
570 : :
571 : : memset(str, 0, BUFSIZ);
572 : : memset(da_val, 0, BUFSIZ);
573 : : /* Remove the exterior [] of the consolidated list */
574 : 13 : strncpy(str, &p_val[1], len - 2);
575 : : while (1) {
576 [ + + ]: 203 : if (str[i] == '\0') {
577 [ + + ]: 12 : if (da_val[0] != '\0') {
578 : 7 : result = devargs_parse_representor_ports(eth_devargs, da_val,
579 : : devargs, nb_da);
580 [ - + ]: 7 : if (result < 0)
581 : 0 : goto parse_cleanup;
582 : :
583 : 7 : devargs++;
584 : : }
585 : : break;
586 : : }
587 [ + + ]: 191 : if (str[i] == ',' || str[i] == '[') {
588 [ + + ]: 64 : if (str[i] == ',') {
589 [ + + ]: 39 : if (da_val[0] != '\0') {
590 : 20 : da_val[j + 1] = '\0';
591 : 20 : result = devargs_parse_representor_ports(eth_devargs,
592 : : da_val, devargs,
593 : : nb_da);
594 [ - + ]: 20 : if (result < 0)
595 : 0 : goto parse_cleanup;
596 : :
597 : 20 : devargs++;
598 : : j = 0;
599 : : memset(da_val, 0, BUFSIZ);
600 : : }
601 : : }
602 : :
603 [ + + ]: 64 : if (str[i] == '[') {
604 [ + + + + ]: 145 : while (str[i] != ']' || isalpha(str[i + 1])) {
605 : 120 : da_val[j] = str[i];
606 : 120 : j++;
607 : 120 : i++;
608 : : }
609 : 25 : da_val[j] = ']';
610 : 25 : da_val[j + 1] = '\0';
611 : 25 : result = devargs_parse_representor_ports(eth_devargs, da_val,
612 : : devargs, nb_da);
613 [ + + ]: 25 : if (result < 0)
614 : 1 : goto parse_cleanup;
615 : :
616 : 24 : devargs++;
617 : : j = 0;
618 : : memset(da_val, 0, BUFSIZ);
619 : : }
620 : : } else {
621 : 127 : da_val[j] = str[i];
622 : 127 : j++;
623 : : }
624 : 190 : i++;
625 : : }
626 : 12 : result = devargs;
627 : :
628 : : parse_cleanup:
629 : : return result;
630 : : }
631 : :
632 : : RTE_EXPORT_INTERNAL_SYMBOL(rte_eth_devargs_parse)
633 : : int
634 : 38 : rte_eth_devargs_parse(const char *dargs, struct rte_eth_devargs *eth_devargs,
635 : : unsigned int nb_da)
636 : : {
637 : : struct rte_kvargs_pair *pair;
638 : : struct rte_kvargs args;
639 : : bool dup_rep = false;
640 : : int devargs = 0;
641 : : unsigned int i;
642 : : int result = 0;
643 : :
644 : 38 : memset(eth_devargs, 0, nb_da * sizeof(*eth_devargs));
645 : :
646 : 38 : result = eth_dev_devargs_tokenise(&args, dargs);
647 [ + + ]: 38 : if (result < 0)
648 : 4 : goto parse_cleanup;
649 : :
650 [ + + ]: 59 : for (i = 0; i < args.count; i++) {
651 : : pair = &args.pairs[i];
652 [ + - ]: 35 : if (strcmp("representor", pair->key) == 0) {
653 [ + + ]: 35 : if (dup_rep) {
654 : 1 : RTE_ETHDEV_LOG_LINE(ERR, "Duplicated representor key: %s",
655 : : pair->value);
656 : : result = -1;
657 : 1 : goto parse_cleanup;
658 : : }
659 : :
660 : 34 : RTE_ETHDEV_LOG_LINE(DEBUG, "Devarg pattern: %s", pair->value);
661 [ + + ]: 34 : if (pair->value[0] == '[') {
662 : : /* Multiple representor list case */
663 : 16 : devargs = eth_dev_tokenise_representor_list(pair->value,
664 : : eth_devargs, nb_da);
665 [ + + ]: 16 : if (devargs < 0)
666 : 2 : goto parse_cleanup;
667 : : } else {
668 : : /* Single representor case */
669 : 18 : devargs = devargs_parse_representor_ports(eth_devargs, pair->value,
670 : : 0, 1);
671 [ + + ]: 18 : if (devargs < 0)
672 : 7 : goto parse_cleanup;
673 : 11 : devargs++;
674 : : }
675 : : dup_rep = true;
676 : : }
677 : : }
678 : 24 : RTE_ETHDEV_LOG_LINE(DEBUG, "Total devargs parsed %d", devargs);
679 : : result = devargs;
680 : :
681 : 38 : parse_cleanup:
682 : 38 : free(args.str);
683 : :
684 : 38 : return result;
685 : : }
686 : :
687 : : static inline int
688 : : eth_dev_dma_mzone_name(char *name, size_t len, uint16_t port_id, uint16_t queue_id,
689 : : const char *ring_name)
690 : : {
691 : : return snprintf(name, len, "eth_p%d_q%d_%s",
692 : : port_id, queue_id, ring_name);
693 : : }
694 : :
695 : : RTE_EXPORT_INTERNAL_SYMBOL(rte_eth_dma_zone_free)
696 : : int
697 : 0 : rte_eth_dma_zone_free(const struct rte_eth_dev *dev, const char *ring_name,
698 : : uint16_t queue_id)
699 : : {
700 : : char z_name[RTE_MEMZONE_NAMESIZE];
701 : : const struct rte_memzone *mz;
702 : : int rc = 0;
703 : :
704 [ # # ]: 0 : rc = eth_dev_dma_mzone_name(z_name, sizeof(z_name), dev->data->port_id,
705 : : queue_id, ring_name);
706 [ # # ]: 0 : if (rc >= RTE_MEMZONE_NAMESIZE) {
707 : 0 : RTE_ETHDEV_LOG_LINE(ERR, "ring name too long");
708 : 0 : return -ENAMETOOLONG;
709 : : }
710 : :
711 : 0 : mz = rte_memzone_lookup(z_name);
712 [ # # ]: 0 : if (mz)
713 : 0 : rc = rte_memzone_free(mz);
714 : : else
715 : : rc = -ENOENT;
716 : :
717 : : return rc;
718 : : }
719 : :
720 : : RTE_EXPORT_INTERNAL_SYMBOL(rte_eth_dma_zone_reserve)
721 : : const struct rte_memzone *
722 : 0 : rte_eth_dma_zone_reserve(const struct rte_eth_dev *dev, const char *ring_name,
723 : : uint16_t queue_id, size_t size, unsigned int align,
724 : : int socket_id)
725 : : {
726 : : char z_name[RTE_MEMZONE_NAMESIZE];
727 : : const struct rte_memzone *mz;
728 : : int rc;
729 : :
730 [ # # ]: 0 : rc = eth_dev_dma_mzone_name(z_name, sizeof(z_name), dev->data->port_id,
731 : : queue_id, ring_name);
732 [ # # ]: 0 : if (rc >= RTE_MEMZONE_NAMESIZE) {
733 : 0 : RTE_ETHDEV_LOG_LINE(ERR, "ring name too long");
734 : 0 : rte_errno = ENAMETOOLONG;
735 : 0 : return NULL;
736 : : }
737 : :
738 : 0 : mz = rte_memzone_lookup(z_name);
739 [ # # ]: 0 : if (mz) {
740 [ # # # # ]: 0 : if ((socket_id != SOCKET_ID_ANY && socket_id != mz->socket_id) ||
741 [ # # ]: 0 : size > mz->len ||
742 [ # # ]: 0 : ((uintptr_t)mz->addr & (align - 1)) != 0) {
743 : 0 : RTE_ETHDEV_LOG_LINE(ERR,
744 : : "memzone %s does not justify the requested attributes",
745 : : mz->name);
746 : 0 : return NULL;
747 : : }
748 : :
749 : : return mz;
750 : : }
751 : :
752 : 0 : return rte_memzone_reserve_aligned(z_name, size, socket_id,
753 : : RTE_MEMZONE_IOVA_CONTIG, align);
754 : : }
755 : :
756 : : RTE_EXPORT_INTERNAL_SYMBOL(rte_eth_hairpin_queue_peer_bind)
757 : : int
758 : 0 : rte_eth_hairpin_queue_peer_bind(uint16_t cur_port, uint16_t cur_queue,
759 : : struct rte_hairpin_peer_info *peer_info,
760 : : uint32_t direction)
761 : : {
762 : : struct rte_eth_dev *dev;
763 : :
764 [ # # ]: 0 : if (peer_info == NULL)
765 : : return -EINVAL;
766 : :
767 : : /* No need to check the validity again. */
768 : 0 : dev = &rte_eth_devices[cur_port];
769 [ # # ]: 0 : if (dev->dev_ops->hairpin_queue_peer_bind == NULL)
770 : : return -ENOTSUP;
771 : :
772 : 0 : return dev->dev_ops->hairpin_queue_peer_bind(dev, cur_queue, peer_info, direction);
773 : : }
774 : :
775 : : RTE_EXPORT_INTERNAL_SYMBOL(rte_eth_hairpin_queue_peer_unbind)
776 : : int
777 : 0 : rte_eth_hairpin_queue_peer_unbind(uint16_t cur_port, uint16_t cur_queue,
778 : : uint32_t direction)
779 : : {
780 : : struct rte_eth_dev *dev;
781 : :
782 : : /* No need to check the validity again. */
783 : 0 : dev = &rte_eth_devices[cur_port];
784 [ # # ]: 0 : if (dev->dev_ops->hairpin_queue_peer_unbind == NULL)
785 : : return -ENOTSUP;
786 : :
787 : 0 : return dev->dev_ops->hairpin_queue_peer_unbind(dev, cur_queue, direction);
788 : : }
789 : :
790 : : RTE_EXPORT_INTERNAL_SYMBOL(rte_eth_hairpin_queue_peer_update)
791 : : int
792 : 0 : rte_eth_hairpin_queue_peer_update(uint16_t peer_port, uint16_t peer_queue,
793 : : struct rte_hairpin_peer_info *cur_info,
794 : : struct rte_hairpin_peer_info *peer_info,
795 : : uint32_t direction)
796 : : {
797 : : struct rte_eth_dev *dev;
798 : :
799 : : /* Current queue information is not mandatory. */
800 [ # # ]: 0 : if (peer_info == NULL)
801 : : return -EINVAL;
802 : :
803 : : /* No need to check the validity again. */
804 : 0 : dev = &rte_eth_devices[peer_port];
805 [ # # ]: 0 : if (dev->dev_ops->hairpin_queue_peer_update == NULL)
806 : : return -ENOTSUP;
807 : :
808 : 0 : return dev->dev_ops->hairpin_queue_peer_update(dev, peer_queue,
809 : : cur_info, peer_info, direction);
810 : : }
811 : :
812 : : RTE_EXPORT_INTERNAL_SYMBOL(rte_eth_ip_reassembly_dynfield_register)
813 : : int
814 : 0 : rte_eth_ip_reassembly_dynfield_register(int *field_offset, int *flag_offset)
815 : : {
816 : : static const struct rte_mbuf_dynfield field_desc = {
817 : : .name = RTE_MBUF_DYNFIELD_IP_REASSEMBLY_NAME,
818 : : .size = sizeof(rte_eth_ip_reassembly_dynfield_t),
819 : : .align = alignof(rte_eth_ip_reassembly_dynfield_t),
820 : : };
821 : : static const struct rte_mbuf_dynflag ip_reassembly_dynflag = {
822 : : .name = RTE_MBUF_DYNFLAG_IP_REASSEMBLY_INCOMPLETE_NAME,
823 : : };
824 : : int offset;
825 : :
826 : 0 : offset = rte_mbuf_dynfield_register(&field_desc);
827 [ # # ]: 0 : if (offset < 0)
828 : : return -1;
829 [ # # ]: 0 : if (field_offset != NULL)
830 : 0 : *field_offset = offset;
831 : :
832 : 0 : offset = rte_mbuf_dynflag_register(&ip_reassembly_dynflag);
833 [ # # ]: 0 : if (offset < 0)
834 : : return -1;
835 [ # # ]: 0 : if (flag_offset != NULL)
836 : 0 : *flag_offset = offset;
837 : :
838 : : return 0;
839 : : }
840 : :
841 : : RTE_EXPORT_INTERNAL_SYMBOL(rte_eth_pkt_burst_dummy)
842 : : uint16_t
843 : 0 : rte_eth_pkt_burst_dummy(void *queue __rte_unused,
844 : : struct rte_mbuf **pkts __rte_unused,
845 : : uint16_t nb_pkts __rte_unused)
846 : : {
847 : 0 : return 0;
848 : : }
849 : :
850 : : RTE_EXPORT_INTERNAL_SYMBOL(rte_eth_representor_id_get)
851 : : int
852 : 0 : rte_eth_representor_id_get(uint16_t port_id,
853 : : enum rte_eth_representor_type type,
854 : : int controller, int pf, int representor_port,
855 : : uint16_t *repr_id)
856 : : {
857 : : int ret, n, count;
858 : : uint32_t i;
859 : : struct rte_eth_representor_info *info = NULL;
860 : : size_t size;
861 : :
862 [ # # ]: 0 : if (type == RTE_ETH_REPRESENTOR_NONE)
863 : : return 0;
864 [ # # ]: 0 : if (repr_id == NULL)
865 : : return -EINVAL;
866 : :
867 : : /* Get PMD representor range info. */
868 : 0 : ret = rte_eth_representor_info_get(port_id, NULL);
869 [ # # ]: 0 : if (ret == -ENOTSUP && type == RTE_ETH_REPRESENTOR_VF &&
870 [ # # ]: 0 : controller == -1 && pf == -1) {
871 : : /* Direct mapping for legacy VF representor. */
872 : 0 : *repr_id = representor_port;
873 : 0 : return 0;
874 [ # # ]: 0 : } else if (ret < 0) {
875 : : return ret;
876 : : }
877 : : n = ret;
878 : 0 : size = sizeof(*info) + n * sizeof(info->ranges[0]);
879 : 0 : info = calloc(1, size);
880 [ # # ]: 0 : if (info == NULL)
881 : : return -ENOMEM;
882 : 0 : info->nb_ranges_alloc = n;
883 : 0 : ret = rte_eth_representor_info_get(port_id, info);
884 [ # # ]: 0 : if (ret < 0)
885 : 0 : goto out;
886 : :
887 : : /* Default controller and pf to caller. */
888 [ # # ]: 0 : if (controller == -1)
889 : 0 : controller = info->controller;
890 [ # # ]: 0 : if (pf == -1)
891 : 0 : pf = info->pf;
892 : :
893 : : /* Locate representor ID. */
894 : : ret = -ENOENT;
895 [ # # ]: 0 : for (i = 0; i < info->nb_ranges; ++i) {
896 [ # # ]: 0 : if (info->ranges[i].type != type)
897 : 0 : continue;
898 [ # # ]: 0 : if (info->ranges[i].controller != controller)
899 : 0 : continue;
900 [ # # ]: 0 : if (info->ranges[i].id_end < info->ranges[i].id_base) {
901 : 0 : RTE_ETHDEV_LOG_LINE(WARNING, "Port %hu invalid representor ID Range %u - %u, entry %d",
902 : : port_id, info->ranges[i].id_base,
903 : : info->ranges[i].id_end, i);
904 : 0 : continue;
905 : :
906 : : }
907 : 0 : count = info->ranges[i].id_end - info->ranges[i].id_base + 1;
908 [ # # # # ]: 0 : switch (info->ranges[i].type) {
909 : 0 : case RTE_ETH_REPRESENTOR_PF:
910 [ # # ]: 0 : if (pf < info->ranges[i].pf ||
911 [ # # ]: 0 : pf >= info->ranges[i].pf + count)
912 : 0 : continue;
913 : 0 : *repr_id = info->ranges[i].id_base +
914 : 0 : (pf - info->ranges[i].pf);
915 : : ret = 0;
916 : 0 : goto out;
917 : 0 : case RTE_ETH_REPRESENTOR_VF:
918 [ # # ]: 0 : if (info->ranges[i].pf != pf)
919 : 0 : continue;
920 [ # # ]: 0 : if (representor_port < info->ranges[i].vf ||
921 [ # # ]: 0 : representor_port >= info->ranges[i].vf + count)
922 : 0 : continue;
923 : 0 : *repr_id = info->ranges[i].id_base +
924 : 0 : (representor_port - info->ranges[i].vf);
925 : : ret = 0;
926 : 0 : goto out;
927 : 0 : case RTE_ETH_REPRESENTOR_SF:
928 [ # # ]: 0 : if (info->ranges[i].pf != pf)
929 : 0 : continue;
930 [ # # ]: 0 : if (representor_port < info->ranges[i].sf ||
931 [ # # ]: 0 : representor_port >= info->ranges[i].sf + count)
932 : 0 : continue;
933 : 0 : *repr_id = info->ranges[i].id_base +
934 : 0 : (representor_port - info->ranges[i].sf);
935 : : ret = 0;
936 : 0 : goto out;
937 : : default:
938 : : break;
939 : : }
940 : : }
941 : 0 : out:
942 : 0 : free(info);
943 : 0 : return ret;
944 : : }
945 : :
946 : : RTE_EXPORT_INTERNAL_SYMBOL(rte_eth_switch_domain_alloc)
947 : : int
948 : 0 : rte_eth_switch_domain_alloc(uint16_t *domain_id)
949 : : {
950 : : uint16_t i;
951 : :
952 : 0 : *domain_id = RTE_ETH_DEV_SWITCH_DOMAIN_ID_INVALID;
953 : :
954 [ # # ]: 0 : for (i = 0; i < RTE_MAX_ETHPORTS; i++) {
955 [ # # ]: 0 : if (eth_dev_switch_domains[i].state ==
956 : : RTE_ETH_SWITCH_DOMAIN_UNUSED) {
957 : 0 : eth_dev_switch_domains[i].state =
958 : : RTE_ETH_SWITCH_DOMAIN_ALLOCATED;
959 : 0 : *domain_id = i;
960 : 0 : return 0;
961 : : }
962 : : }
963 : :
964 : : return -ENOSPC;
965 : : }
966 : :
967 : : RTE_EXPORT_INTERNAL_SYMBOL(rte_eth_switch_domain_free)
968 : : int
969 : 0 : rte_eth_switch_domain_free(uint16_t domain_id)
970 : : {
971 [ # # ]: 0 : if (domain_id == RTE_ETH_DEV_SWITCH_DOMAIN_ID_INVALID ||
972 : : domain_id >= RTE_MAX_ETHPORTS)
973 : : return -EINVAL;
974 : :
975 [ # # ]: 0 : if (eth_dev_switch_domains[domain_id].state !=
976 : : RTE_ETH_SWITCH_DOMAIN_ALLOCATED)
977 : : return -EINVAL;
978 : :
979 : 0 : eth_dev_switch_domains[domain_id].state = RTE_ETH_SWITCH_DOMAIN_UNUSED;
980 : :
981 : 0 : return 0;
982 : : }
983 : :
984 : : RTE_EXPORT_INTERNAL_SYMBOL(rte_eth_get_restore_flags)
985 : : uint64_t
986 : 10 : rte_eth_get_restore_flags(struct rte_eth_dev *dev, enum rte_eth_dev_operation op)
987 : : {
988 [ - + ]: 10 : if (dev->dev_ops->get_restore_flags != NULL)
989 : 0 : return dev->dev_ops->get_restore_flags(dev, op);
990 : : else
991 : : return RTE_ETH_RESTORE_ALL;
992 : : }
|