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