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