xref: /dpdk/drivers/common/mlx5/linux/mlx5_common_auxiliary.c (revision b3f89090d667a3ab29e8327242dbc0c12d8b7262)
1 /* SPDX-License-Identifier: BSD-3-Clause
2  * Copyright 2020 Mellanox Technologies Ltd
3  */
4 
5 #include <stdlib.h>
6 #include <dirent.h>
7 #include <libgen.h>
8 
9 #include <rte_malloc.h>
10 #include <rte_errno.h>
11 #include <bus_auxiliary_driver.h>
12 #include <rte_common.h>
13 #include "eal_filesystem.h"
14 
15 #include "mlx5_common_utils.h"
16 #include "mlx5_common_private.h"
17 
18 #define AUXILIARY_SYSFS_PATH "/sys/bus/auxiliary/devices"
19 #define MLX5_AUXILIARY_PREFIX "mlx5_core.sf."
20 
21 int
mlx5_auxiliary_get_child_name(const char * dev,const char * node,char * child,size_t size)22 mlx5_auxiliary_get_child_name(const char *dev, const char *node,
23 			      char *child, size_t size)
24 {
25 	DIR *dir;
26 	struct dirent *dent;
27 	MKSTR(path, "%s/%s%s", AUXILIARY_SYSFS_PATH, dev, node);
28 
29 	dir = opendir(path);
30 	if (dir == NULL) {
31 		rte_errno = errno;
32 		return -rte_errno;
33 	}
34 	/* Get the first file name. */
35 	while ((dent = readdir(dir)) != NULL) {
36 		if (dent->d_name[0] != '.')
37 			break;
38 	}
39 	closedir(dir);
40 	if (dent == NULL) {
41 		rte_errno = ENOENT;
42 		return -rte_errno;
43 	}
44 	if (rte_strscpy(child, dent->d_name, size) < 0)
45 		return -rte_errno;
46 	return 0;
47 }
48 
49 static int
mlx5_auxiliary_get_pci_path(const struct rte_auxiliary_device * dev,char * sysfs_pci,size_t size)50 mlx5_auxiliary_get_pci_path(const struct rte_auxiliary_device *dev,
51 			    char *sysfs_pci, size_t size)
52 {
53 	char sysfs_real[PATH_MAX] = { 0 };
54 	MKSTR(sysfs_aux, "%s/%s", AUXILIARY_SYSFS_PATH, dev->name);
55 	char *dir;
56 
57 	if (realpath(sysfs_aux, sysfs_real) == NULL) {
58 		rte_errno = errno;
59 		return -rte_errno;
60 	}
61 	dir = dirname(sysfs_real);
62 	if (dir == NULL) {
63 		rte_errno = errno;
64 		return -rte_errno;
65 	}
66 	if (rte_strscpy(sysfs_pci, dir, size) < 0)
67 		return -rte_errno;
68 	return 0;
69 }
70 
71 int
mlx5_auxiliary_get_pci_str(const struct rte_auxiliary_device * dev,char * addr,size_t size)72 mlx5_auxiliary_get_pci_str(const struct rte_auxiliary_device *dev,
73 			   char *addr, size_t size)
74 {
75 	char sysfs_pci[PATH_MAX];
76 	char *base;
77 
78 	if (mlx5_auxiliary_get_pci_path(dev, sysfs_pci, sizeof(sysfs_pci)) != 0)
79 		return -ENODEV;
80 	base = basename(sysfs_pci);
81 	if (base == NULL)
82 		return -errno;
83 	if (rte_strscpy(addr, base, size) < 0)
84 		return -rte_errno;
85 	return 0;
86 }
87 
88 static int
mlx5_auxiliary_get_numa(const struct rte_auxiliary_device * dev)89 mlx5_auxiliary_get_numa(const struct rte_auxiliary_device *dev)
90 {
91 	unsigned long numa;
92 	char numa_path[PATH_MAX];
93 
94 	if (mlx5_auxiliary_get_pci_path(dev, numa_path, sizeof(numa_path)) != 0)
95 		return SOCKET_ID_ANY;
96 	if (strcat(numa_path, "/numa_node") == NULL) {
97 		rte_errno = ENAMETOOLONG;
98 		return SOCKET_ID_ANY;
99 	}
100 	if (eal_parse_sysfs_value(numa_path, &numa) != 0) {
101 		rte_errno = EINVAL;
102 		return SOCKET_ID_ANY;
103 	}
104 	return (int)numa;
105 }
106 
107 struct ibv_device *
mlx5_get_aux_ibv_device(const struct rte_auxiliary_device * dev)108 mlx5_get_aux_ibv_device(const struct rte_auxiliary_device *dev)
109 {
110 	int n;
111 	char ib_name[64] = { 0 };
112 	struct ibv_device **ibv_list = mlx5_glue->get_device_list(&n);
113 	struct ibv_device *ibv_match = NULL;
114 
115 	if (!ibv_list) {
116 		rte_errno = ENOSYS;
117 		return NULL;
118 	}
119 	if (mlx5_auxiliary_get_child_name(dev->name, "/infiniband",
120 					  ib_name, sizeof(ib_name)) != 0)
121 		goto out;
122 	while (n-- > 0) {
123 		if (strcmp(ibv_list[n]->name, ib_name) != 0)
124 			continue;
125 		ibv_match = ibv_list[n];
126 		break;
127 	}
128 	if (ibv_match == NULL)
129 		rte_errno = ENOENT;
130 out:
131 	mlx5_glue->free_device_list(ibv_list);
132 	return ibv_match;
133 }
134 
135 static bool
mlx5_common_auxiliary_match(const char * name)136 mlx5_common_auxiliary_match(const char *name)
137 {
138 	return strncmp(name, MLX5_AUXILIARY_PREFIX,
139 		       strlen(MLX5_AUXILIARY_PREFIX)) == 0;
140 }
141 
142 static int
mlx5_common_auxiliary_probe(struct rte_auxiliary_driver * drv __rte_unused,struct rte_auxiliary_device * dev)143 mlx5_common_auxiliary_probe(struct rte_auxiliary_driver *drv __rte_unused,
144 			    struct rte_auxiliary_device *dev)
145 {
146 	dev->device.numa_node = mlx5_auxiliary_get_numa(dev);
147 	return mlx5_common_dev_probe(&dev->device);
148 }
149 
150 static int
mlx5_common_auxiliary_remove(struct rte_auxiliary_device * auxiliary_dev)151 mlx5_common_auxiliary_remove(struct rte_auxiliary_device *auxiliary_dev)
152 {
153 	return mlx5_common_dev_remove(&auxiliary_dev->device);
154 }
155 
156 static int
mlx5_common_auxiliary_dma_map(struct rte_auxiliary_device * auxiliary_dev,void * addr,uint64_t iova,size_t len)157 mlx5_common_auxiliary_dma_map(struct rte_auxiliary_device *auxiliary_dev,
158 			      void *addr, uint64_t iova, size_t len)
159 {
160 	return mlx5_common_dev_dma_map(&auxiliary_dev->device, addr, iova, len);
161 }
162 
163 static int
mlx5_common_auxiliary_dma_unmap(struct rte_auxiliary_device * auxiliary_dev,void * addr,uint64_t iova,size_t len)164 mlx5_common_auxiliary_dma_unmap(struct rte_auxiliary_device *auxiliary_dev,
165 				void *addr, uint64_t iova, size_t len)
166 {
167 	return mlx5_common_dev_dma_unmap(&auxiliary_dev->device, addr, iova,
168 					 len);
169 }
170 
171 static struct rte_auxiliary_driver mlx5_auxiliary_driver = {
172 	.driver = {
173 		   .name = MLX5_AUXILIARY_DRIVER_NAME,
174 	},
175 	.match = mlx5_common_auxiliary_match,
176 	.probe = mlx5_common_auxiliary_probe,
177 	.remove = mlx5_common_auxiliary_remove,
178 	.dma_map = mlx5_common_auxiliary_dma_map,
179 	.dma_unmap = mlx5_common_auxiliary_dma_unmap,
180 };
181 
182 static bool mlx5_common_auxiliary_initialized;
183 
mlx5_common_auxiliary_init(void)184 void mlx5_common_auxiliary_init(void)
185 {
186 	if (!mlx5_common_auxiliary_initialized) {
187 		rte_auxiliary_register(&mlx5_auxiliary_driver);
188 		mlx5_common_auxiliary_initialized = true;
189 	}
190 }
191 
RTE_FINI(mlx5_common_auxiliary_driver_finish)192 RTE_FINI(mlx5_common_auxiliary_driver_finish)
193 {
194 	if (mlx5_common_auxiliary_initialized) {
195 		rte_auxiliary_unregister(&mlx5_auxiliary_driver);
196 		mlx5_common_auxiliary_initialized = false;
197 	}
198 }
199