xref: /dpdk/drivers/common/mlx5/linux/mlx5_common_auxiliary.c (revision 777b72a9339c375b5c70dbe09262ad1fd123f159)
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 <rte_bus_auxiliary.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
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
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 static int
72 mlx5_auxiliary_get_numa(const struct rte_auxiliary_device *dev)
73 {
74 	unsigned long numa;
75 	char numa_path[PATH_MAX];
76 
77 	if (mlx5_auxiliary_get_pci_path(dev, numa_path, sizeof(numa_path)) != 0)
78 		return SOCKET_ID_ANY;
79 	if (strcat(numa_path, "/numa_node") == NULL) {
80 		rte_errno = ENAMETOOLONG;
81 		return SOCKET_ID_ANY;
82 	}
83 	if (eal_parse_sysfs_value(numa_path, &numa) != 0) {
84 		rte_errno = EINVAL;
85 		return SOCKET_ID_ANY;
86 	}
87 	return (int)numa;
88 }
89 
90 struct ibv_device *
91 mlx5_get_aux_ibv_device(const struct rte_auxiliary_device *dev)
92 {
93 	int n;
94 	char ib_name[64] = { 0 };
95 	struct ibv_device **ibv_list = mlx5_glue->get_device_list(&n);
96 	struct ibv_device *ibv_match = NULL;
97 
98 	if (!ibv_list) {
99 		rte_errno = ENOSYS;
100 		return NULL;
101 	}
102 	if (mlx5_auxiliary_get_child_name(dev->name, "/infiniband",
103 					  ib_name, sizeof(ib_name)) != 0)
104 		goto out;
105 	while (n-- > 0) {
106 		if (strcmp(ibv_list[n]->name, ib_name) != 0)
107 			continue;
108 		ibv_match = ibv_list[n];
109 		break;
110 	}
111 	if (ibv_match == NULL)
112 		rte_errno = ENOENT;
113 out:
114 	mlx5_glue->free_device_list(ibv_list);
115 	return ibv_match;
116 }
117 
118 static bool
119 mlx5_common_auxiliary_match(const char *name)
120 {
121 	return strncmp(name, MLX5_AUXILIARY_PREFIX,
122 		       strlen(MLX5_AUXILIARY_PREFIX)) == 0;
123 }
124 
125 static int
126 mlx5_common_auxiliary_probe(struct rte_auxiliary_driver *drv __rte_unused,
127 			    struct rte_auxiliary_device *dev)
128 {
129 	dev->device.numa_node = mlx5_auxiliary_get_numa(dev);
130 	return mlx5_common_dev_probe(&dev->device);
131 }
132 
133 static int
134 mlx5_common_auxiliary_remove(struct rte_auxiliary_device *auxiliary_dev)
135 {
136 	return mlx5_common_dev_remove(&auxiliary_dev->device);
137 }
138 
139 static int
140 mlx5_common_auxiliary_dma_map(struct rte_auxiliary_device *auxiliary_dev,
141 			      void *addr, uint64_t iova, size_t len)
142 {
143 	return mlx5_common_dev_dma_map(&auxiliary_dev->device, addr, iova, len);
144 }
145 
146 static int
147 mlx5_common_auxiliary_dma_unmap(struct rte_auxiliary_device *auxiliary_dev,
148 				void *addr, uint64_t iova, size_t len)
149 {
150 	return mlx5_common_dev_dma_unmap(&auxiliary_dev->device, addr, iova,
151 					 len);
152 }
153 
154 static struct rte_auxiliary_driver mlx5_auxiliary_driver = {
155 	.driver = {
156 		   .name = MLX5_AUXILIARY_DRIVER_NAME,
157 	},
158 	.match = mlx5_common_auxiliary_match,
159 	.probe = mlx5_common_auxiliary_probe,
160 	.remove = mlx5_common_auxiliary_remove,
161 	.dma_map = mlx5_common_auxiliary_dma_map,
162 	.dma_unmap = mlx5_common_auxiliary_dma_unmap,
163 };
164 
165 void mlx5_common_auxiliary_init(void)
166 {
167 	if (mlx5_auxiliary_driver.bus == NULL)
168 		rte_auxiliary_register(&mlx5_auxiliary_driver);
169 }
170 
171 RTE_FINI(mlx5_common_auxiliary_driver_finish)
172 {
173 	if (mlx5_auxiliary_driver.bus != NULL)
174 		rte_auxiliary_unregister(&mlx5_auxiliary_driver);
175 }
176