net/ark: set generator delay thread name
[dpdk.git] / drivers / crypto / bcmfs / bcmfs_device.c
1 /* SPDX-License-Identifier: BSD-3-Clause
2  * Copyright(C) 2020 Broadcom.
3  * All rights reserved.
4  */
5
6 #include <dirent.h>
7 #include <stdbool.h>
8 #include <sys/queue.h>
9
10 #include <rte_malloc.h>
11 #include <rte_string_fns.h>
12
13 #include "bcmfs_device.h"
14 #include "bcmfs_logs.h"
15 #include "bcmfs_qp.h"
16 #include "bcmfs_vfio.h"
17 #include "bcmfs_sym_pmd.h"
18
19 struct bcmfs_device_attr {
20         const char name[BCMFS_MAX_PATH_LEN];
21         const char suffix[BCMFS_DEV_NAME_LEN];
22         const enum bcmfs_device_type type;
23         const uint32_t offset;
24         const uint32_t version;
25 };
26
27 /* BCMFS supported devices */
28 static struct bcmfs_device_attr dev_table[] = {
29         {
30                 .name = "fs4",
31                 .suffix = "crypto_mbox",
32                 .type = BCMFS_SYM_FS4,
33                 .offset = 0,
34                 .version = BCMFS_SYM_FS4_VERSION
35         },
36         {
37                 .name = "fs5",
38                 .suffix = "mbox",
39                 .type = BCMFS_SYM_FS5,
40                 .offset = 0,
41                 .version = BCMFS_SYM_FS5_VERSION
42         },
43         {
44                 /* sentinel */
45         }
46 };
47
48 struct bcmfs_hw_queue_pair_ops_table bcmfs_hw_queue_pair_ops_table = {
49         .tl =  RTE_SPINLOCK_INITIALIZER,
50         .num_ops = 0
51 };
52
53 int bcmfs_hw_queue_pair_register_ops(const struct bcmfs_hw_queue_pair_ops *h)
54 {
55         struct bcmfs_hw_queue_pair_ops *ops;
56         int16_t ops_index;
57
58         rte_spinlock_lock(&bcmfs_hw_queue_pair_ops_table.tl);
59
60         if (h->enq_one_req == NULL || h->dequeue == NULL ||
61             h->ring_db == NULL || h->startq == NULL || h->stopq == NULL) {
62                 rte_spinlock_unlock(&bcmfs_hw_queue_pair_ops_table.tl);
63                 BCMFS_LOG(ERR,
64                           "Missing callback while registering device ops");
65                 return -EINVAL;
66         }
67
68         if (strlen(h->name) >= sizeof(ops->name) - 1) {
69                 rte_spinlock_unlock(&bcmfs_hw_queue_pair_ops_table.tl);
70                 BCMFS_LOG(ERR, "%s(): fs device_ops <%s>: name too long",
71                                 __func__, h->name);
72                 return -EEXIST;
73         }
74
75         ops_index = bcmfs_hw_queue_pair_ops_table.num_ops++;
76         ops = &bcmfs_hw_queue_pair_ops_table.qp_ops[ops_index];
77         strlcpy(ops->name, h->name, sizeof(ops->name));
78         ops->enq_one_req = h->enq_one_req;
79         ops->dequeue = h->dequeue;
80         ops->ring_db = h->ring_db;
81         ops->startq = h->startq;
82         ops->stopq = h->stopq;
83
84         rte_spinlock_unlock(&bcmfs_hw_queue_pair_ops_table.tl);
85
86         return ops_index;
87 }
88
89 TAILQ_HEAD(fsdev_list, bcmfs_device);
90 static struct fsdev_list fsdev_list = TAILQ_HEAD_INITIALIZER(fsdev_list);
91
92 static struct bcmfs_device *
93 fsdev_allocate_one_dev(struct rte_vdev_device *vdev,
94                        char *dirpath,
95                        char *devname,
96                        enum bcmfs_device_type dev_type __rte_unused)
97 {
98         struct bcmfs_device *fsdev;
99         uint32_t i;
100
101         fsdev = rte_calloc(__func__, 1, sizeof(*fsdev), 0);
102         if (!fsdev)
103                 return NULL;
104
105         if (strlen(dirpath) > sizeof(fsdev->dirname)) {
106                 BCMFS_LOG(ERR, "dir path name is too long");
107                 goto cleanup;
108         }
109
110         if (strlen(devname) > sizeof(fsdev->name)) {
111                 BCMFS_LOG(ERR, "devname is too long");
112                 goto cleanup;
113         }
114
115         /* check if registered ops name is present in directory path */
116         for (i = 0; i < bcmfs_hw_queue_pair_ops_table.num_ops; i++)
117                 if (strstr(dirpath,
118                            bcmfs_hw_queue_pair_ops_table.qp_ops[i].name))
119                         fsdev->sym_hw_qp_ops =
120                                 &bcmfs_hw_queue_pair_ops_table.qp_ops[i];
121         if (!fsdev->sym_hw_qp_ops)
122                 goto cleanup;
123
124         strcpy(fsdev->dirname, dirpath);
125         strcpy(fsdev->name, devname);
126
127         fsdev->vdev = vdev;
128
129         /* attach to VFIO */
130         if (bcmfs_attach_vfio(fsdev))
131                 goto cleanup;
132
133         /* Maximum number of QPs supported */
134         fsdev->max_hw_qps = fsdev->mmap_size / BCMFS_HW_QUEUE_IO_ADDR_LEN;
135
136         TAILQ_INSERT_TAIL(&fsdev_list, fsdev, next);
137
138         return fsdev;
139
140 cleanup:
141         free(fsdev);
142
143         return NULL;
144 }
145
146 static struct bcmfs_device *
147 find_fsdev(struct rte_vdev_device *vdev)
148 {
149         struct bcmfs_device *fsdev;
150
151         TAILQ_FOREACH(fsdev, &fsdev_list, next)
152                 if (fsdev->vdev == vdev)
153                         return fsdev;
154
155         return NULL;
156 }
157
158 static void
159 fsdev_release(struct bcmfs_device *fsdev)
160 {
161         if (fsdev == NULL)
162                 return;
163
164         TAILQ_REMOVE(&fsdev_list, fsdev, next);
165         free(fsdev);
166 }
167
168 static int
169 cmprator(const void *a, const void *b)
170 {
171         return (*(const unsigned int *)a - *(const unsigned int *)b);
172 }
173
174 static int
175 fsdev_find_all_devs(const char *path, const char *search,
176                     uint32_t *devs)
177 {
178         DIR *dir;
179         struct dirent *entry;
180         int count = 0;
181         char addr[BCMFS_MAX_NODES][BCMFS_MAX_PATH_LEN];
182         int i;
183
184         dir = opendir(path);
185         if (dir == NULL) {
186                 BCMFS_LOG(ERR, "Unable to open directory");
187                 return 0;
188         }
189
190         while ((entry = readdir(dir)) != NULL) {
191                 if (strstr(entry->d_name, search)) {
192                         strlcpy(addr[count], entry->d_name,
193                                 BCMFS_MAX_PATH_LEN);
194                         count++;
195                 }
196         }
197
198         closedir(dir);
199
200         for (i = 0 ; i < count; i++)
201                 devs[i] = (uint32_t)strtoul(addr[i], NULL, 16);
202         /* sort the devices based on IO addresses */
203         qsort(devs, count, sizeof(uint32_t), cmprator);
204
205         return count;
206 }
207
208 static bool
209 fsdev_find_sub_dir(char *path, const char *search, char *output)
210 {
211         DIR *dir;
212         struct dirent *entry;
213
214         dir = opendir(path);
215         if (dir == NULL) {
216                 BCMFS_LOG(ERR, "Unable to open directory");
217                 return -ENODEV;
218         }
219
220         while ((entry = readdir(dir)) != NULL) {
221                 if (!strcmp(entry->d_name, search)) {
222                         strlcpy(output, entry->d_name, BCMFS_MAX_PATH_LEN);
223                         closedir(dir);
224                         return true;
225                 }
226         }
227
228         closedir(dir);
229
230         return false;
231 }
232
233
234 static int
235 bcmfs_vdev_probe(struct rte_vdev_device *vdev)
236 {
237         struct bcmfs_device *fsdev;
238         char top_dirpath[BCMFS_MAX_PATH_LEN];
239         char sub_dirpath[BCMFS_MAX_PATH_LEN];
240         char out_dirpath[BCMFS_MAX_PATH_LEN];
241         char out_dirname[BCMFS_MAX_PATH_LEN];
242         uint32_t fsdev_dev[BCMFS_MAX_NODES];
243         enum bcmfs_device_type dtype;
244         int err;
245         int i = 0;
246         int dev_idx;
247         int count = 0;
248         bool found = false;
249
250         sprintf(top_dirpath, "%s", SYSFS_BCM_PLTFORM_DEVICES);
251         while (strlen(dev_table[i].name)) {
252                 found = fsdev_find_sub_dir(top_dirpath,
253                                            dev_table[i].name,
254                                            sub_dirpath);
255                 if (found)
256                         break;
257                 i++;
258         }
259         if (!found) {
260                 BCMFS_LOG(ERR, "No supported bcmfs dev found");
261                 return -ENODEV;
262         }
263
264         dev_idx = i;
265         dtype = dev_table[i].type;
266
267         snprintf(out_dirpath, sizeof(out_dirpath), "%s/%s",
268                  top_dirpath, sub_dirpath);
269         count = fsdev_find_all_devs(out_dirpath,
270                                     dev_table[dev_idx].suffix,
271                                     fsdev_dev);
272         if (!count) {
273                 BCMFS_LOG(ERR, "No supported bcmfs dev found");
274                 return -ENODEV;
275         }
276
277         i = 0;
278         while (count) {
279                 /* format the device name present in the patch */
280                 snprintf(out_dirname, sizeof(out_dirname), "%x.%s",
281                          fsdev_dev[i], dev_table[dev_idx].suffix);
282                 fsdev = fsdev_allocate_one_dev(vdev, out_dirpath,
283                                                out_dirname, dtype);
284                 if (!fsdev) {
285                         count--;
286                         i++;
287                         continue;
288                 }
289                 break;
290         }
291         if (fsdev == NULL) {
292                 BCMFS_LOG(ERR, "All supported devs busy");
293                 return -ENODEV;
294         }
295
296         err = bcmfs_sym_dev_create(fsdev);
297         if (err) {
298                 BCMFS_LOG(WARNING,
299                           "Failed to create BCMFS SYM PMD for device %s",
300                           fsdev->name);
301                 goto pmd_create_fail;
302         }
303
304         return 0;
305
306 pmd_create_fail:
307         fsdev_release(fsdev);
308
309         return err;
310 }
311
312 static int
313 bcmfs_vdev_remove(struct rte_vdev_device *vdev)
314 {
315         struct bcmfs_device *fsdev;
316
317         fsdev = find_fsdev(vdev);
318         if (fsdev == NULL)
319                 return -ENODEV;
320
321         fsdev_release(fsdev);
322         return 0;
323 }
324
325 /* Register with vdev */
326 static struct rte_vdev_driver rte_bcmfs_pmd = {
327         .probe = bcmfs_vdev_probe,
328         .remove = bcmfs_vdev_remove
329 };
330
331 RTE_PMD_REGISTER_VDEV(bcmfs_pmd,
332                       rte_bcmfs_pmd);