Branch data Line data Source code
1 : : /* SPDX-License-Identifier: BSD-3-Clause
2 : : *
3 : : * Copyright 2017-2025 NXP
4 : : *
5 : : */
6 : : /* System headers */
7 : : #include <stdalign.h>
8 : : #include <stdio.h>
9 : : #include <inttypes.h>
10 : : #include <unistd.h>
11 : : #include <limits.h>
12 : : #include <sched.h>
13 : : #include <signal.h>
14 : : #include <pthread.h>
15 : : #include <sys/types.h>
16 : : #include <sys/eventfd.h>
17 : :
18 : : #include <eal_export.h>
19 : : #include <rte_byteorder.h>
20 : : #include <rte_common.h>
21 : : #include <rte_interrupts.h>
22 : : #include <rte_log.h>
23 : : #include <rte_debug.h>
24 : : #include <rte_atomic.h>
25 : : #include <rte_branch_prediction.h>
26 : : #include <rte_memory.h>
27 : : #include <rte_tailq.h>
28 : : #include <rte_eal.h>
29 : : #include <rte_alarm.h>
30 : : #include <rte_ether.h>
31 : : #include <ethdev_driver.h>
32 : : #include <rte_malloc.h>
33 : : #include <rte_ring.h>
34 : : #include <bus_driver.h>
35 : : #include <rte_mbuf_pool_ops.h>
36 : : #include <rte_mbuf_dyn.h>
37 : :
38 : : #include <dpaa_of.h>
39 : : #include <bus_dpaa_driver.h>
40 : : #include <rte_dpaa_logs.h>
41 : : #include <dpaax_iova_table.h>
42 : :
43 : : #include <fsl_usd.h>
44 : : #include <fsl_qman.h>
45 : : #include <fsl_bman.h>
46 : : #include <netcfg.h>
47 : : #include <fman.h>
48 : :
49 : : #define DPAA_SOC_ID_FILE "/sys/devices/soc0/soc_id"
50 : : #define DPAA_SVR_MASK 0xffff0000
51 : : #define RTE_PRIORITY_102 102
52 : :
53 : : #define DPAA_PUSH_RXQ_NUM_ARG "dpaa_push_rxq_num"
54 : : /* At present we allow up to 4 push mode queues as default - as each of
55 : : * this queue need dedicated portal and we are short of portals.
56 : : */
57 : : #define DPAA_MAX_PUSH_MODE_QUEUE 8
58 : : #define DPAA_DEFAULT_PUSH_MODE_QUEUE 4
59 : :
60 : : struct rte_dpaa_bus {
61 : : struct rte_bus bus;
62 : : TAILQ_HEAD(, rte_dpaa_device) device_list;
63 : : TAILQ_HEAD(, rte_dpaa_driver) driver_list;
64 : : int device_count;
65 : : int detected;
66 : : uint32_t svr_ver;
67 : : uint16_t max_push_rxq_num;
68 : : RTE_ATOMIC(uint16_t) push_rxq_num;
69 : : };
70 : :
71 : : static struct rte_dpaa_bus rte_dpaa_bus;
72 : : static struct netcfg_info *dpaa_netcfg;
73 : :
74 : : /* define a variable to hold the portal_key, once created.*/
75 : : static pthread_key_t dpaa_portal_key;
76 : : /* dpaa lcore specific portals */
77 : : struct dpaa_portal *dpaa_portals[RTE_MAX_LCORE] = {NULL};
78 : : static int dpaa_bus_global_init;
79 : :
80 : : #define FSL_DPAA_BUS_NAME dpaa_bus
81 : :
82 : : RTE_EXPORT_INTERNAL_SYMBOL(per_lcore_dpaa_io)
83 : : RTE_DEFINE_PER_LCORE(struct dpaa_portal *, dpaa_io);
84 : :
85 : : #define DPAA_SEQN_DYNFIELD_NAME "dpaa_seqn_dynfield"
86 : : RTE_EXPORT_INTERNAL_SYMBOL(dpaa_seqn_dynfield_offset)
87 : : int dpaa_seqn_dynfield_offset = -1;
88 : :
89 : : RTE_EXPORT_INTERNAL_SYMBOL(dpaa_get_eth_port_cfg)
90 : :
91 : : RTE_EXPORT_INTERNAL_SYMBOL(dpaa_soc_ver)
92 : 0 : uint32_t dpaa_soc_ver(void)
93 : : {
94 : 0 : return rte_dpaa_bus.svr_ver;
95 : : }
96 : :
97 : : struct fm_eth_port_cfg *
98 : 0 : dpaa_get_eth_port_cfg(int dev_id)
99 : : {
100 : 0 : return &dpaa_netcfg->port_cfg[dev_id];
101 : : }
102 : :
103 : : RTE_EXPORT_INTERNAL_SYMBOL(dpaa_push_queue_num_update)
104 : : int
105 : 0 : dpaa_push_queue_num_update(void)
106 : : {
107 : : int ret = false;
108 : : uint16_t current, new_val;
109 : :
110 : 0 : current = rte_atomic_load_explicit(&rte_dpaa_bus.push_rxq_num,
111 : : rte_memory_order_acquire);
112 [ # # ]: 0 : if (current < rte_dpaa_bus.max_push_rxq_num) {
113 : 0 : new_val = current + 1;
114 [ # # ]: 0 : if (rte_atomic_compare_exchange_strong_explicit(&rte_dpaa_bus.push_rxq_num,
115 : : ¤t, new_val,
116 : : rte_memory_order_release,
117 : : rte_memory_order_acquire))
118 : : ret = true;
119 : : }
120 : :
121 : 0 : return ret;
122 : : }
123 : :
124 : : RTE_EXPORT_INTERNAL_SYMBOL(dpaa_push_queue_max_num)
125 : : uint16_t
126 : 0 : dpaa_push_queue_max_num(void)
127 : : {
128 : 0 : return rte_dpaa_bus.max_push_rxq_num;
129 : : }
130 : :
131 : : static int
132 : : compare_dpaa_devices(struct rte_dpaa_device *dev1,
133 : : struct rte_dpaa_device *dev2)
134 : : {
135 : : int comp = 0;
136 : :
137 : : /* Segregating ETH from SEC devices */
138 : 0 : if (dev1->device_type > dev2->device_type)
139 : : comp = 1;
140 [ # # ]: 0 : else if (dev1->device_type < dev2->device_type)
141 : : comp = -1;
142 : : else
143 : : comp = 0;
144 : :
145 [ # # ]: 0 : if ((comp != 0) || (dev1->device_type != FSL_DPAA_ETH))
146 : : return comp;
147 : :
148 [ # # ]: 0 : if (dev1->id.fman_id > dev2->id.fman_id) {
149 : : comp = 1;
150 [ # # ]: 0 : } else if (dev1->id.fman_id < dev2->id.fman_id) {
151 : : comp = -1;
152 : : } else {
153 : : /* FMAN ids match, check for mac_id */
154 [ # # ]: 0 : if (dev1->id.mac_id > dev2->id.mac_id)
155 : : comp = 1;
156 [ # # ]: 0 : else if (dev1->id.mac_id < dev2->id.mac_id)
157 : : comp = -1;
158 : : else
159 : : comp = 0;
160 : : }
161 : :
162 : : return comp;
163 : : }
164 : :
165 : : static inline void
166 : 0 : dpaa_add_to_device_list(struct rte_dpaa_device *newdev)
167 : : {
168 : : int comp, inserted = 0;
169 : : struct rte_dpaa_device *dev = NULL;
170 : : struct rte_dpaa_device *tdev = NULL;
171 : :
172 [ # # # # ]: 0 : RTE_TAILQ_FOREACH_SAFE(dev, &rte_dpaa_bus.device_list, next, tdev) {
173 : : comp = compare_dpaa_devices(newdev, dev);
174 : : if (comp < 0) {
175 : 0 : TAILQ_INSERT_BEFORE(dev, newdev, next);
176 : : inserted = 1;
177 : : break;
178 : : }
179 : : }
180 : :
181 : : if (!inserted)
182 : 0 : TAILQ_INSERT_TAIL(&rte_dpaa_bus.device_list, newdev, next);
183 : 0 : }
184 : :
185 : : /*
186 : : * Reads the SEC device from DTS
187 : : * Returns -1 if SEC devices not available, 0 otherwise
188 : : */
189 : : static inline int
190 : : dpaa_sec_available(void)
191 : : {
192 : : const struct device_node *caam_node;
193 : :
194 [ # # ]: 0 : for_each_compatible_node(caam_node, NULL, "fsl,sec-v4.0") {
195 : : return 0;
196 : : }
197 : :
198 : : return -1;
199 : : }
200 : :
201 : : static void dpaa_clean_device_list(void);
202 : :
203 : : static struct rte_devargs *
204 : 0 : dpaa_devargs_lookup(struct rte_dpaa_device *dev)
205 : : {
206 : : struct rte_devargs *devargs;
207 : : char dev_name[32];
208 : :
209 [ # # ]: 0 : RTE_EAL_DEVARGS_FOREACH("dpaa_bus", devargs) {
210 : 0 : devargs->bus->parse(devargs->name, &dev_name);
211 [ # # ]: 0 : if (strcmp(dev_name, dev->device.name) == 0) {
212 : 0 : DPAA_BUS_INFO("**Devargs matched %s", dev_name);
213 : 0 : return devargs;
214 : : }
215 : : }
216 : : return NULL;
217 : : }
218 : :
219 : : static int
220 : 0 : dpaa_create_device_list(void)
221 : : {
222 : : int i;
223 : : int ret;
224 : : struct rte_dpaa_device *dev;
225 : : struct fm_eth_port_cfg *cfg;
226 : : struct fman_if *fman_intf;
227 : :
228 : 0 : rte_dpaa_bus.device_count = 0;
229 : :
230 : : /* Creating Ethernet Devices */
231 [ # # # # ]: 0 : for (i = 0; dpaa_netcfg && (i < dpaa_netcfg->num_ethports); i++) {
232 : 0 : dev = calloc(1, sizeof(struct rte_dpaa_device));
233 [ # # ]: 0 : if (!dev) {
234 : 0 : DPAA_BUS_LOG(ERR, "Failed to allocate ETH devices");
235 : : ret = -ENOMEM;
236 : 0 : goto cleanup;
237 : : }
238 : :
239 : 0 : dev->device.bus = &rte_dpaa_bus.bus;
240 : 0 : dev->device.numa_node = SOCKET_ID_ANY;
241 : :
242 : : /* Allocate interrupt handle instance */
243 : 0 : dev->intr_handle =
244 : 0 : rte_intr_instance_alloc(RTE_INTR_INSTANCE_F_PRIVATE);
245 [ # # ]: 0 : if (dev->intr_handle == NULL) {
246 : 0 : DPAA_BUS_LOG(ERR, "Failed to allocate intr handle");
247 : : ret = -ENOMEM;
248 : 0 : free(dev);
249 : 0 : goto cleanup;
250 : : }
251 : :
252 : 0 : cfg = &dpaa_netcfg->port_cfg[i];
253 : 0 : fman_intf = cfg->fman_if;
254 : :
255 : : /* Device identifiers */
256 : 0 : dev->id.fman_id = fman_intf->fman->idx + 1;
257 : 0 : dev->id.mac_id = fman_intf->mac_idx;
258 : 0 : dev->device_type = FSL_DPAA_ETH;
259 : 0 : dev->id.dev_id = i;
260 : :
261 : : /* Create device name */
262 [ # # ]: 0 : memset(dev->name, 0, RTE_ETH_NAME_MAX_LEN);
263 [ # # ]: 0 : if (fman_intf->mac_type == fman_offline_internal) {
264 : 0 : snprintf(dev->name, RTE_ETH_NAME_MAX_LEN, "fm%d-oh%d",
265 : 0 : (fman_intf->fman->idx + 1), fman_intf->mac_idx);
266 [ # # ]: 0 : } else if (fman_intf->mac_type == fman_onic) {
267 : 0 : snprintf(dev->name, RTE_ETH_NAME_MAX_LEN, "fm%d-onic%d",
268 : 0 : (fman_intf->fman->idx + 1), fman_intf->mac_idx);
269 : : } else {
270 : 0 : snprintf(dev->name, RTE_ETH_NAME_MAX_LEN, "fm%d-mac%d",
271 : 0 : (fman_intf->fman->idx + 1), fman_intf->mac_idx);
272 : : }
273 : 0 : dev->device.name = dev->name;
274 : 0 : dev->device.devargs = dpaa_devargs_lookup(dev);
275 : :
276 : 0 : dpaa_add_to_device_list(dev);
277 : : }
278 : :
279 : 0 : rte_dpaa_bus.device_count += i;
280 : :
281 : : /* Unlike case of ETH, RTE_LIBRTE_DPAA_MAX_CRYPTODEV SEC devices are
282 : : * constantly created only if "sec" property is found in the device
283 : : * tree. Logically there is no limit for number of devices (QI
284 : : * interfaces) that can be created.
285 : : */
286 : :
287 : : if (dpaa_sec_available()) {
288 : 0 : DPAA_BUS_LOG(INFO, "DPAA SEC devices are not available");
289 : 0 : goto qdma_dpaa;
290 : : }
291 : :
292 : : /* Creating SEC Devices */
293 [ # # ]: 0 : for (i = 0; i < RTE_LIBRTE_DPAA_MAX_CRYPTODEV; i++) {
294 : 0 : dev = calloc(1, sizeof(struct rte_dpaa_device));
295 [ # # ]: 0 : if (!dev) {
296 : 0 : DPAA_BUS_LOG(ERR, "Failed to allocate SEC devices");
297 : : ret = -1;
298 : 0 : goto cleanup;
299 : : }
300 : :
301 : : /* Allocate interrupt handle instance */
302 : 0 : dev->intr_handle =
303 : 0 : rte_intr_instance_alloc(RTE_INTR_INSTANCE_F_PRIVATE);
304 [ # # ]: 0 : if (dev->intr_handle == NULL) {
305 : 0 : DPAA_BUS_LOG(ERR, "Failed to allocate intr handle");
306 : : ret = -ENOMEM;
307 : 0 : free(dev);
308 : 0 : goto cleanup;
309 : : }
310 : :
311 : 0 : dev->device_type = FSL_DPAA_CRYPTO;
312 : 0 : dev->id.dev_id = rte_dpaa_bus.device_count + i;
313 : :
314 : : /* Even though RTE_CRYPTODEV_NAME_MAX_LEN is valid length of
315 : : * crypto PMD, using RTE_ETH_NAME_MAX_LEN as that is the size
316 : : * allocated for dev->name/
317 : : */
318 : 0 : memset(dev->name, 0, RTE_ETH_NAME_MAX_LEN);
319 : 0 : sprintf(dev->name, "dpaa_sec-%d", i+1);
320 : 0 : DPAA_BUS_LOG(INFO, "%s cryptodev added", dev->name);
321 : 0 : dev->device.name = dev->name;
322 : 0 : dev->device.devargs = dpaa_devargs_lookup(dev);
323 : :
324 : 0 : dpaa_add_to_device_list(dev);
325 : : }
326 : :
327 : 0 : rte_dpaa_bus.device_count += i;
328 : :
329 : : qdma_dpaa:
330 : : /* Creating QDMA Device */
331 [ # # ]: 0 : for (i = 0; i < RTE_DPAA_QDMA_DEVICES; i++) {
332 : 0 : dev = calloc(1, sizeof(struct rte_dpaa_device));
333 [ # # ]: 0 : if (!dev) {
334 : 0 : DPAA_BUS_LOG(ERR, "Failed to allocate QDMA device");
335 : : ret = -1;
336 : 0 : goto cleanup;
337 : : }
338 : :
339 : 0 : dev->device_type = FSL_DPAA_QDMA;
340 : 0 : dev->id.dev_id = rte_dpaa_bus.device_count + i;
341 : :
342 : 0 : memset(dev->name, 0, RTE_ETH_NAME_MAX_LEN);
343 : : sprintf(dev->name, "dpaa_qdma-%d", i+1);
344 : 0 : DPAA_BUS_LOG(INFO, "%s qdma device added", dev->name);
345 : 0 : dev->device.name = dev->name;
346 : 0 : dev->device.devargs = dpaa_devargs_lookup(dev);
347 : :
348 : 0 : dpaa_add_to_device_list(dev);
349 : : }
350 : 0 : rte_dpaa_bus.device_count += i;
351 : :
352 : 0 : return 0;
353 : :
354 : 0 : cleanup:
355 : 0 : dpaa_clean_device_list();
356 : 0 : return ret;
357 : : }
358 : :
359 : : static void
360 : 0 : dpaa_clean_device_list(void)
361 : : {
362 : : struct rte_dpaa_device *dev = NULL;
363 : : struct rte_dpaa_device *tdev = NULL;
364 : :
365 [ # # ]: 0 : RTE_TAILQ_FOREACH_SAFE(dev, &rte_dpaa_bus.device_list, next, tdev) {
366 [ # # ]: 0 : TAILQ_REMOVE(&rte_dpaa_bus.device_list, dev, next);
367 : 0 : rte_intr_instance_free(dev->intr_handle);
368 : 0 : free(dev);
369 : : dev = NULL;
370 : : }
371 : 0 : }
372 : :
373 : : RTE_EXPORT_INTERNAL_SYMBOL(rte_dpaa_portal_init)
374 : 0 : int rte_dpaa_portal_init(void *arg)
375 : : {
376 : : static const struct rte_mbuf_dynfield dpaa_seqn_dynfield_desc = {
377 : : .name = DPAA_SEQN_DYNFIELD_NAME,
378 : : .size = sizeof(dpaa_seqn_t),
379 : : .align = alignof(dpaa_seqn_t),
380 : : };
381 : : unsigned int cpu, lcore = rte_lcore_id();
382 : : int ret;
383 : :
384 : 0 : BUS_INIT_FUNC_TRACE();
385 : :
386 [ # # ]: 0 : if ((size_t)arg == 1 || lcore == LCORE_ID_ANY)
387 : 0 : lcore = rte_get_main_lcore();
388 : : else
389 [ # # ]: 0 : if (lcore >= RTE_MAX_LCORE)
390 : : return -1;
391 : :
392 : 0 : cpu = rte_lcore_to_cpu_id(lcore);
393 : :
394 : 0 : dpaa_seqn_dynfield_offset =
395 : 0 : rte_mbuf_dynfield_register(&dpaa_seqn_dynfield_desc);
396 [ # # ]: 0 : if (dpaa_seqn_dynfield_offset < 0) {
397 : 0 : DPAA_BUS_LOG(ERR, "Failed to register mbuf field for dpaa sequence number");
398 : 0 : return -rte_errno;
399 : : }
400 : :
401 : : /* Initialise bman thread portals */
402 : 0 : ret = bman_thread_init();
403 [ # # ]: 0 : if (ret) {
404 : 0 : DPAA_BUS_LOG(ERR, "bman_thread_init failed on core %u"
405 : : " (lcore=%u) with ret: %d", cpu, lcore, ret);
406 : 0 : return ret;
407 : : }
408 : :
409 : 0 : DPAA_BUS_LOG(DEBUG, "BMAN thread initialized - CPU=%d lcore=%d",
410 : : cpu, lcore);
411 : :
412 : : /* Initialise qman thread portals */
413 : 0 : ret = qman_thread_init();
414 [ # # ]: 0 : if (ret) {
415 : 0 : DPAA_BUS_LOG(ERR, "qman_thread_init failed on core %u"
416 : : " (lcore=%u) with ret: %d", cpu, lcore, ret);
417 : 0 : bman_thread_finish();
418 : 0 : return ret;
419 : : }
420 : :
421 : 0 : DPAA_BUS_LOG(DEBUG, "QMAN thread initialized - CPU=%d lcore=%d",
422 : : cpu, lcore);
423 : :
424 : 0 : DPAA_PER_LCORE_PORTAL = rte_malloc(NULL, sizeof(struct dpaa_portal),
425 : : RTE_CACHE_LINE_SIZE);
426 [ # # ]: 0 : if (!DPAA_PER_LCORE_PORTAL) {
427 : 0 : DPAA_BUS_LOG(ERR, "Unable to allocate memory");
428 : 0 : bman_thread_finish();
429 : 0 : qman_thread_finish();
430 : 0 : return -ENOMEM;
431 : : }
432 : :
433 : 0 : DPAA_PER_LCORE_PORTAL->qman_idx = qman_get_portal_index();
434 [ # # ]: 0 : DPAA_PER_LCORE_PORTAL->bman_idx = bman_get_portal_index();
435 : 0 : DPAA_PER_LCORE_PORTAL->tid = rte_gettid();
436 : :
437 : 0 : ret = pthread_setspecific(dpaa_portal_key,
438 : : (void *)DPAA_PER_LCORE_PORTAL);
439 [ # # ]: 0 : if (ret) {
440 : 0 : DPAA_BUS_LOG(ERR, "pthread_setspecific failed on core %u"
441 : : " (lcore=%u) with ret: %d", cpu, lcore, ret);
442 : 0 : dpaa_portal_finish(NULL);
443 : :
444 : 0 : return ret;
445 : : }
446 : 0 : dpaa_portals[lcore] = DPAA_PER_LCORE_PORTAL;
447 : :
448 : 0 : DPAA_BUS_LOG(DEBUG, "QMAN thread initialized");
449 : :
450 : 0 : return 0;
451 : : }
452 : :
453 : : RTE_EXPORT_INTERNAL_SYMBOL(rte_dpaa_portal_fq_init)
454 : : int
455 : 0 : rte_dpaa_portal_fq_init(void *arg, struct qman_fq *fq)
456 : : {
457 : : /* Affine above created portal with channel*/
458 : : u32 sdqcr;
459 : : int ret;
460 : :
461 [ # # ]: 0 : if (unlikely(!DPAA_PER_LCORE_PORTAL)) {
462 : 0 : ret = rte_dpaa_portal_init(arg);
463 [ # # ]: 0 : if (ret < 0) {
464 : 0 : DPAA_BUS_LOG(ERR, "portal initialization failure");
465 : 0 : return ret;
466 : : }
467 : : }
468 : :
469 : : /* Initialise qman specific portals */
470 : 0 : ret = fsl_qman_fq_portal_init(fq->qp);
471 [ # # ]: 0 : if (ret) {
472 : 0 : DPAA_BUS_LOG(ERR, "Unable to init fq portal");
473 : 0 : return -1;
474 : : }
475 : :
476 : 0 : sdqcr = QM_SDQCR_CHANNELS_POOL_CONV(fq->ch_id);
477 : 0 : qman_static_dequeue_add(sdqcr, fq->qp);
478 : :
479 : 0 : return 0;
480 : : }
481 : :
482 : : RTE_EXPORT_INTERNAL_SYMBOL(rte_dpaa_portal_fq_close)
483 : 0 : int rte_dpaa_portal_fq_close(struct qman_fq *fq)
484 : : {
485 : 0 : return fsl_qman_fq_portal_destroy(fq->qp);
486 : : }
487 : :
488 : : void
489 : 247 : dpaa_portal_finish(void *arg)
490 : : {
491 : : struct dpaa_portal *dpaa_io_portal = (struct dpaa_portal *)arg;
492 : :
493 [ + - ]: 247 : if (!dpaa_io_portal) {
494 : 247 : DPAA_BUS_LOG(DEBUG, "Portal already cleaned");
495 : 247 : return;
496 : : }
497 : :
498 : 0 : bman_thread_finish();
499 : 0 : qman_thread_finish();
500 : :
501 : 0 : pthread_setspecific(dpaa_portal_key, NULL);
502 : :
503 : 0 : rte_free(dpaa_io_portal);
504 : : dpaa_io_portal = NULL;
505 : 0 : DPAA_PER_LCORE_PORTAL = NULL;
506 : 0 : dpaa_portals[rte_lcore_id()] = NULL;
507 : 0 : DPAA_BUS_DEBUG("Portal cleanup done for lcore = %d", rte_lcore_id());
508 : : }
509 : :
510 : : static int
511 : 37 : rte_dpaa_bus_parse(const char *name, void *out)
512 : : {
513 : : unsigned int i, j;
514 : : size_t delta, dev_delta;
515 : : size_t max_name_len;
516 : :
517 : : /* There are two ways of passing device name, with and without
518 : : * separator. "dpaa_bus:fm1-mac3" with separator, and "fm1-mac3"
519 : : * without separator. Both need to be handled.
520 : : * It is also possible that "name=fm1-mac3" is passed along.
521 : : */
522 : 37 : DPAA_BUS_DEBUG("Parse device name (%s)", name);
523 : :
524 : : delta = 0;
525 [ + - ]: 37 : if (strncmp(name, "dpaa_bus:", 9) == 0) {
526 : : delta = 9;
527 [ - + ]: 37 : } else if (strncmp(name, "name=", 5) == 0) {
528 : : delta = 5;
529 : : }
530 : :
531 : : /* dev_delta points to the dev name (mac/oh/onic). Not valid for
532 : : * dpaa_sec.
533 : : */
534 : 37 : dev_delta = delta + sizeof("fm.-") - 1;
535 : :
536 [ - + ]: 37 : if (strncmp("dpaa_sec", &name[delta], 8) == 0) {
537 [ # # ]: 0 : if (sscanf(&name[delta], "dpaa_sec-%u", &i) != 1 ||
538 [ # # # # ]: 0 : i < 1 || i > 4)
539 : : return -EINVAL;
540 : : max_name_len = sizeof("dpaa_sec-.") - 1;
541 [ - + ]: 37 : } else if (strncmp("oh", &name[dev_delta], 2) == 0) {
542 [ # # ]: 0 : if (sscanf(&name[delta], "fm%u-oh%u", &i, &j) != 2 ||
543 [ # # # # ]: 0 : i >= 2 || j >= 16)
544 : : return -EINVAL;
545 : : max_name_len = sizeof("fm.-oh..") - 1;
546 [ - + ]: 37 : } else if (strncmp("onic", &name[dev_delta], 4) == 0) {
547 [ # # ]: 0 : if (sscanf(&name[delta], "fm%u-onic%u", &i, &j) != 2 ||
548 [ # # # # ]: 0 : i >= 2 || j >= 16)
549 : : return -EINVAL;
550 : : max_name_len = sizeof("fm.-onic..") - 1;
551 : : } else {
552 [ - + ]: 37 : if (sscanf(&name[delta], "fm%u-mac%u", &i, &j) != 2 ||
553 [ # # # # ]: 0 : i >= 2 || j >= 16)
554 : : return -EINVAL;
555 : : max_name_len = sizeof("fm.-mac..") - 1;
556 : : }
557 : :
558 [ # # ]: 0 : if (out != NULL) {
559 : : char *out_name = out;
560 : :
561 : : /* Do not check for truncation, either name ends with
562 : : * '\0' or the device name is followed by parameters and there
563 : : * will be a ',' instead. Not copying past this comma is not an
564 : : * error.
565 : : */
566 [ # # ]: 0 : strlcpy(out_name, &name[delta], max_name_len + 1);
567 : :
568 : : /* Second digit of mac%u could instead be ','. */
569 [ # # ]: 0 : if ((strlen(out_name) == max_name_len) &&
570 [ # # ]: 0 : out_name[max_name_len] == ',')
571 : 0 : out_name[max_name_len] = '\0';
572 : : }
573 : :
574 : : return 0;
575 : : }
576 : :
577 : : #define DPAA_DEV_PATH1 "/sys/devices/platform/soc/soc:fsl,dpaa"
578 : : #define DPAA_DEV_PATH2 "/sys/devices/platform/fsl,dpaa"
579 : :
580 : : static int
581 : 187 : rte_dpaa_bus_scan(void)
582 : : {
583 : : int ret;
584 : :
585 : 187 : BUS_INIT_FUNC_TRACE();
586 : :
587 [ + - + - ]: 374 : if ((access(DPAA_DEV_PATH1, F_OK) != 0) &&
588 : 187 : (access(DPAA_DEV_PATH2, F_OK) != 0)) {
589 : 187 : DPAA_BUS_LOG(DEBUG, "DPAA Bus not present. Skipping.");
590 : 187 : return 0;
591 : : }
592 : :
593 [ # # ]: 0 : if (rte_dpaa_bus.detected)
594 : : return 0;
595 : :
596 : 0 : rte_dpaa_bus.detected = 1;
597 : :
598 : : /* create the key, supplying a function that'll be invoked
599 : : * when a portal affined thread will be deleted.
600 : : */
601 : 0 : ret = pthread_key_create(&dpaa_portal_key, dpaa_portal_finish);
602 [ # # ]: 0 : if (ret) {
603 : 0 : DPAA_BUS_LOG(DEBUG, "Unable to create pthread key. (%d)", ret);
604 : 0 : dpaa_clean_device_list();
605 : 0 : return ret;
606 : : }
607 : :
608 : : return 0;
609 : : }
610 : :
611 : : /* register a dpaa bus based dpaa driver */
612 : : RTE_EXPORT_INTERNAL_SYMBOL(rte_dpaa_driver_register)
613 : : void
614 : 762 : rte_dpaa_driver_register(struct rte_dpaa_driver *driver)
615 : : {
616 [ - + ]: 762 : RTE_VERIFY(driver);
617 : :
618 : 762 : BUS_INIT_FUNC_TRACE();
619 : :
620 : 762 : TAILQ_INSERT_TAIL(&rte_dpaa_bus.driver_list, driver, next);
621 : 762 : }
622 : :
623 : : /* un-register a dpaa bus based dpaa driver */
624 : : RTE_EXPORT_INTERNAL_SYMBOL(rte_dpaa_driver_unregister)
625 : : void
626 : 0 : rte_dpaa_driver_unregister(struct rte_dpaa_driver *driver)
627 : : {
628 : 0 : BUS_INIT_FUNC_TRACE();
629 : :
630 [ # # ]: 0 : TAILQ_REMOVE(&rte_dpaa_bus.driver_list, driver, next);
631 : 0 : }
632 : :
633 : : static int
634 : 0 : rte_dpaa_device_match(struct rte_dpaa_driver *drv,
635 : : struct rte_dpaa_device *dev)
636 : : {
637 [ # # ]: 0 : if (!drv || !dev) {
638 : 0 : DPAA_BUS_DEBUG("Invalid drv or dev received.");
639 : 0 : return -1;
640 : : }
641 : :
642 [ # # ]: 0 : if (drv->drv_type == dev->device_type)
643 : 0 : return 0;
644 : :
645 : : return -1;
646 : : }
647 : :
648 : : static int
649 : 0 : rte_dpaa_bus_dev_build(void)
650 : : {
651 : : int ret;
652 : :
653 : : /* Load the device-tree driver */
654 : : ret = of_init();
655 [ # # ]: 0 : if (ret) {
656 : 0 : DPAA_BUS_LOG(ERR, "of_init failed with ret: %d", ret);
657 : 0 : return -1;
658 : : }
659 : :
660 : : /* Get the interface configurations from device-tree */
661 : 0 : dpaa_netcfg = netcfg_acquire();
662 [ # # ]: 0 : if (!dpaa_netcfg) {
663 : 0 : DPAA_BUS_LOG(ERR,
664 : : "netcfg failed: /dev/fsl_usdpaa device not available");
665 : 0 : DPAA_BUS_WARN(
666 : : "Check if you are using USDPAA based device tree");
667 : 0 : return -EINVAL;
668 : : }
669 : :
670 : 0 : DPAA_BUS_LOG(NOTICE, "DPAA Bus Detected");
671 : :
672 [ # # ]: 0 : if (!dpaa_netcfg->num_ethports) {
673 : 0 : DPAA_BUS_LOG(INFO, "NO DPDK mapped net interfaces available");
674 : : /* This is not an error */
675 : : }
676 : :
677 : : #ifdef RTE_LIBRTE_DPAA_DEBUG_DRIVER
678 : : dump_netcfg(dpaa_netcfg, stdout);
679 : : #endif
680 : :
681 : 0 : DPAA_BUS_LOG(DEBUG, "Number of ethernet devices = %d",
682 : : dpaa_netcfg->num_ethports);
683 : 0 : ret = dpaa_create_device_list();
684 [ # # ]: 0 : if (ret) {
685 : 0 : DPAA_BUS_LOG(ERR, "Unable to create device list. (%d)", ret);
686 : 0 : return ret;
687 : : }
688 : : return 0;
689 : : }
690 : :
691 : 0 : static int rte_dpaa_setup_intr(struct rte_intr_handle *intr_handle)
692 : : {
693 : : int fd;
694 : :
695 : 0 : fd = eventfd(0, EFD_NONBLOCK | EFD_CLOEXEC);
696 [ # # ]: 0 : if (fd < 0) {
697 : 0 : DPAA_BUS_ERR("Cannot set up eventfd, error %i (%s)",
698 : : errno, strerror(errno));
699 : 0 : return errno;
700 : : }
701 : :
702 [ # # ]: 0 : if (rte_intr_fd_set(intr_handle, fd))
703 : 0 : return rte_errno;
704 : :
705 [ # # ]: 0 : if (rte_intr_type_set(intr_handle, RTE_INTR_HANDLE_EXT))
706 : 0 : return rte_errno;
707 : :
708 : : return 0;
709 : : }
710 : :
711 : : static int
712 : 182 : rte_dpaa_bus_probe(void)
713 : : {
714 : : int ret = -1;
715 : : struct rte_dpaa_device *dev;
716 : : struct rte_dpaa_driver *drv;
717 : : FILE *svr_file = NULL;
718 : : uint32_t svr_ver;
719 : 182 : int probe_all = rte_dpaa_bus.bus.conf.scan_mode != RTE_BUS_SCAN_ALLOWLIST;
720 : : static int process_once;
721 : : char *penv;
722 : :
723 : : /* If DPAA bus is not present nothing needs to be done */
724 [ - + ]: 182 : if (!rte_dpaa_bus.detected)
725 : : return 0;
726 : :
727 [ # # ]: 0 : if (rte_dpaa_bus.bus.conf.scan_mode != RTE_BUS_SCAN_ALLOWLIST)
728 : : probe_all = true;
729 : :
730 : 0 : svr_file = fopen(DPAA_SOC_ID_FILE, "r");
731 [ # # ]: 0 : if (svr_file) {
732 [ # # ]: 0 : if (fscanf(svr_file, "svr:%x", &svr_ver) > 0)
733 : 0 : rte_dpaa_bus.svr_ver = svr_ver & DPAA_SVR_MASK;
734 : : else
735 : 0 : rte_dpaa_bus.svr_ver = 0;
736 : 0 : fclose(svr_file);
737 : : } else {
738 : 0 : rte_dpaa_bus.svr_ver = 0;
739 : : }
740 [ # # ]: 0 : if (rte_dpaa_bus.svr_ver == SVR_LS1046A_FAMILY) {
741 : 0 : DPAA_BUS_LOG(INFO, "This is LS1046A family SoC.");
742 [ # # ]: 0 : } else if (rte_dpaa_bus.svr_ver == SVR_LS1043A_FAMILY) {
743 : 0 : DPAA_BUS_LOG(INFO, "This is LS1043A family SoC.");
744 : : } else {
745 : 0 : DPAA_BUS_LOG(WARNING,
746 : : "This is Unknown(%08x) DPAA1 family SoC.",
747 : : rte_dpaa_bus.svr_ver);
748 : : }
749 : :
750 : : /* Disabling the default push mode for LS1043A */
751 [ # # ]: 0 : if (rte_dpaa_bus.svr_ver == SVR_LS1043A_FAMILY) {
752 : 0 : rte_dpaa_bus.max_push_rxq_num = 0;
753 : 0 : return 0;
754 : : }
755 : :
756 : 0 : penv = getenv("DPAA_PUSH_QUEUES_NUMBER");
757 [ # # ]: 0 : if (penv)
758 : 0 : rte_dpaa_bus.max_push_rxq_num = atoi(penv);
759 [ # # ]: 0 : if (rte_dpaa_bus.max_push_rxq_num > DPAA_MAX_PUSH_MODE_QUEUE)
760 : 0 : rte_dpaa_bus.max_push_rxq_num = DPAA_MAX_PUSH_MODE_QUEUE;
761 : :
762 : : /* Device list creation is only done once */
763 [ # # ]: 0 : if (!process_once) {
764 : 0 : rte_dpaa_bus_dev_build();
765 : : /* One time load of Qman/Bman drivers */
766 : 0 : ret = qman_global_init();
767 [ # # ]: 0 : if (ret) {
768 : 0 : DPAA_BUS_ERR("QMAN initialization failed: %d",
769 : : ret);
770 : 0 : return ret;
771 : : }
772 : 0 : ret = bman_global_init();
773 [ # # ]: 0 : if (ret) {
774 : 0 : DPAA_BUS_ERR("BMAN initialization failed: %d",
775 : : ret);
776 : 0 : return ret;
777 : : }
778 : : }
779 : 0 : process_once = 1;
780 : :
781 : : /* If no device present on DPAA bus nothing needs to be done */
782 [ # # ]: 0 : if (TAILQ_EMPTY(&rte_dpaa_bus.device_list))
783 : : return 0;
784 : :
785 : : /* Register DPAA mempool ops only if any DPAA device has
786 : : * been detected.
787 : : */
788 : 0 : rte_mbuf_set_platform_mempool_ops(DPAA_MEMPOOL_OPS_NAME);
789 : :
790 [ # # ]: 0 : TAILQ_FOREACH(dev, &rte_dpaa_bus.device_list, next) {
791 [ # # ]: 0 : if (dev->device_type == FSL_DPAA_ETH) {
792 : 0 : ret = rte_dpaa_setup_intr(dev->intr_handle);
793 [ # # ]: 0 : if (ret)
794 : 0 : DPAA_BUS_ERR("Error setting up interrupt.");
795 : : }
796 : : }
797 : :
798 : : /* And initialize the PA->VA translation table */
799 : 0 : dpaax_iova_table_populate();
800 : :
801 : : /* For each registered driver, and device, call the driver->probe */
802 [ # # ]: 0 : TAILQ_FOREACH(dev, &rte_dpaa_bus.device_list, next) {
803 [ # # ]: 0 : TAILQ_FOREACH(drv, &rte_dpaa_bus.driver_list, next) {
804 : 0 : ret = rte_dpaa_device_match(drv, dev);
805 [ # # ]: 0 : if (ret)
806 : 0 : continue;
807 : :
808 [ # # ]: 0 : if (rte_dev_is_probed(&dev->device))
809 : 0 : continue;
810 : :
811 [ # # ]: 0 : if (!drv->probe ||
812 [ # # ]: 0 : (dev->device.devargs &&
813 [ # # ]: 0 : dev->device.devargs->policy == RTE_DEV_BLOCKED))
814 : 0 : continue;
815 : :
816 [ # # # # ]: 0 : if (probe_all ||
817 : 0 : (dev->device.devargs &&
818 [ # # ]: 0 : dev->device.devargs->policy == RTE_DEV_ALLOWED)) {
819 : 0 : ret = drv->probe(drv, dev);
820 [ # # ]: 0 : if (ret) {
821 : 0 : DPAA_BUS_ERR("unable to probe:%s",
822 : : dev->name);
823 : : } else {
824 : 0 : dev->driver = drv;
825 : 0 : dev->device.driver = &drv->driver;
826 : : }
827 : : }
828 : : break;
829 : : }
830 : : }
831 : 0 : dpaa_bus_global_init = 1;
832 : :
833 : 0 : return 0;
834 : : }
835 : :
836 : : static struct rte_device *
837 : 0 : rte_dpaa_find_device(const struct rte_device *start, rte_dev_cmp_t cmp,
838 : : const void *data)
839 : : {
840 : : struct rte_dpaa_device *dev;
841 : : const struct rte_dpaa_device *dstart;
842 : :
843 : : /* find_device is called with 'data' as an opaque object - just call
844 : : * cmp with this and each device object on bus.
845 : : */
846 : :
847 [ # # ]: 0 : if (start != NULL) {
848 : 0 : dstart = RTE_DEV_TO_DPAA_CONST(start);
849 : 0 : dev = TAILQ_NEXT(dstart, next);
850 : : } else {
851 : 0 : dev = TAILQ_FIRST(&rte_dpaa_bus.device_list);
852 : : }
853 : :
854 [ # # ]: 0 : while (dev != NULL) {
855 [ # # ]: 0 : if (cmp(&dev->device, data) == 0) {
856 : 0 : DPAA_BUS_DEBUG("Found dev=(%s)", dev->device.name);
857 : 0 : return &dev->device;
858 : : }
859 : 0 : dev = TAILQ_NEXT(dev, next);
860 : : }
861 : :
862 : 0 : DPAA_BUS_DEBUG("Unable to find any device");
863 : 0 : return NULL;
864 : : }
865 : :
866 : : /*
867 : : * Get iommu class of DPAA2 devices on the bus.
868 : : */
869 : : static enum rte_iova_mode
870 : 187 : rte_dpaa_get_iommu_class(void)
871 : : {
872 [ + - + - ]: 374 : if ((access(DPAA_DEV_PATH1, F_OK) != 0) &&
873 : 187 : (access(DPAA_DEV_PATH2, F_OK) != 0)) {
874 : 187 : return RTE_IOVA_DC;
875 : : }
876 : : return RTE_IOVA_PA;
877 : : }
878 : :
879 : : static int
880 : 0 : dpaa_bus_plug(struct rte_device *dev __rte_unused)
881 : : {
882 : : /* No operation is performed while plugging the device */
883 : 0 : return 0;
884 : : }
885 : :
886 : : static int
887 : 0 : dpaa_bus_unplug(struct rte_device *dev __rte_unused)
888 : : {
889 : : /* No operation is performed while unplugging the device */
890 : 0 : return 0;
891 : : }
892 : :
893 : : static void *
894 : 0 : dpaa_bus_dev_iterate(const void *start, const char *str,
895 : : const struct rte_dev_iterator *it __rte_unused)
896 : : {
897 : : const struct rte_dpaa_device *dstart;
898 : : struct rte_dpaa_device *dev;
899 : : char *dup, *dev_name = NULL;
900 : :
901 [ # # ]: 0 : if (str == NULL) {
902 : 0 : DPAA_BUS_DEBUG("No device string");
903 : 0 : return NULL;
904 : : }
905 : :
906 : : /* Expectation is that device would be name=device_name */
907 [ # # ]: 0 : if (strncmp(str, "name=", 5) != 0) {
908 : 0 : DPAA_BUS_DEBUG("Invalid device string (%s)", str);
909 : 0 : return NULL;
910 : : }
911 : :
912 : : /* Now that name=device_name format is available, split */
913 : 0 : dup = strdup(str);
914 [ # # ]: 0 : if (dup == NULL) {
915 : 0 : DPAA_BUS_DEBUG("Dup string (%s) failed!", str);
916 : 0 : return NULL;
917 : : }
918 : 0 : dev_name = dup + strlen("name=");
919 : :
920 [ # # ]: 0 : if (start != NULL) {
921 : 0 : dstart = RTE_DEV_TO_DPAA_CONST(start);
922 : 0 : dev = TAILQ_NEXT(dstart, next);
923 : : } else {
924 : 0 : dev = TAILQ_FIRST(&rte_dpaa_bus.device_list);
925 : : }
926 : :
927 [ # # ]: 0 : while (dev != NULL) {
928 [ # # ]: 0 : if (strcmp(dev->device.name, dev_name) == 0) {
929 : 0 : free(dup);
930 : 0 : return &dev->device;
931 : : }
932 : 0 : dev = TAILQ_NEXT(dev, next);
933 : : }
934 : :
935 : 0 : free(dup);
936 : 0 : return NULL;
937 : : }
938 : :
939 : : static int
940 : 247 : dpaa_bus_cleanup(void)
941 : : {
942 : : struct rte_dpaa_device *dev, *tmp_dev;
943 : :
944 : 247 : BUS_INIT_FUNC_TRACE();
945 [ - + ]: 247 : RTE_TAILQ_FOREACH_SAFE(dev, &rte_dpaa_bus.device_list, next, tmp_dev) {
946 : 0 : struct rte_dpaa_driver *drv = dev->driver;
947 : : int ret = 0;
948 : :
949 [ # # ]: 0 : if (!rte_dev_is_probed(&dev->device))
950 : 0 : continue;
951 [ # # # # ]: 0 : if (!drv || !drv->remove)
952 : 0 : continue;
953 : 0 : ret = drv->remove(dev);
954 [ # # ]: 0 : if (ret < 0) {
955 : 0 : rte_errno = errno;
956 : 0 : return -1;
957 : : }
958 : 0 : dev->driver = NULL;
959 : 0 : dev->device.driver = NULL;
960 : : }
961 : 247 : dpaa_portal_finish((void *)DPAA_PER_LCORE_PORTAL);
962 : 247 : dpaa_bus_global_init = 0;
963 : 247 : DPAA_BUS_DEBUG("Bus cleanup done");
964 : :
965 : 247 : return 0;
966 : : }
967 : :
968 : : /* Adding destructor for double check in case non-gracefully
969 : : * exit.
970 : : */
971 : 254 : RTE_FINI_PRIO(dpaa_cleanup, 102)
972 : : {
973 : : unsigned int lcore_id;
974 : :
975 [ - + ]: 254 : if (!dpaa_bus_global_init)
976 : : return;
977 : :
978 : : /* cleanup portals in case non-graceful exit */
979 [ # # ]: 0 : RTE_LCORE_FOREACH_WORKER(lcore_id) {
980 : : /* Check for non zero id */
981 : 0 : dpaa_portal_finish((void *)dpaa_portals[lcore_id]);
982 : : }
983 : 0 : dpaa_portal_finish((void *)DPAA_PER_LCORE_PORTAL);
984 : 0 : dpaa_bus_global_init = 0;
985 : 0 : DPAA_BUS_DEBUG("Worker thread clean up done");
986 : : }
987 : :
988 : : static struct rte_dpaa_bus rte_dpaa_bus = {
989 : : .bus = {
990 : : .scan = rte_dpaa_bus_scan,
991 : : .probe = rte_dpaa_bus_probe,
992 : : .parse = rte_dpaa_bus_parse,
993 : : .find_device = rte_dpaa_find_device,
994 : : .get_iommu_class = rte_dpaa_get_iommu_class,
995 : : .plug = dpaa_bus_plug,
996 : : .unplug = dpaa_bus_unplug,
997 : : .dev_iterate = dpaa_bus_dev_iterate,
998 : : .cleanup = dpaa_bus_cleanup,
999 : : },
1000 : : .max_push_rxq_num = DPAA_DEFAULT_PUSH_MODE_QUEUE,
1001 : : .device_list = TAILQ_HEAD_INITIALIZER(rte_dpaa_bus.device_list),
1002 : : .driver_list = TAILQ_HEAD_INITIALIZER(rte_dpaa_bus.driver_list),
1003 : : .device_count = 0,
1004 : : };
1005 : :
1006 : 254 : RTE_REGISTER_BUS(FSL_DPAA_BUS_NAME, rte_dpaa_bus.bus);
1007 [ - + ]: 254 : RTE_LOG_REGISTER_DEFAULT(dpaa_logtype_bus, NOTICE);
|