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