1 /* SPDX-License-Identifier: BSD-3-Clause
2 * Copyright(C) 2020 Broadcom.
10 #include <rte_malloc.h>
11 #include <rte_string_fns.h>
13 #include "bcmfs_device.h"
14 #include "bcmfs_logs.h"
16 #include "bcmfs_vfio.h"
18 struct bcmfs_device_attr {
19 const char name[BCMFS_MAX_PATH_LEN];
20 const char suffix[BCMFS_DEV_NAME_LEN];
21 const enum bcmfs_device_type type;
22 const uint32_t offset;
23 const uint32_t version;
26 /* BCMFS supported devices */
27 static struct bcmfs_device_attr dev_table[] = {
30 .suffix = "crypto_mbox",
31 .type = BCMFS_SYM_FS4,
33 .version = BCMFS_SYM_FS4_VERSION
38 .type = BCMFS_SYM_FS5,
40 .version = BCMFS_SYM_FS5_VERSION
47 struct bcmfs_hw_queue_pair_ops_table bcmfs_hw_queue_pair_ops_table = {
48 .tl = RTE_SPINLOCK_INITIALIZER,
52 int bcmfs_hw_queue_pair_register_ops(const struct bcmfs_hw_queue_pair_ops *h)
54 struct bcmfs_hw_queue_pair_ops *ops;
57 rte_spinlock_lock(&bcmfs_hw_queue_pair_ops_table.tl);
59 if (h->enq_one_req == NULL || h->dequeue == NULL ||
60 h->ring_db == NULL || h->startq == NULL || h->stopq == NULL) {
61 rte_spinlock_unlock(&bcmfs_hw_queue_pair_ops_table.tl);
63 "Missing callback while registering device ops");
67 if (strlen(h->name) >= sizeof(ops->name) - 1) {
68 rte_spinlock_unlock(&bcmfs_hw_queue_pair_ops_table.tl);
69 BCMFS_LOG(ERR, "%s(): fs device_ops <%s>: name too long",
74 ops_index = bcmfs_hw_queue_pair_ops_table.num_ops++;
75 ops = &bcmfs_hw_queue_pair_ops_table.qp_ops[ops_index];
76 strlcpy(ops->name, h->name, sizeof(ops->name));
77 ops->enq_one_req = h->enq_one_req;
78 ops->dequeue = h->dequeue;
79 ops->ring_db = h->ring_db;
80 ops->startq = h->startq;
81 ops->stopq = h->stopq;
83 rte_spinlock_unlock(&bcmfs_hw_queue_pair_ops_table.tl);
88 TAILQ_HEAD(fsdev_list, bcmfs_device);
89 static struct fsdev_list fsdev_list = TAILQ_HEAD_INITIALIZER(fsdev_list);
91 static struct bcmfs_device *
92 fsdev_allocate_one_dev(struct rte_vdev_device *vdev,
95 enum bcmfs_device_type dev_type __rte_unused)
97 struct bcmfs_device *fsdev;
100 fsdev = rte_calloc(__func__, 1, sizeof(*fsdev), 0);
104 if (strlen(dirpath) > sizeof(fsdev->dirname)) {
105 BCMFS_LOG(ERR, "dir path name is too long");
109 if (strlen(devname) > sizeof(fsdev->name)) {
110 BCMFS_LOG(ERR, "devname is too long");
114 /* check if registered ops name is present in directory path */
115 for (i = 0; i < bcmfs_hw_queue_pair_ops_table.num_ops; i++)
117 bcmfs_hw_queue_pair_ops_table.qp_ops[i].name))
118 fsdev->sym_hw_qp_ops =
119 &bcmfs_hw_queue_pair_ops_table.qp_ops[i];
120 if (!fsdev->sym_hw_qp_ops)
123 strcpy(fsdev->dirname, dirpath);
124 strcpy(fsdev->name, devname);
129 if (bcmfs_attach_vfio(fsdev))
132 /* Maximum number of QPs supported */
133 fsdev->max_hw_qps = fsdev->mmap_size / BCMFS_HW_QUEUE_IO_ADDR_LEN;
135 TAILQ_INSERT_TAIL(&fsdev_list, fsdev, next);
145 static struct bcmfs_device *
146 find_fsdev(struct rte_vdev_device *vdev)
148 struct bcmfs_device *fsdev;
150 TAILQ_FOREACH(fsdev, &fsdev_list, next)
151 if (fsdev->vdev == vdev)
158 fsdev_release(struct bcmfs_device *fsdev)
163 TAILQ_REMOVE(&fsdev_list, fsdev, next);
168 cmprator(const void *a, const void *b)
170 return (*(const unsigned int *)a - *(const unsigned int *)b);
174 fsdev_find_all_devs(const char *path, const char *search,
178 struct dirent *entry;
180 char addr[BCMFS_MAX_NODES][BCMFS_MAX_PATH_LEN];
185 BCMFS_LOG(ERR, "Unable to open directory");
189 while ((entry = readdir(dir)) != NULL) {
190 if (strstr(entry->d_name, search)) {
191 strlcpy(addr[count], entry->d_name,
199 for (i = 0 ; i < count; i++)
200 devs[i] = (uint32_t)strtoul(addr[i], NULL, 16);
201 /* sort the devices based on IO addresses */
202 qsort(devs, count, sizeof(uint32_t), cmprator);
208 fsdev_find_sub_dir(char *path, const char *search, char *output)
211 struct dirent *entry;
215 BCMFS_LOG(ERR, "Unable to open directory");
219 while ((entry = readdir(dir)) != NULL) {
220 if (!strcmp(entry->d_name, search)) {
221 strlcpy(output, entry->d_name, BCMFS_MAX_PATH_LEN);
234 bcmfs_vdev_probe(struct rte_vdev_device *vdev)
236 struct bcmfs_device *fsdev;
237 char top_dirpath[BCMFS_MAX_PATH_LEN];
238 char sub_dirpath[BCMFS_MAX_PATH_LEN];
239 char out_dirpath[BCMFS_MAX_PATH_LEN];
240 char out_dirname[BCMFS_MAX_PATH_LEN];
241 uint32_t fsdev_dev[BCMFS_MAX_NODES];
242 enum bcmfs_device_type dtype;
248 sprintf(top_dirpath, "%s", SYSFS_BCM_PLTFORM_DEVICES);
249 while (strlen(dev_table[i].name)) {
250 found = fsdev_find_sub_dir(top_dirpath,
258 BCMFS_LOG(ERR, "No supported bcmfs dev found");
263 dtype = dev_table[i].type;
265 snprintf(out_dirpath, sizeof(out_dirpath), "%s/%s",
266 top_dirpath, sub_dirpath);
267 count = fsdev_find_all_devs(out_dirpath,
268 dev_table[dev_idx].suffix,
271 BCMFS_LOG(ERR, "No supported bcmfs dev found");
277 /* format the device name present in the patch */
278 snprintf(out_dirname, sizeof(out_dirname), "%x.%s",
279 fsdev_dev[i], dev_table[dev_idx].suffix);
280 fsdev = fsdev_allocate_one_dev(vdev, out_dirpath,
290 BCMFS_LOG(ERR, "All supported devs busy");
298 bcmfs_vdev_remove(struct rte_vdev_device *vdev)
300 struct bcmfs_device *fsdev;
302 fsdev = find_fsdev(vdev);
306 fsdev_release(fsdev);
310 /* Register with vdev */
311 static struct rte_vdev_driver rte_bcmfs_pmd = {
312 .probe = bcmfs_vdev_probe,
313 .remove = bcmfs_vdev_remove
316 RTE_PMD_REGISTER_VDEV(bcmfs_pmd,