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