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