ethdev: separate driver APIs
[dpdk.git] / drivers / bus / dpaa / dpaa_bus.c
1 /* SPDX-License-Identifier: BSD-3-Clause
2  *
3  *   Copyright 2017 NXP
4  *
5  */
6 /* System headers */
7 #include <stdio.h>
8 #include <inttypes.h>
9 #include <unistd.h>
10 #include <limits.h>
11 #include <sched.h>
12 #include <signal.h>
13 #include <pthread.h>
14 #include <sys/types.h>
15 #include <sys/syscall.h>
16
17 #include <rte_byteorder.h>
18 #include <rte_common.h>
19 #include <rte_interrupts.h>
20 #include <rte_log.h>
21 #include <rte_debug.h>
22 #include <rte_pci.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 <rte_ethdev_driver.h>
31 #include <rte_malloc.h>
32 #include <rte_ring.h>
33 #include <rte_bus.h>
34
35 #include <rte_dpaa_bus.h>
36 #include <rte_dpaa_logs.h>
37
38 #include <fsl_usd.h>
39 #include <fsl_qman.h>
40 #include <fsl_bman.h>
41 #include <of.h>
42 #include <netcfg.h>
43
44 int dpaa_logtype_bus;
45 int dpaa_logtype_mempool;
46 int dpaa_logtype_pmd;
47 int dpaa_logtype_eventdev;
48
49 struct rte_dpaa_bus rte_dpaa_bus;
50 struct netcfg_info *dpaa_netcfg;
51
52 /* define a variable to hold the portal_key, once created.*/
53 pthread_key_t dpaa_portal_key;
54
55 unsigned int dpaa_svr_family;
56
57 RTE_DEFINE_PER_LCORE(bool, _dpaa_io);
58 RTE_DEFINE_PER_LCORE(struct dpaa_portal_dqrr, held_bufs);
59
60 static inline void
61 dpaa_add_to_device_list(struct rte_dpaa_device *dev)
62 {
63         TAILQ_INSERT_TAIL(&rte_dpaa_bus.device_list, dev, next);
64 }
65
66 static inline void
67 dpaa_remove_from_device_list(struct rte_dpaa_device *dev)
68 {
69         TAILQ_INSERT_TAIL(&rte_dpaa_bus.device_list, dev, next);
70 }
71
72 /*
73  * Reads the SEC device from DTS
74  * Returns -1 if SEC devices not available, 0 otherwise
75  */
76 static inline int
77 dpaa_sec_available(void)
78 {
79         const struct device_node *caam_node;
80
81         for_each_compatible_node(caam_node, NULL, "fsl,sec-v4.0") {
82                 return 0;
83         }
84
85         return -1;
86 }
87
88 static void dpaa_clean_device_list(void);
89
90 static int
91 dpaa_create_device_list(void)
92 {
93         int i;
94         int ret;
95         struct rte_dpaa_device *dev;
96         struct fm_eth_port_cfg *cfg;
97         struct fman_if *fman_intf;
98
99         /* Creating Ethernet Devices */
100         for (i = 0; i < dpaa_netcfg->num_ethports; i++) {
101                 dev = calloc(1, sizeof(struct rte_dpaa_device));
102                 if (!dev) {
103                         DPAA_BUS_LOG(ERR, "Failed to allocate ETH devices");
104                         ret = -ENOMEM;
105                         goto cleanup;
106                 }
107
108                 cfg = &dpaa_netcfg->port_cfg[i];
109                 fman_intf = cfg->fman_if;
110
111                 /* Device identifiers */
112                 dev->id.fman_id = fman_intf->fman_idx + 1;
113                 dev->id.mac_id = fman_intf->mac_idx;
114                 dev->device_type = FSL_DPAA_ETH;
115                 dev->id.dev_id = i;
116
117                 /* Create device name */
118                 memset(dev->name, 0, RTE_ETH_NAME_MAX_LEN);
119                 sprintf(dev->name, "fm%d-mac%d", (fman_intf->fman_idx + 1),
120                         fman_intf->mac_idx);
121                 DPAA_BUS_LOG(DEBUG, "Device added: %s", dev->name);
122                 dev->device.name = dev->name;
123
124                 dpaa_add_to_device_list(dev);
125         }
126
127         rte_dpaa_bus.device_count = i;
128
129         /* Unlike case of ETH, RTE_LIBRTE_DPAA_MAX_CRYPTODEV SEC devices are
130          * constantly created only if "sec" property is found in the device
131          * tree. Logically there is no limit for number of devices (QI
132          * interfaces) that can be created.
133          */
134
135         if (dpaa_sec_available()) {
136                 DPAA_BUS_LOG(INFO, "DPAA SEC devices are not available");
137                 return 0;
138         }
139
140         /* Creating SEC Devices */
141         for (i = 0; i < RTE_LIBRTE_DPAA_MAX_CRYPTODEV; i++) {
142                 dev = calloc(1, sizeof(struct rte_dpaa_device));
143                 if (!dev) {
144                         DPAA_BUS_LOG(ERR, "Failed to allocate SEC devices");
145                         ret = -1;
146                         goto cleanup;
147                 }
148
149                 dev->device_type = FSL_DPAA_CRYPTO;
150                 dev->id.dev_id = rte_dpaa_bus.device_count + i;
151
152                 /* Even though RTE_CRYPTODEV_NAME_MAX_LEN is valid length of
153                  * crypto PMD, using RTE_ETH_NAME_MAX_LEN as that is the size
154                  * allocated for dev->name/
155                  */
156                 memset(dev->name, 0, RTE_ETH_NAME_MAX_LEN);
157                 sprintf(dev->name, "dpaa-sec%d", i);
158                 DPAA_BUS_LOG(DEBUG, "Device added: %s", dev->name);
159
160                 dpaa_add_to_device_list(dev);
161         }
162
163         rte_dpaa_bus.device_count += i;
164
165         return 0;
166
167 cleanup:
168         dpaa_clean_device_list();
169         return ret;
170 }
171
172 static void
173 dpaa_clean_device_list(void)
174 {
175         struct rte_dpaa_device *dev = NULL;
176         struct rte_dpaa_device *tdev = NULL;
177
178         TAILQ_FOREACH_SAFE(dev, &rte_dpaa_bus.device_list, next, tdev) {
179                 TAILQ_REMOVE(&rte_dpaa_bus.device_list, dev, next);
180                 free(dev);
181                 dev = NULL;
182         }
183 }
184
185 /** XXX move this function into a separate file */
186 static int
187 _dpaa_portal_init(void *arg)
188 {
189         cpu_set_t cpuset;
190         pthread_t id;
191         uint32_t cpu = rte_lcore_id();
192         int ret;
193         struct dpaa_portal *dpaa_io_portal;
194
195         BUS_INIT_FUNC_TRACE();
196
197         if ((uint64_t)arg == 1 || cpu == LCORE_ID_ANY)
198                 cpu = rte_get_master_lcore();
199         /* if the core id is not supported */
200         else
201                 if (cpu >= RTE_MAX_LCORE)
202                         return -1;
203
204         /* Set CPU affinity for this thread */
205         CPU_ZERO(&cpuset);
206         CPU_SET(cpu, &cpuset);
207         id = pthread_self();
208         ret = pthread_setaffinity_np(id, sizeof(cpu_set_t), &cpuset);
209         if (ret) {
210                 DPAA_BUS_LOG(ERR, "pthread_setaffinity_np failed on "
211                         "core :%d with ret: %d", cpu, ret);
212                 return ret;
213         }
214
215         /* Initialise bman thread portals */
216         ret = bman_thread_init();
217         if (ret) {
218                 DPAA_BUS_LOG(ERR, "bman_thread_init failed on "
219                         "core %d with ret: %d", cpu, ret);
220                 return ret;
221         }
222
223         DPAA_BUS_LOG(DEBUG, "BMAN thread initialized");
224
225         /* Initialise qman thread portals */
226         ret = qman_thread_init();
227         if (ret) {
228                 DPAA_BUS_LOG(ERR, "bman_thread_init failed on "
229                         "core %d with ret: %d", cpu, ret);
230                 bman_thread_finish();
231                 return ret;
232         }
233
234         DPAA_BUS_LOG(DEBUG, "QMAN thread initialized");
235
236         dpaa_io_portal = rte_malloc(NULL, sizeof(struct dpaa_portal),
237                                     RTE_CACHE_LINE_SIZE);
238         if (!dpaa_io_portal) {
239                 DPAA_BUS_LOG(ERR, "Unable to allocate memory");
240                 bman_thread_finish();
241                 qman_thread_finish();
242                 return -ENOMEM;
243         }
244
245         dpaa_io_portal->qman_idx = qman_get_portal_index();
246         dpaa_io_portal->bman_idx = bman_get_portal_index();
247         dpaa_io_portal->tid = syscall(SYS_gettid);
248
249         ret = pthread_setspecific(dpaa_portal_key, (void *)dpaa_io_portal);
250         if (ret) {
251                 DPAA_BUS_LOG(ERR, "pthread_setspecific failed on "
252                             "core %d with ret: %d", cpu, ret);
253                 dpaa_portal_finish(NULL);
254
255                 return ret;
256         }
257
258         RTE_PER_LCORE(_dpaa_io) = true;
259
260         DPAA_BUS_LOG(DEBUG, "QMAN thread initialized");
261
262         return 0;
263 }
264
265 /*
266  * rte_dpaa_portal_init - Wrapper over _dpaa_portal_init with thread level check
267  * XXX Complete this
268  */
269 int rte_dpaa_portal_init(void *arg)
270 {
271         if (unlikely(!RTE_PER_LCORE(_dpaa_io)))
272                 return _dpaa_portal_init(arg);
273
274         return 0;
275 }
276
277 int
278 rte_dpaa_portal_fq_init(void *arg, struct qman_fq *fq)
279 {
280         /* Affine above created portal with channel*/
281         u32 sdqcr;
282         struct qman_portal *qp;
283
284         if (unlikely(!RTE_PER_LCORE(_dpaa_io)))
285                 _dpaa_portal_init(arg);
286
287         /* Initialise qman specific portals */
288         qp = fsl_qman_portal_create();
289         if (!qp) {
290                 DPAA_BUS_LOG(ERR, "Unable to alloc fq portal");
291                 return -1;
292         }
293         fq->qp = qp;
294         sdqcr = QM_SDQCR_CHANNELS_POOL_CONV(fq->ch_id);
295         qman_static_dequeue_add(sdqcr, qp);
296
297         return 0;
298 }
299
300 int rte_dpaa_portal_fq_close(struct qman_fq *fq)
301 {
302         return fsl_qman_portal_destroy(fq->qp);
303 }
304
305 void
306 dpaa_portal_finish(void *arg)
307 {
308         struct dpaa_portal *dpaa_io_portal = (struct dpaa_portal *)arg;
309
310         if (!dpaa_io_portal) {
311                 DPAA_BUS_LOG(DEBUG, "Portal already cleaned");
312                 return;
313         }
314
315         bman_thread_finish();
316         qman_thread_finish();
317
318         pthread_setspecific(dpaa_portal_key, NULL);
319
320         rte_free(dpaa_io_portal);
321         dpaa_io_portal = NULL;
322
323         RTE_PER_LCORE(_dpaa_io) = false;
324 }
325
326 #define DPAA_DEV_PATH1 "/sys/devices/platform/soc/soc:fsl,dpaa"
327 #define DPAA_DEV_PATH2 "/sys/devices/platform/fsl,dpaa"
328
329 static int
330 rte_dpaa_bus_scan(void)
331 {
332         int ret;
333
334         BUS_INIT_FUNC_TRACE();
335
336         if ((access(DPAA_DEV_PATH1, F_OK) != 0) &&
337             (access(DPAA_DEV_PATH2, F_OK) != 0)) {
338                 RTE_LOG(DEBUG, EAL, "DPAA Bus not present. Skipping.\n");
339                 return 0;
340         }
341
342         /* Load the device-tree driver */
343         ret = of_init();
344         if (ret) {
345                 DPAA_BUS_LOG(ERR, "of_init failed with ret: %d", ret);
346                 return -1;
347         }
348
349         /* Get the interface configurations from device-tree */
350         dpaa_netcfg = netcfg_acquire();
351         if (!dpaa_netcfg) {
352                 DPAA_BUS_LOG(ERR, "netcfg_acquire failed");
353                 return -EINVAL;
354         }
355
356         RTE_LOG(NOTICE, EAL, "DPAA Bus Detected\n");
357
358         if (!dpaa_netcfg->num_ethports) {
359                 DPAA_BUS_LOG(INFO, "no network interfaces available");
360                 /* This is not an error */
361                 return 0;
362         }
363
364         DPAA_BUS_LOG(DEBUG, "Bus: Address of netcfg=%p, Ethports=%d",
365                      dpaa_netcfg, dpaa_netcfg->num_ethports);
366
367 #ifdef RTE_LIBRTE_DPAA_DEBUG_DRIVER
368         dump_netcfg(dpaa_netcfg);
369 #endif
370
371         DPAA_BUS_LOG(DEBUG, "Number of devices = %d\n",
372                      dpaa_netcfg->num_ethports);
373         ret = dpaa_create_device_list();
374         if (ret) {
375                 DPAA_BUS_LOG(ERR, "Unable to create device list. (%d)", ret);
376                 return ret;
377         }
378
379         /* create the key, supplying a function that'll be invoked
380          * when a portal affined thread will be deleted.
381          */
382         ret = pthread_key_create(&dpaa_portal_key, dpaa_portal_finish);
383         if (ret) {
384                 DPAA_BUS_LOG(DEBUG, "Unable to create pthread key. (%d)", ret);
385                 dpaa_clean_device_list();
386                 return ret;
387         }
388
389         DPAA_BUS_LOG(DEBUG, "dpaa_portal_key=%u, ret=%d\n",
390                     (unsigned int)dpaa_portal_key, ret);
391
392         return 0;
393 }
394
395 /* register a dpaa bus based dpaa driver */
396 void
397 rte_dpaa_driver_register(struct rte_dpaa_driver *driver)
398 {
399         RTE_VERIFY(driver);
400
401         BUS_INIT_FUNC_TRACE();
402
403         TAILQ_INSERT_TAIL(&rte_dpaa_bus.driver_list, driver, next);
404         /* Update Bus references */
405         driver->dpaa_bus = &rte_dpaa_bus;
406 }
407
408 /* un-register a dpaa bus based dpaa driver */
409 void
410 rte_dpaa_driver_unregister(struct rte_dpaa_driver *driver)
411 {
412         struct rte_dpaa_bus *dpaa_bus;
413
414         BUS_INIT_FUNC_TRACE();
415
416         dpaa_bus = driver->dpaa_bus;
417
418         TAILQ_REMOVE(&dpaa_bus->driver_list, driver, next);
419         /* Update Bus references */
420         driver->dpaa_bus = NULL;
421 }
422
423 static int
424 rte_dpaa_device_match(struct rte_dpaa_driver *drv,
425                       struct rte_dpaa_device *dev)
426 {
427         int ret = -1;
428
429         BUS_INIT_FUNC_TRACE();
430
431         if (!drv || !dev) {
432                 DPAA_BUS_DEBUG("Invalid drv or dev received.");
433                 return ret;
434         }
435
436         if (drv->drv_type == dev->device_type) {
437                 DPAA_BUS_INFO("Device: %s matches for driver: %s",
438                               dev->name, drv->driver.name);
439                 ret = 0; /* Found a match */
440         }
441
442         return ret;
443 }
444
445 static int
446 rte_dpaa_bus_probe(void)
447 {
448         int ret = -1;
449         struct rte_dpaa_device *dev;
450         struct rte_dpaa_driver *drv;
451         FILE *svr_file = NULL;
452         unsigned int svr_ver;
453
454         BUS_INIT_FUNC_TRACE();
455
456         /* For each registered driver, and device, call the driver->probe */
457         TAILQ_FOREACH(dev, &rte_dpaa_bus.device_list, next) {
458                 TAILQ_FOREACH(drv, &rte_dpaa_bus.driver_list, next) {
459                         ret = rte_dpaa_device_match(drv, dev);
460                         if (ret)
461                                 continue;
462
463                         if (!drv->probe)
464                                 continue;
465
466                         ret = drv->probe(drv, dev);
467                         if (ret)
468                                 DPAA_BUS_ERR("Unable to probe.\n");
469                         break;
470                 }
471         }
472
473         svr_file = fopen(DPAA_SOC_ID_FILE, "r");
474         if (svr_file) {
475                 if (fscanf(svr_file, "svr:%x", &svr_ver) > 0)
476                         dpaa_svr_family = svr_ver & SVR_MASK;
477                 fclose(svr_file);
478         }
479
480         return 0;
481 }
482
483 static struct rte_device *
484 rte_dpaa_find_device(const struct rte_device *start, rte_dev_cmp_t cmp,
485                      const void *data)
486 {
487         struct rte_dpaa_device *dev;
488
489         TAILQ_FOREACH(dev, &rte_dpaa_bus.device_list, next) {
490                 if (start && &dev->device == start) {
491                         start = NULL;  /* starting point found */
492                         continue;
493                 }
494
495                 if (cmp(&dev->device, data) == 0)
496                         return &dev->device;
497         }
498
499         return NULL;
500 }
501
502 /*
503  * Get iommu class of DPAA2 devices on the bus.
504  */
505 static enum rte_iova_mode
506 rte_dpaa_get_iommu_class(void)
507 {
508         return RTE_IOVA_PA;
509 }
510
511 struct rte_dpaa_bus rte_dpaa_bus = {
512         .bus = {
513                 .scan = rte_dpaa_bus_scan,
514                 .probe = rte_dpaa_bus_probe,
515                 .find_device = rte_dpaa_find_device,
516                 .get_iommu_class = rte_dpaa_get_iommu_class,
517         },
518         .device_list = TAILQ_HEAD_INITIALIZER(rte_dpaa_bus.device_list),
519         .driver_list = TAILQ_HEAD_INITIALIZER(rte_dpaa_bus.driver_list),
520         .device_count = 0,
521 };
522
523 RTE_REGISTER_BUS(FSL_DPAA_BUS_NAME, rte_dpaa_bus.bus);
524
525 RTE_INIT(dpaa_init_log);
526 static void
527 dpaa_init_log(void)
528 {
529         dpaa_logtype_bus = rte_log_register("bus.dpaa");
530         if (dpaa_logtype_bus >= 0)
531                 rte_log_set_level(dpaa_logtype_bus, RTE_LOG_NOTICE);
532
533         dpaa_logtype_mempool = rte_log_register("mempool.dpaa");
534         if (dpaa_logtype_mempool >= 0)
535                 rte_log_set_level(dpaa_logtype_mempool, RTE_LOG_NOTICE);
536
537         dpaa_logtype_pmd = rte_log_register("pmd.dpaa");
538         if (dpaa_logtype_pmd >= 0)
539                 rte_log_set_level(dpaa_logtype_pmd, RTE_LOG_NOTICE);
540
541         dpaa_logtype_eventdev = rte_log_register("eventdev.dpaa");
542         if (dpaa_logtype_eventdev >= 0)
543                 rte_log_set_level(dpaa_logtype_eventdev, RTE_LOG_NOTICE);
544 }