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