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 : 116 : eth_dev_allocated(const char *name)
37 : : {
38 : : uint16_t i;
39 : :
40 : : RTE_BUILD_BUG_ON(RTE_MAX_ETHPORTS >= UINT16_MAX);
41 : :
42 [ + + ]: 2309 : for (i = 0; i < RTE_MAX_ETHPORTS; i++) {
43 [ + + ]: 2241 : if (rte_eth_devices[i].data != NULL &&
44 [ + + ]: 90 : strcmp(rte_eth_devices[i].data->name, name) == 0)
45 : 48 : 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 [ + - ]: 88 : for (i = 0; i < RTE_MAX_ETHPORTS; i++) {
57 : : /* Using shared name field to find a free port. */
58 [ + + ]: 88 : 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 : 58 : struct rte_eth_dev *eth_dev = &rte_eth_devices[port_id];
72 : :
73 : 58 : 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 : 58 : eth_dev->rx_pkt_burst = rte_eth_pkt_burst_dummy;
82 : 58 : eth_dev->tx_pkt_burst = rte_eth_pkt_burst_dummy;
83 : 58 : eth_dev->tx_pkt_prepare = rte_eth_tx_pkt_prepare_dummy;
84 : 58 : eth_dev->rx_queue_count = rte_eth_queue_count_dummy;
85 : 58 : eth_dev->tx_queue_count = rte_eth_queue_count_dummy;
86 : 58 : eth_dev->rx_descriptor_status = rte_eth_descriptor_status_dummy;
87 : 58 : eth_dev->tx_descriptor_status = rte_eth_descriptor_status_dummy;
88 : 58 : eth_dev->recycle_tx_mbufs_reuse = rte_eth_recycle_tx_mbufs_reuse_dummy;
89 : 58 : 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 : 58 : 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 : 58 : name_len = strnlen(name, RTE_ETH_NAME_MAX_LEN);
101 [ - + ]: 58 : if (name_len == 0) {
102 : 0 : RTE_ETHDEV_LOG_LINE(ERR, "Zero length Ethernet device name");
103 : 0 : return NULL;
104 : : }
105 : :
106 [ - + ]: 58 : 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 : 58 : rte_spinlock_lock(rte_mcfg_ethdev_get_lock());
113 : :
114 [ - + ]: 58 : if (eth_dev_shared_data_prepare() == NULL)
115 : 0 : goto unlock;
116 : :
117 [ - + ]: 58 : 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 [ - + ]: 58 : 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 : 58 : eth_dev = eth_dev_get(port_id);
132 : : eth_dev_set_dummy_fops(eth_dev);
133 : 58 : eth_dev->flow_fp_ops = &rte_flow_fp_default_ops;
134 : 58 : strlcpy(eth_dev->data->name, name, sizeof(eth_dev->data->name));
135 : 58 : eth_dev->data->port_id = port_id;
136 : 58 : eth_dev->data->backer_port_id = RTE_MAX_ETHPORTS;
137 : 58 : eth_dev->data->mtu = RTE_ETHER_MTU;
138 : 58 : rte_thread_mutex_init_shared(ð_dev->data->flow_ops_mutex);
139 : : RTE_ASSERT(rte_eal_process_type() == RTE_PROC_PRIMARY);
140 : 58 : eth_dev_shared_data->allocated_ports++;
141 : :
142 : 58 : unlock:
143 : 58 : rte_spinlock_unlock(rte_mcfg_ethdev_get_lock());
144 : :
145 : 58 : return eth_dev;
146 : : }
147 : :
148 : : RTE_EXPORT_INTERNAL_SYMBOL(rte_eth_dev_allocated)
149 : : struct rte_eth_dev *
150 : 58 : rte_eth_dev_allocated(const char *name)
151 : : {
152 : : struct rte_eth_dev *ethdev;
153 : :
154 : 58 : rte_spinlock_lock(rte_mcfg_ethdev_get_lock());
155 : :
156 [ + - ]: 58 : if (eth_dev_shared_data_prepare() != NULL)
157 : 58 : ethdev = eth_dev_allocated(name);
158 : : else
159 : : ethdev = NULL;
160 : :
161 : 58 : rte_spinlock_unlock(rte_mcfg_ethdev_get_lock());
162 : :
163 : 58 : 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 : 117 : 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 [ + + ]: 119 : TAILQ_FOREACH(cb_lst, &(dev->link_intr_cbs), next) {
213 [ + - - + ]: 2 : if (cb_lst->cb_fn == NULL || cb_lst->event != event)
214 : 0 : continue;
215 : 2 : dev_cb = *cb_lst;
216 : 2 : cb_lst->active = 1;
217 [ - + ]: 2 : if (ret_param != NULL)
218 : : dev_cb.ret_param = ret_param;
219 : :
220 : : rte_spinlock_unlock(ð_dev_cb_lock);
221 : 2 : 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 : 2 : cb_lst->active = 0;
225 : : }
226 : : rte_spinlock_unlock(ð_dev_cb_lock);
227 : 117 : return rc;
228 : : }
229 : :
230 : : RTE_EXPORT_INTERNAL_SYMBOL(rte_eth_dev_probing_finish)
231 : : void
232 : 58 : rte_eth_dev_probing_finish(struct rte_eth_dev *dev)
233 : : {
234 [ + - ]: 58 : 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 [ - + ]: 58 : 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 : 58 : rte_eth_dev_callback_process(dev, RTE_ETH_EVENT_NEW, NULL);
246 : :
247 : 58 : dev->state = RTE_ETH_DEV_ATTACHED;
248 : : }
249 : :
250 : : RTE_EXPORT_INTERNAL_SYMBOL(rte_eth_dev_release_port)
251 : : int
252 : 57 : rte_eth_dev_release_port(struct rte_eth_dev *eth_dev)
253 : : {
254 : : int ret;
255 : :
256 [ + - ]: 57 : if (eth_dev == NULL)
257 : : return -EINVAL;
258 : :
259 : 57 : rte_spinlock_lock(rte_mcfg_ethdev_get_lock());
260 [ + - ]: 57 : if (eth_dev_shared_data_prepare() == NULL)
261 : : ret = -EINVAL;
262 : : else
263 : : ret = 0;
264 : 57 : rte_spinlock_unlock(rte_mcfg_ethdev_get_lock());
265 [ + - ]: 57 : if (ret != 0)
266 : : return ret;
267 : :
268 [ + - ]: 57 : if (eth_dev->state != RTE_ETH_DEV_UNUSED)
269 : 57 : rte_eth_dev_callback_process(eth_dev,
270 : : RTE_ETH_EVENT_DESTROY, NULL);
271 : :
272 : 57 : eth_dev_fp_ops_reset(rte_eth_fp_ops + eth_dev->data->port_id);
273 : :
274 : 57 : eth_dev->flow_fp_ops = &rte_flow_fp_default_ops;
275 : :
276 : 57 : rte_spinlock_lock(rte_mcfg_ethdev_get_lock());
277 : :
278 : 57 : eth_dev->state = RTE_ETH_DEV_UNUSED;
279 : 57 : eth_dev->device = NULL;
280 : 57 : eth_dev->process_private = NULL;
281 : 57 : eth_dev->intr_handle = NULL;
282 : 57 : eth_dev->rx_pkt_burst = NULL;
283 : 57 : eth_dev->tx_pkt_burst = NULL;
284 : 57 : eth_dev->tx_pkt_prepare = NULL;
285 : 57 : eth_dev->rx_queue_count = NULL;
286 : 57 : eth_dev->rx_descriptor_status = NULL;
287 : 57 : eth_dev->tx_descriptor_status = NULL;
288 : 57 : eth_dev->dev_ops = NULL;
289 : :
290 [ + - ]: 57 : if (rte_eal_process_type() == RTE_PROC_PRIMARY) {
291 : 57 : rte_free(eth_dev->data->rx_queues);
292 : 57 : rte_free(eth_dev->data->tx_queues);
293 : 57 : rte_free(eth_dev->data->mac_addrs);
294 : 57 : rte_free(eth_dev->data->hash_mac_addrs);
295 : 57 : rte_free(eth_dev->data->dev_private);
296 : 57 : pthread_mutex_destroy(ð_dev->data->flow_ops_mutex);
297 : 57 : memset(eth_dev->data, 0, sizeof(struct rte_eth_dev_data));
298 : 57 : eth_dev->data = NULL;
299 : :
300 : 57 : eth_dev_shared_data->allocated_ports--;
301 : 57 : eth_dev_shared_data_release();
302 : : }
303 : :
304 : 57 : rte_spinlock_unlock(rte_mcfg_ethdev_get_lock());
305 : :
306 : 57 : 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 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 (bus_specific_init) {
362 : 0 : retval = 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 : 4 : rte_eth_dev_is_rx_hairpin_queue(struct rte_eth_dev *dev, uint16_t queue_id)
421 : : {
422 [ - + ]: 4 : 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 : 5 : rte_eth_dev_is_tx_hairpin_queue(struct rte_eth_dev *dev, uint16_t queue_id)
430 : : {
431 [ - + ]: 5 : 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 : : /* len - 2 strips the outer '[' and ']'; guard against underflow and overflow */
587 [ - + ]: 13 : if (len < 2 || (len - 2) >= BUFSIZ) {
588 : 0 : RTE_ETHDEV_LOG_LINE(ERR, "Representor list too long or malformed: %s", p_val);
589 : 0 : return -EINVAL;
590 : : }
591 : : memset(str, 0, BUFSIZ);
592 : : memset(da_val, 0, BUFSIZ);
593 : : /* Remove the exterior [] of the consolidated list */
594 : 13 : memcpy(str, &p_val[1], len - 2);
595 : : while (1) {
596 [ + + ]: 203 : if (str[i] == '\0') {
597 [ + + ]: 12 : if (da_val[0] != '\0') {
598 : 7 : result = devargs_parse_representor_ports(eth_devargs, da_val,
599 : : devargs, nb_da);
600 [ - + ]: 7 : if (result < 0)
601 : 0 : goto parse_cleanup;
602 : :
603 : 7 : devargs++;
604 : : }
605 : : break;
606 : : }
607 [ + + ]: 191 : if (str[i] == ',' || str[i] == '[') {
608 [ + + ]: 64 : if (str[i] == ',') {
609 [ + + ]: 39 : if (da_val[0] != '\0') {
610 : 20 : da_val[j + 1] = '\0';
611 : 20 : result = devargs_parse_representor_ports(eth_devargs,
612 : : da_val, devargs,
613 : : nb_da);
614 [ - + ]: 20 : if (result < 0)
615 : 0 : goto parse_cleanup;
616 : :
617 : 20 : devargs++;
618 : : j = 0;
619 : : memset(da_val, 0, BUFSIZ);
620 : : }
621 : : }
622 : :
623 [ + + ]: 64 : if (str[i] == '[') {
624 [ + + + + ]: 145 : while (str[i] != ']' || isalpha(str[i + 1])) {
625 : 120 : da_val[j] = str[i];
626 : 120 : j++;
627 : 120 : i++;
628 : : }
629 : 25 : da_val[j] = ']';
630 : 25 : da_val[j + 1] = '\0';
631 : 25 : result = devargs_parse_representor_ports(eth_devargs, da_val,
632 : : devargs, nb_da);
633 [ + + ]: 25 : if (result < 0)
634 : 1 : goto parse_cleanup;
635 : :
636 : 24 : devargs++;
637 : : j = 0;
638 : : memset(da_val, 0, BUFSIZ);
639 : : }
640 : : } else {
641 : 127 : da_val[j] = str[i];
642 : 127 : j++;
643 : : }
644 : 190 : i++;
645 : : }
646 : 12 : result = devargs;
647 : :
648 : : parse_cleanup:
649 : : return result;
650 : : }
651 : :
652 : : RTE_EXPORT_INTERNAL_SYMBOL(rte_eth_devargs_parse)
653 : : int
654 : 38 : rte_eth_devargs_parse(const char *dargs, struct rte_eth_devargs *eth_devargs,
655 : : unsigned int nb_da)
656 : : {
657 : : struct rte_kvargs_pair *pair;
658 : : struct rte_kvargs args;
659 : : bool dup_rep = false;
660 : : int devargs = 0;
661 : : unsigned int i;
662 : : int result = 0;
663 : :
664 : 38 : memset(eth_devargs, 0, nb_da * sizeof(*eth_devargs));
665 : :
666 : 38 : result = eth_dev_devargs_tokenise(&args, dargs);
667 [ + + ]: 38 : if (result < 0)
668 : 4 : goto parse_cleanup;
669 : :
670 [ + + ]: 59 : for (i = 0; i < args.count; i++) {
671 : : pair = &args.pairs[i];
672 [ + - ]: 35 : if (strcmp("representor", pair->key) == 0) {
673 [ + + ]: 35 : if (dup_rep) {
674 : 1 : RTE_ETHDEV_LOG_LINE(ERR, "Duplicated representor key: %s",
675 : : pair->value);
676 : : result = -1;
677 : 1 : goto parse_cleanup;
678 : : }
679 : :
680 : 34 : RTE_ETHDEV_LOG_LINE(DEBUG, "Devarg pattern: %s", pair->value);
681 [ + + ]: 34 : if (pair->value[0] == '[') {
682 : : /* Multiple representor list case */
683 : 16 : devargs = eth_dev_tokenise_representor_list(pair->value,
684 : : eth_devargs, nb_da);
685 [ + + ]: 16 : if (devargs < 0)
686 : 2 : goto parse_cleanup;
687 : : } else {
688 : : /* Single representor case */
689 : 18 : devargs = devargs_parse_representor_ports(eth_devargs, pair->value,
690 : : 0, 1);
691 [ + + ]: 18 : if (devargs < 0)
692 : 7 : goto parse_cleanup;
693 : 11 : devargs++;
694 : : }
695 : : dup_rep = true;
696 : : }
697 : : }
698 : 24 : RTE_ETHDEV_LOG_LINE(DEBUG, "Total devargs parsed %d", devargs);
699 : : result = devargs;
700 : :
701 : 38 : parse_cleanup:
702 : 38 : free(args.str);
703 : :
704 : 38 : return result;
705 : : }
706 : :
707 : : static inline int
708 : : eth_dev_dma_mzone_name(char *name, size_t len, uint16_t port_id, uint16_t queue_id,
709 : : const char *ring_name)
710 : : {
711 : : return snprintf(name, len, "eth_p%d_q%d_%s",
712 : : port_id, queue_id, ring_name);
713 : : }
714 : :
715 : : RTE_EXPORT_INTERNAL_SYMBOL(rte_eth_dma_zone_free)
716 : : int
717 : 0 : rte_eth_dma_zone_free(const struct rte_eth_dev *dev, const char *ring_name,
718 : : uint16_t queue_id)
719 : : {
720 : : char z_name[RTE_MEMZONE_NAMESIZE];
721 : : const struct rte_memzone *mz;
722 : : int rc = 0;
723 : :
724 [ # # ]: 0 : rc = eth_dev_dma_mzone_name(z_name, sizeof(z_name), dev->data->port_id,
725 : : queue_id, ring_name);
726 [ # # ]: 0 : if (rc >= RTE_MEMZONE_NAMESIZE) {
727 : 0 : RTE_ETHDEV_LOG_LINE(ERR, "ring name too long");
728 : 0 : return -ENAMETOOLONG;
729 : : }
730 : :
731 : 0 : mz = rte_memzone_lookup(z_name);
732 [ # # ]: 0 : if (mz)
733 : 0 : rc = rte_memzone_free(mz);
734 : : else
735 : : rc = -ENOENT;
736 : :
737 : : return rc;
738 : : }
739 : :
740 : : RTE_EXPORT_INTERNAL_SYMBOL(rte_eth_dma_zone_reserve)
741 : : const struct rte_memzone *
742 : 0 : rte_eth_dma_zone_reserve(const struct rte_eth_dev *dev, const char *ring_name,
743 : : uint16_t queue_id, size_t size, unsigned int align,
744 : : int socket_id)
745 : : {
746 : : char z_name[RTE_MEMZONE_NAMESIZE];
747 : : const struct rte_memzone *mz;
748 : : int rc;
749 : :
750 [ # # ]: 0 : rc = eth_dev_dma_mzone_name(z_name, sizeof(z_name), dev->data->port_id,
751 : : queue_id, ring_name);
752 [ # # ]: 0 : if (rc >= RTE_MEMZONE_NAMESIZE) {
753 : 0 : RTE_ETHDEV_LOG_LINE(ERR, "ring name too long");
754 : 0 : rte_errno = ENAMETOOLONG;
755 : 0 : return NULL;
756 : : }
757 : :
758 : 0 : mz = rte_memzone_lookup(z_name);
759 [ # # ]: 0 : if (mz) {
760 [ # # # # ]: 0 : if ((socket_id != SOCKET_ID_ANY && socket_id != mz->socket_id) ||
761 [ # # ]: 0 : size > mz->len ||
762 [ # # ]: 0 : ((uintptr_t)mz->addr & (align - 1)) != 0) {
763 : 0 : RTE_ETHDEV_LOG_LINE(ERR,
764 : : "memzone %s does not justify the requested attributes",
765 : : mz->name);
766 : 0 : return NULL;
767 : : }
768 : :
769 : : return mz;
770 : : }
771 : :
772 : 0 : return rte_memzone_reserve_aligned(z_name, size, socket_id,
773 : : RTE_MEMZONE_IOVA_CONTIG, align);
774 : : }
775 : :
776 : : RTE_EXPORT_INTERNAL_SYMBOL(rte_eth_hairpin_queue_peer_bind)
777 : : int
778 : 0 : rte_eth_hairpin_queue_peer_bind(uint16_t cur_port, uint16_t cur_queue,
779 : : struct rte_hairpin_peer_info *peer_info,
780 : : uint32_t direction)
781 : : {
782 : : struct rte_eth_dev *dev;
783 : :
784 [ # # ]: 0 : if (peer_info == NULL)
785 : : return -EINVAL;
786 : :
787 : : /* No need to check the validity again. */
788 : 0 : dev = &rte_eth_devices[cur_port];
789 [ # # ]: 0 : if (dev->dev_ops->hairpin_queue_peer_bind == NULL)
790 : : return -ENOTSUP;
791 : :
792 : 0 : return dev->dev_ops->hairpin_queue_peer_bind(dev, cur_queue, peer_info, direction);
793 : : }
794 : :
795 : : RTE_EXPORT_INTERNAL_SYMBOL(rte_eth_hairpin_queue_peer_unbind)
796 : : int
797 : 0 : rte_eth_hairpin_queue_peer_unbind(uint16_t cur_port, uint16_t cur_queue,
798 : : uint32_t direction)
799 : : {
800 : : struct rte_eth_dev *dev;
801 : :
802 : : /* No need to check the validity again. */
803 : 0 : dev = &rte_eth_devices[cur_port];
804 [ # # ]: 0 : if (dev->dev_ops->hairpin_queue_peer_unbind == NULL)
805 : : return -ENOTSUP;
806 : :
807 : 0 : return dev->dev_ops->hairpin_queue_peer_unbind(dev, cur_queue, direction);
808 : : }
809 : :
810 : : RTE_EXPORT_INTERNAL_SYMBOL(rte_eth_hairpin_queue_peer_update)
811 : : int
812 : 0 : rte_eth_hairpin_queue_peer_update(uint16_t peer_port, uint16_t peer_queue,
813 : : struct rte_hairpin_peer_info *cur_info,
814 : : struct rte_hairpin_peer_info *peer_info,
815 : : uint32_t direction)
816 : : {
817 : : struct rte_eth_dev *dev;
818 : :
819 : : /* Current queue information is not mandatory. */
820 [ # # ]: 0 : if (peer_info == NULL)
821 : : return -EINVAL;
822 : :
823 : : /* No need to check the validity again. */
824 : 0 : dev = &rte_eth_devices[peer_port];
825 [ # # ]: 0 : if (dev->dev_ops->hairpin_queue_peer_update == NULL)
826 : : return -ENOTSUP;
827 : :
828 : 0 : return dev->dev_ops->hairpin_queue_peer_update(dev, peer_queue,
829 : : cur_info, peer_info, direction);
830 : : }
831 : :
832 : : RTE_EXPORT_INTERNAL_SYMBOL(rte_eth_ip_reassembly_dynfield_register)
833 : : int
834 : 0 : rte_eth_ip_reassembly_dynfield_register(int *field_offset, int *flag_offset)
835 : : {
836 : : static const struct rte_mbuf_dynfield field_desc = {
837 : : .name = RTE_MBUF_DYNFIELD_IP_REASSEMBLY_NAME,
838 : : .size = sizeof(rte_eth_ip_reassembly_dynfield_t),
839 : : .align = alignof(rte_eth_ip_reassembly_dynfield_t),
840 : : };
841 : : static const struct rte_mbuf_dynflag ip_reassembly_dynflag = {
842 : : .name = RTE_MBUF_DYNFLAG_IP_REASSEMBLY_INCOMPLETE_NAME,
843 : : };
844 : : int offset;
845 : :
846 : 0 : offset = rte_mbuf_dynfield_register(&field_desc);
847 [ # # ]: 0 : if (offset < 0)
848 : : return -1;
849 [ # # ]: 0 : if (field_offset != NULL)
850 : 0 : *field_offset = offset;
851 : :
852 : 0 : offset = rte_mbuf_dynflag_register(&ip_reassembly_dynflag);
853 [ # # ]: 0 : if (offset < 0)
854 : : return -1;
855 [ # # ]: 0 : if (flag_offset != NULL)
856 : 0 : *flag_offset = offset;
857 : :
858 : : return 0;
859 : : }
860 : :
861 : : RTE_EXPORT_INTERNAL_SYMBOL(rte_eth_pkt_burst_dummy)
862 : : uint16_t
863 : 0 : rte_eth_pkt_burst_dummy(void *queue __rte_unused,
864 : : struct rte_mbuf **pkts __rte_unused,
865 : : uint16_t nb_pkts __rte_unused)
866 : : {
867 : 0 : return 0;
868 : : }
869 : :
870 : : RTE_EXPORT_INTERNAL_SYMBOL(rte_eth_tx_pkt_prepare_dummy)
871 : : uint16_t
872 : 0 : rte_eth_tx_pkt_prepare_dummy(void *queue __rte_unused,
873 : : struct rte_mbuf **pkts __rte_unused,
874 : : uint16_t nb_pkts)
875 : : {
876 : 0 : return nb_pkts;
877 : : }
878 : :
879 : : RTE_EXPORT_INTERNAL_SYMBOL(rte_eth_queue_count_dummy)
880 : : int
881 : 0 : rte_eth_queue_count_dummy(void *queue __rte_unused)
882 : : {
883 : 0 : return 0;
884 : : }
885 : :
886 : : RTE_EXPORT_INTERNAL_SYMBOL(rte_eth_descriptor_status_dummy)
887 : : int
888 : 0 : rte_eth_descriptor_status_dummy(void *queue __rte_unused,
889 : : uint16_t offset __rte_unused)
890 : : {
891 : 0 : return -ENOTSUP;
892 : : }
893 : :
894 : : RTE_EXPORT_INTERNAL_SYMBOL(rte_eth_recycle_tx_mbufs_reuse_dummy)
895 : : uint16_t
896 : 0 : rte_eth_recycle_tx_mbufs_reuse_dummy(void *queue __rte_unused,
897 : : struct rte_eth_recycle_rxq_info *recycle_rxq_info __rte_unused)
898 : : {
899 : 0 : return 0;
900 : : }
901 : :
902 : : RTE_EXPORT_INTERNAL_SYMBOL(rte_eth_recycle_rx_descriptors_refill_dummy)
903 : : void
904 : 0 : rte_eth_recycle_rx_descriptors_refill_dummy(void *queue __rte_unused,
905 : : uint16_t nb __rte_unused)
906 : : {
907 : : /* No action. */
908 : 0 : }
909 : :
910 : : RTE_EXPORT_INTERNAL_SYMBOL(rte_eth_representor_id_get)
911 : : int
912 : 0 : rte_eth_representor_id_get(uint16_t port_id,
913 : : enum rte_eth_representor_type type,
914 : : int controller, int pf, int representor_port,
915 : : uint16_t *repr_id)
916 : : {
917 : : int ret, n, count;
918 : : uint32_t i;
919 : : struct rte_eth_representor_info *info = NULL;
920 : : size_t size;
921 : :
922 [ # # ]: 0 : if (type == RTE_ETH_REPRESENTOR_NONE)
923 : : return 0;
924 [ # # ]: 0 : if (repr_id == NULL)
925 : : return -EINVAL;
926 : :
927 : : /* Get PMD representor range info. */
928 : 0 : ret = rte_eth_representor_info_get(port_id, NULL);
929 [ # # ]: 0 : if (ret == -ENOTSUP && type == RTE_ETH_REPRESENTOR_VF &&
930 [ # # ]: 0 : controller == -1 && pf == -1) {
931 : : /* Direct mapping for legacy VF representor. */
932 : 0 : *repr_id = representor_port;
933 : 0 : return 0;
934 [ # # ]: 0 : } else if (ret < 0) {
935 : : return ret;
936 : : }
937 : : n = ret;
938 : 0 : size = sizeof(*info) + n * sizeof(info->ranges[0]);
939 : 0 : info = calloc(1, size);
940 [ # # ]: 0 : if (info == NULL)
941 : : return -ENOMEM;
942 : 0 : info->nb_ranges_alloc = n;
943 : 0 : ret = rte_eth_representor_info_get(port_id, info);
944 [ # # ]: 0 : if (ret < 0)
945 : 0 : goto out;
946 : :
947 : : /* Default controller and pf to caller. */
948 [ # # ]: 0 : if (controller == -1)
949 : 0 : controller = info->controller;
950 [ # # ]: 0 : if (pf == -1)
951 : 0 : pf = info->pf;
952 : :
953 : : /* Locate representor ID. */
954 : : ret = -ENOENT;
955 [ # # ]: 0 : for (i = 0; i < info->nb_ranges; ++i) {
956 [ # # ]: 0 : if (info->ranges[i].type != type)
957 : 0 : continue;
958 [ # # ]: 0 : if (info->ranges[i].controller != controller)
959 : 0 : continue;
960 [ # # ]: 0 : if (info->ranges[i].id_end < info->ranges[i].id_base) {
961 : 0 : RTE_ETHDEV_LOG_LINE(WARNING, "Port %hu invalid representor ID Range %u - %u, entry %d",
962 : : port_id, info->ranges[i].id_base,
963 : : info->ranges[i].id_end, i);
964 : 0 : continue;
965 : :
966 : : }
967 : 0 : count = info->ranges[i].id_end - info->ranges[i].id_base + 1;
968 [ # # # # ]: 0 : switch (info->ranges[i].type) {
969 : 0 : case RTE_ETH_REPRESENTOR_PF:
970 [ # # ]: 0 : if (pf < info->ranges[i].pf ||
971 [ # # ]: 0 : pf >= info->ranges[i].pf + count)
972 : 0 : continue;
973 : 0 : *repr_id = info->ranges[i].id_base +
974 : 0 : (pf - info->ranges[i].pf);
975 : : ret = 0;
976 : 0 : goto out;
977 : 0 : case RTE_ETH_REPRESENTOR_VF:
978 [ # # ]: 0 : if (info->ranges[i].pf != pf)
979 : 0 : continue;
980 [ # # ]: 0 : if (representor_port < info->ranges[i].vf ||
981 [ # # ]: 0 : representor_port >= info->ranges[i].vf + count)
982 : 0 : continue;
983 : 0 : *repr_id = info->ranges[i].id_base +
984 : 0 : (representor_port - info->ranges[i].vf);
985 : : ret = 0;
986 : 0 : goto out;
987 : 0 : case RTE_ETH_REPRESENTOR_SF:
988 [ # # ]: 0 : if (info->ranges[i].pf != pf)
989 : 0 : continue;
990 [ # # ]: 0 : if (representor_port < info->ranges[i].sf ||
991 [ # # ]: 0 : representor_port >= info->ranges[i].sf + count)
992 : 0 : continue;
993 : 0 : *repr_id = info->ranges[i].id_base +
994 : 0 : (representor_port - info->ranges[i].sf);
995 : : ret = 0;
996 : 0 : goto out;
997 : : default:
998 : : break;
999 : : }
1000 : : }
1001 : 0 : out:
1002 : 0 : free(info);
1003 : 0 : return ret;
1004 : : }
1005 : :
1006 : : RTE_EXPORT_INTERNAL_SYMBOL(rte_eth_switch_domain_alloc)
1007 : : int
1008 : 0 : rte_eth_switch_domain_alloc(uint16_t *domain_id)
1009 : : {
1010 : : uint16_t i;
1011 : :
1012 : 0 : *domain_id = RTE_ETH_DEV_SWITCH_DOMAIN_ID_INVALID;
1013 : :
1014 [ # # ]: 0 : for (i = 0; i < RTE_MAX_ETHPORTS; i++) {
1015 [ # # ]: 0 : if (eth_dev_switch_domains[i].state ==
1016 : : RTE_ETH_SWITCH_DOMAIN_UNUSED) {
1017 : 0 : eth_dev_switch_domains[i].state =
1018 : : RTE_ETH_SWITCH_DOMAIN_ALLOCATED;
1019 : 0 : *domain_id = i;
1020 : 0 : return 0;
1021 : : }
1022 : : }
1023 : :
1024 : : return -ENOSPC;
1025 : : }
1026 : :
1027 : : RTE_EXPORT_INTERNAL_SYMBOL(rte_eth_switch_domain_free)
1028 : : int
1029 : 0 : rte_eth_switch_domain_free(uint16_t domain_id)
1030 : : {
1031 [ # # ]: 0 : if (domain_id == RTE_ETH_DEV_SWITCH_DOMAIN_ID_INVALID ||
1032 : : domain_id >= RTE_MAX_ETHPORTS)
1033 : : return -EINVAL;
1034 : :
1035 [ # # ]: 0 : if (eth_dev_switch_domains[domain_id].state !=
1036 : : RTE_ETH_SWITCH_DOMAIN_ALLOCATED)
1037 : : return -EINVAL;
1038 : :
1039 : 0 : eth_dev_switch_domains[domain_id].state = RTE_ETH_SWITCH_DOMAIN_UNUSED;
1040 : :
1041 : 0 : return 0;
1042 : : }
1043 : :
1044 : : RTE_EXPORT_INTERNAL_SYMBOL(rte_eth_get_restore_flags)
1045 : : uint64_t
1046 : 42 : rte_eth_get_restore_flags(struct rte_eth_dev *dev, enum rte_eth_dev_operation op)
1047 : : {
1048 [ - + ]: 42 : if (dev->dev_ops->get_restore_flags != NULL)
1049 : 0 : return dev->dev_ops->get_restore_flags(dev, op);
1050 : : else
1051 : : return RTE_ETH_RESTORE_ALL;
1052 : : }
|