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