New upstream version 18.02
[deb_dpdk.git] / drivers / bus / fslmc / fslmc_bus.c
1 /* SPDX-License-Identifier: BSD-3-Clause
2  *
3  *   Copyright 2016 NXP
4  *
5  */
6
7 #include <string.h>
8 #include <dirent.h>
9 #include <stdbool.h>
10
11 #include <rte_log.h>
12 #include <rte_bus.h>
13 #include <rte_eal_memconfig.h>
14 #include <rte_malloc.h>
15 #include <rte_devargs.h>
16 #include <rte_memcpy.h>
17 #include <rte_ethdev_driver.h>
18
19 #include <rte_fslmc.h>
20 #include <fslmc_vfio.h>
21
22 #define FSLMC_BUS_LOG(level, fmt, args...) \
23         RTE_LOG(level, EAL, fmt "\n", ##args)
24
25 #define VFIO_IOMMU_GROUP_PATH "/sys/kernel/iommu_groups"
26
27 struct rte_fslmc_bus rte_fslmc_bus;
28 uint8_t dpaa2_virt_mode;
29
30 uint32_t
31 rte_fslmc_get_device_count(enum rte_dpaa2_dev_type device_type)
32 {
33         if (device_type > DPAA2_DEVTYPE_MAX)
34                 return 0;
35         return rte_fslmc_bus.device_count[device_type];
36 }
37
38 RTE_DEFINE_PER_LCORE(struct dpaa2_portal_dqrr, dpaa2_held_bufs);
39
40 static void
41 cleanup_fslmc_device_list(void)
42 {
43         struct rte_dpaa2_device *dev;
44         struct rte_dpaa2_device *t_dev;
45
46         TAILQ_FOREACH_SAFE(dev, &rte_fslmc_bus.device_list, next, t_dev) {
47                 TAILQ_REMOVE(&rte_fslmc_bus.device_list, dev, next);
48                 free(dev);
49                 dev = NULL;
50         }
51 }
52
53 static int
54 compare_dpaa2_devname(struct rte_dpaa2_device *dev1,
55                       struct rte_dpaa2_device *dev2)
56 {
57         int comp;
58
59         if (dev1->dev_type > dev2->dev_type) {
60                 comp = 1;
61         } else if (dev1->dev_type < dev2->dev_type) {
62                 comp = -1;
63         } else {
64                 /* Check the ID as types match */
65                 if (dev1->object_id > dev2->object_id)
66                         comp = 1;
67                 else if (dev1->object_id < dev2->object_id)
68                         comp = -1;
69                 else
70                         comp = 0; /* Duplicate device name */
71         }
72
73         return comp;
74 }
75
76 static void
77 insert_in_device_list(struct rte_dpaa2_device *newdev)
78 {
79         int comp, inserted = 0;
80         struct rte_dpaa2_device *dev = NULL;
81         struct rte_dpaa2_device *tdev = NULL;
82
83         TAILQ_FOREACH_SAFE(dev, &rte_fslmc_bus.device_list, next, tdev) {
84                 comp = compare_dpaa2_devname(newdev, dev);
85                 if (comp < 0) {
86                         TAILQ_INSERT_BEFORE(dev, newdev, next);
87                         inserted = 1;
88                         break;
89                 }
90         }
91
92         if (!inserted)
93                 TAILQ_INSERT_TAIL(&rte_fslmc_bus.device_list, newdev, next);
94 }
95
96 static int
97 scan_one_fslmc_device(char *dev_name)
98 {
99         char *dup_dev_name, *t_ptr;
100         struct rte_dpaa2_device *dev;
101
102         if (!dev_name)
103                 return -1;
104
105         /* Ignore the Container name itself */
106         if (!strncmp("dprc", dev_name, 4))
107                 return 0;
108
109         /* Creating a temporary copy to perform cut-parse over string */
110         dup_dev_name = strdup(dev_name);
111         if (!dup_dev_name) {
112                 FSLMC_BUS_LOG(ERR, "Out of memory.");
113                 return -ENOMEM;
114         }
115
116         /* For all other devices, we allocate rte_dpaa2_device.
117          * For those devices where there is no driver, probe would release
118          * the memory associated with the rte_dpaa2_device after necessary
119          * initialization.
120          */
121         dev = calloc(1, sizeof(struct rte_dpaa2_device));
122         if (!dev) {
123                 FSLMC_BUS_LOG(ERR, "Out of memory.");
124                 free(dup_dev_name);
125                 return -ENOMEM;
126         }
127
128         /* Parse the device name and ID */
129         t_ptr = strtok(dup_dev_name, ".");
130         if (!t_ptr) {
131                 FSLMC_BUS_LOG(ERR, "Incorrect device string observed.");
132                 goto cleanup;
133         }
134         if (!strncmp("dpni", t_ptr, 4))
135                 dev->dev_type = DPAA2_ETH;
136         else if (!strncmp("dpseci", t_ptr, 6))
137                 dev->dev_type = DPAA2_CRYPTO;
138         else if (!strncmp("dpcon", t_ptr, 5))
139                 dev->dev_type = DPAA2_CON;
140         else if (!strncmp("dpbp", t_ptr, 4))
141                 dev->dev_type = DPAA2_BPOOL;
142         else if (!strncmp("dpio", t_ptr, 4))
143                 dev->dev_type = DPAA2_IO;
144         else if (!strncmp("dpci", t_ptr, 4))
145                 dev->dev_type = DPAA2_CI;
146         else if (!strncmp("dpmcp", t_ptr, 5))
147                 dev->dev_type = DPAA2_MPORTAL;
148         else
149                 dev->dev_type = DPAA2_UNKNOWN;
150
151         /* Update the device found into the device_count table */
152         rte_fslmc_bus.device_count[dev->dev_type]++;
153
154         t_ptr = strtok(NULL, ".");
155         if (!t_ptr) {
156                 FSLMC_BUS_LOG(ERR, "Incorrect device string observed (%s).",
157                               t_ptr);
158                 goto cleanup;
159         }
160
161         sscanf(t_ptr, "%hu", &dev->object_id);
162         dev->device.name = strdup(dev_name);
163         if (!dev->device.name) {
164                 FSLMC_BUS_LOG(ERR, "Out of memory.");
165                 goto cleanup;
166         }
167
168         /* Add device in the fslmc device list */
169         insert_in_device_list(dev);
170
171         /* Don't need the duplicated device filesystem entry anymore */
172         if (dup_dev_name)
173                 free(dup_dev_name);
174
175         return 0;
176 cleanup:
177         if (dup_dev_name)
178                 free(dup_dev_name);
179         if (dev)
180                 free(dev);
181         return -1;
182 }
183
184 static int
185 rte_fslmc_scan(void)
186 {
187         int ret;
188         int device_count = 0;
189         char fslmc_dirpath[PATH_MAX];
190         DIR *dir;
191         struct dirent *entry;
192         static int process_once;
193         int groupid;
194
195         if (process_once) {
196                 FSLMC_BUS_LOG(DEBUG,
197                               "Fslmc bus already scanned. Not rescanning");
198                 return 0;
199         }
200         process_once = 1;
201
202         ret = fslmc_get_container_group(&groupid);
203         if (ret != 0)
204                 goto scan_fail;
205
206         /* Scan devices on the group */
207         sprintf(fslmc_dirpath, "%s/%d/devices", VFIO_IOMMU_GROUP_PATH,
208                 groupid);
209         dir = opendir(fslmc_dirpath);
210         if (!dir) {
211                 FSLMC_BUS_LOG(ERR, "Unable to open VFIO group dir.");
212                 goto scan_fail;
213         }
214
215         while ((entry = readdir(dir)) != NULL) {
216                 if (entry->d_name[0] == '.' || entry->d_type != DT_LNK)
217                         continue;
218
219                 ret = scan_one_fslmc_device(entry->d_name);
220                 if (ret != 0) {
221                         /* Error in parsing directory - exit gracefully */
222                         goto scan_fail_cleanup;
223                 }
224                 device_count += 1;
225         }
226
227         FSLMC_BUS_LOG(INFO, "fslmc: Bus scan completed");
228
229         closedir(dir);
230         return 0;
231
232 scan_fail_cleanup:
233         closedir(dir);
234
235         /* Remove all devices in the list */
236         cleanup_fslmc_device_list();
237 scan_fail:
238         FSLMC_BUS_LOG(DEBUG, "FSLMC Bus Not Available. Skipping.");
239         /* Irrespective of failure, scan only return success */
240         return 0;
241 }
242
243 static int
244 rte_fslmc_match(struct rte_dpaa2_driver *dpaa2_drv,
245                 struct rte_dpaa2_device *dpaa2_dev)
246 {
247         if (dpaa2_drv->drv_type == dpaa2_dev->dev_type)
248                 return 0;
249
250         return 1;
251 }
252
253 static int
254 rte_fslmc_probe(void)
255 {
256         int ret = 0;
257         struct rte_dpaa2_device *dev;
258         struct rte_dpaa2_driver *drv;
259
260         if (TAILQ_EMPTY(&rte_fslmc_bus.device_list))
261                 return 0;
262
263         ret = fslmc_vfio_setup_group();
264         if (ret) {
265                 FSLMC_BUS_LOG(ERR, "Unable to setup VFIO %d", ret);
266                 return 0;
267         }
268
269         ret = fslmc_vfio_process_group();
270         if (ret) {
271                 FSLMC_BUS_LOG(ERR, "Unable to setup devices %d", ret);
272                 return 0;
273         }
274
275         TAILQ_FOREACH(dev, &rte_fslmc_bus.device_list, next) {
276                 TAILQ_FOREACH(drv, &rte_fslmc_bus.driver_list, next) {
277                         ret = rte_fslmc_match(drv, dev);
278                         if (ret)
279                                 continue;
280
281                         if (!drv->probe)
282                                 continue;
283
284                         ret = drv->probe(drv, dev);
285                         if (ret)
286                                 FSLMC_BUS_LOG(ERR, "Unable to probe.\n");
287                         break;
288                 }
289         }
290
291         if (rte_eal_iova_mode() == RTE_IOVA_VA)
292                 dpaa2_virt_mode = 1;
293
294         return 0;
295 }
296
297 static struct rte_device *
298 rte_fslmc_find_device(const struct rte_device *start, rte_dev_cmp_t cmp,
299                       const void *data)
300 {
301         struct rte_dpaa2_device *dev;
302
303         TAILQ_FOREACH(dev, &rte_fslmc_bus.device_list, next) {
304                 if (start && &dev->device == start) {
305                         start = NULL;  /* starting point found */
306                         continue;
307                 }
308
309                 if (cmp(&dev->device, data) == 0)
310                         return &dev->device;
311         }
312
313         return NULL;
314 }
315
316 /*register a fslmc bus based dpaa2 driver */
317 void
318 rte_fslmc_driver_register(struct rte_dpaa2_driver *driver)
319 {
320         RTE_VERIFY(driver);
321
322         TAILQ_INSERT_TAIL(&rte_fslmc_bus.driver_list, driver, next);
323         /* Update Bus references */
324         driver->fslmc_bus = &rte_fslmc_bus;
325 }
326
327 /*un-register a fslmc bus based dpaa2 driver */
328 void
329 rte_fslmc_driver_unregister(struct rte_dpaa2_driver *driver)
330 {
331         struct rte_fslmc_bus *fslmc_bus;
332
333         fslmc_bus = driver->fslmc_bus;
334
335         TAILQ_REMOVE(&fslmc_bus->driver_list, driver, next);
336         /* Update Bus references */
337         driver->fslmc_bus = NULL;
338 }
339
340 /*
341  * All device has iova as va
342  */
343 static inline int
344 fslmc_all_device_support_iova(void)
345 {
346         int ret = 0;
347         struct rte_dpaa2_device *dev;
348         struct rte_dpaa2_driver *drv;
349
350         TAILQ_FOREACH(dev, &rte_fslmc_bus.device_list, next) {
351                 TAILQ_FOREACH(drv, &rte_fslmc_bus.driver_list, next) {
352                         ret = rte_fslmc_match(drv, dev);
353                         if (ret)
354                                 continue;
355                         /* if the driver is not supporting IOVA */
356                         if (!(drv->drv_flags & RTE_DPAA2_DRV_IOVA_AS_VA))
357                                 return 0;
358                 }
359         }
360         return 1;
361 }
362
363 /*
364  * Get iommu class of DPAA2 devices on the bus.
365  */
366 static enum rte_iova_mode
367 rte_dpaa2_get_iommu_class(void)
368 {
369         bool is_vfio_noiommu_enabled = 1;
370         bool has_iova_va;
371
372         if (TAILQ_EMPTY(&rte_fslmc_bus.device_list))
373                 return RTE_IOVA_DC;
374
375         /* check if all devices on the bus support Virtual addressing or not */
376         has_iova_va = fslmc_all_device_support_iova();
377
378 #ifdef VFIO_PRESENT
379         is_vfio_noiommu_enabled = rte_vfio_noiommu_is_enabled() == true ?
380                                                 true : false;
381 #endif
382
383         if (has_iova_va && !is_vfio_noiommu_enabled)
384                 return RTE_IOVA_VA;
385
386         return RTE_IOVA_PA;
387 }
388
389 struct rte_fslmc_bus rte_fslmc_bus = {
390         .bus = {
391                 .scan = rte_fslmc_scan,
392                 .probe = rte_fslmc_probe,
393                 .find_device = rte_fslmc_find_device,
394                 .get_iommu_class = rte_dpaa2_get_iommu_class,
395         },
396         .device_list = TAILQ_HEAD_INITIALIZER(rte_fslmc_bus.device_list),
397         .driver_list = TAILQ_HEAD_INITIALIZER(rte_fslmc_bus.driver_list),
398         .device_count = {0},
399 };
400
401 RTE_REGISTER_BUS(fslmc, rte_fslmc_bus.bus);