common/mlx5: share device context object
[dpdk.git] / drivers / common / mlx5 / linux / mlx5_common_auxiliary.c
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 int
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
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 *
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
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
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
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
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
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 void mlx5_common_auxiliary_init(void)
183 {
184         if (mlx5_auxiliary_driver.bus == NULL)
185                 rte_auxiliary_register(&mlx5_auxiliary_driver);
186 }
187
188 RTE_FINI(mlx5_common_auxiliary_driver_finish)
189 {
190         if (mlx5_auxiliary_driver.bus != NULL)
191                 rte_auxiliary_unregister(&mlx5_auxiliary_driver);
192 }