1 /* SPDX-License-Identifier: BSD-3-Clause
2 * Copyright 2020 Mellanox Technologies, Ltd
3 */
4
5 #include <errno.h>
6 #include <stdalign.h>
7 #include <stddef.h>
8 #include <stdint.h>
9 #include <stdlib.h>
10 #include <unistd.h>
11
12 #include <rte_malloc.h>
13
14 #include "mlx5_glue.h"
15 #include "../mlx5_common_log.h"
16 #include "mlx5_win_ext.h"
17
18 /*
19 * The returned value of this API is an array of pointers to mlx5
20 * devices under Windows. The interesting parameters of a device:
21 * Device PCI parameters: domain, bus, device id, function.
22 * Device name.
23 */
24 static void *
mlx5_glue_devx_get_device_list(int * num_devices)25 mlx5_glue_devx_get_device_list(int *num_devices)
26 {
27 struct devx_device_bdf *devx_bdf_devs = NULL;
28 size_t n_devx_devx = 0;
29 int32_t ret = devx_get_device_list(&n_devx_devx, &devx_bdf_devs);
30
31 if (ret) {
32 errno = ret;
33 *num_devices = 0;
34 return NULL;
35 }
36 *num_devices = (int)n_devx_devx;
37 return devx_bdf_devs;
38 }
39
40 static void
mlx5_glue_devx_free_device_list(void * list)41 mlx5_glue_devx_free_device_list(void *list)
42 {
43 if (!list) {
44 errno = EINVAL;
45 return;
46 }
47 devx_free_device_list(list);
48 }
49
50 static int
mlx5_glue_devx_close_device(void * ctx)51 mlx5_glue_devx_close_device(void *ctx)
52 {
53 mlx5_context_st *mlx5_ctx;
54 int rc;
55
56 if (!ctx)
57 return -EINVAL;
58 mlx5_ctx = (mlx5_context_st *)ctx;
59 rc = devx_close_device(mlx5_ctx->devx_ctx);
60 free(mlx5_ctx);
61 return rc;
62 }
63
64 static void *
mlx5_glue_devx_open_device(void * device)65 mlx5_glue_devx_open_device(void *device)
66 {
67 struct mlx5_context *mlx5_ctx;
68
69 if (!device) {
70 errno = EINVAL;
71 return NULL;
72 }
73 mlx5_ctx = malloc((sizeof(struct mlx5_context)));
74 if (!mlx5_ctx) {
75 errno = ENOMEM;
76 return NULL;
77 }
78 memset(mlx5_ctx, 0, sizeof(*mlx5_ctx));
79 mlx5_ctx->devx_ctx = devx_open_device(device);
80 if (DEVX_IS_ERR(mlx5_ctx->devx_ctx)) {
81 errno = -DEVX_PTR_ERR(mlx5_ctx->devx_ctx);
82 free(mlx5_ctx);
83 return NULL;
84 }
85 return mlx5_ctx;
86 }
87
88 static int
mlx5_glue_devx_query_device(void * device_bdf,void * dev_inf)89 mlx5_glue_devx_query_device(void *device_bdf, void *dev_inf)
90 {
91 struct devx_device_bdf *dev_bdf;
92 struct devx_device *mlx5_dev;
93
94 if (!device_bdf)
95 return -EINVAL;
96 dev_bdf = (struct devx_device_bdf *)device_bdf;
97 mlx5_dev = (struct devx_device *)dev_inf;
98 int err = devx_query_device(dev_bdf, mlx5_dev);
99 if (err)
100 return -E_FAIL;
101 return 0;
102 }
103
104 static void *
mlx5_glue_devx_query_hca_iseg_mapping(void * ctx,uint32_t * cb_iseg)105 mlx5_glue_devx_query_hca_iseg_mapping(void *ctx, uint32_t *cb_iseg)
106 {
107 struct mlx5_context *mlx5_ctx;
108 void *pv_iseg;
109 int err;
110
111 if (!ctx) {
112 errno = EINVAL;
113 return NULL;
114 }
115 mlx5_ctx = (struct mlx5_context *)ctx;
116 err = devx_query_hca_iseg_mapping(mlx5_ctx->devx_ctx,
117 cb_iseg, &pv_iseg);
118 if (err) {
119 errno = err;
120 return NULL;
121 }
122 return pv_iseg;
123 }
124
125 static void *
mlx5_glue_devx_obj_create(void * ctx,void * in,size_t inlen,void * out,size_t outlen)126 mlx5_glue_devx_obj_create(void *ctx,
127 void *in, size_t inlen,
128 void *out, size_t outlen)
129 {
130 mlx5_devx_obj_st *devx_obj;
131
132 if (!ctx) {
133 errno = EINVAL;
134 return NULL;
135 }
136 devx_obj = malloc((sizeof(*devx_obj)));
137 if (!devx_obj) {
138 errno = ENOMEM;
139 return NULL;
140 }
141 memset(devx_obj, 0, sizeof(*devx_obj));
142 devx_obj->devx_ctx = GET_DEVX_CTX(ctx);
143 devx_obj->obj = devx_obj_create(devx_obj->devx_ctx,
144 in, inlen, out, outlen);
145 if (DEVX_IS_ERR(devx_obj->obj)) {
146 errno = -DEVX_PTR_ERR(devx_obj->obj);
147 free(devx_obj);
148 return NULL;
149 }
150 return devx_obj;
151 }
152
153 static int
mlx5_glue_devx_obj_destroy(void * obj)154 mlx5_glue_devx_obj_destroy(void *obj)
155 {
156 mlx5_devx_obj_st *devx_obj;
157
158 if (!obj)
159 return -EINVAL;
160 devx_obj = obj;
161 int rc = devx_obj_destroy(devx_obj->obj);
162 free(devx_obj);
163 return rc;
164 }
165
166 static int
mlx5_glue_devx_general_cmd(void * ctx,void * in,size_t inlen,void * out,size_t outlen)167 mlx5_glue_devx_general_cmd(void *ctx,
168 void *in, size_t inlen,
169 void *out, size_t outlen)
170 {
171 if (!ctx)
172 return -EINVAL;
173 return devx_cmd(GET_DEVX_CTX(ctx), in, inlen, out, outlen);
174 }
175
176 static int
mlx5_glue_devx_obj_query(void * obj,void * in,size_t inlen,void * out,size_t outlen)177 mlx5_glue_devx_obj_query(void *obj,
178 void *in, size_t inlen,
179 void *out, size_t outlen)
180 {
181 return devx_cmd(GET_OBJ_CTX(obj), in, inlen, out, outlen);
182 }
183
184 static int
mlx5_glue_devx_obj_modify(void * obj,void * in,size_t inlen,void * out,size_t outlen)185 mlx5_glue_devx_obj_modify(void *obj,
186 void *in, size_t inlen,
187 void *out, size_t outlen)
188 {
189 return devx_cmd(GET_OBJ_CTX(obj), in, inlen, out, outlen);
190 }
191
192 static int
mlx5_glue_devx_umem_dereg(void * pumem)193 mlx5_glue_devx_umem_dereg(void *pumem)
194 {
195 struct devx_obj_handle *umem;
196
197 if (!pumem)
198 return -EINVAL;
199 umem = pumem;
200 return devx_umem_unreg(umem);
201 }
202
203 static void *
mlx5_glue_devx_umem_reg(void * ctx,void * addr,size_t size,uint32_t access,uint32_t * id)204 mlx5_glue_devx_umem_reg(void *ctx, void *addr, size_t size,
205 uint32_t access, uint32_t *id)
206 {
207 struct devx_obj_handle *umem_hdl;
208 int w_access = DEVX_UMEM_ACCESS_READ;
209
210 if (!ctx) {
211 errno = EINVAL;
212 return NULL;
213 }
214 if (access)
215 w_access |= DEVX_UMEM_ACCESS_WRITE;
216
217 umem_hdl = devx_umem_reg(GET_DEVX_CTX(ctx), addr,
218 size, w_access, id);
219 if (DEVX_IS_ERR(umem_hdl)) {
220 errno = -DEVX_PTR_ERR(umem_hdl);
221 return NULL;
222 }
223 return umem_hdl;
224 }
225
226 static void *
mlx5_glue_devx_alloc_uar(void * ctx,uint32_t flags)227 mlx5_glue_devx_alloc_uar(void *ctx,
228 uint32_t flags)
229 {
230 devx_uar_handle *uar;
231
232 if (!ctx) {
233 errno = EINVAL;
234 return NULL;
235 }
236 uar = devx_alloc_uar(GET_DEVX_CTX(ctx), flags);
237 if (DEVX_IS_ERR(uar)) {
238 errno = -DEVX_PTR_ERR(uar);
239 return NULL;
240 }
241 return uar;
242 }
243
244 static int
mlx5_glue_devx_query_eqn(void * ctx,uint32_t cpus,uint32_t * eqn)245 mlx5_glue_devx_query_eqn(void *ctx,
246 uint32_t cpus, uint32_t *eqn)
247 {
248 if (!ctx)
249 return -EINVAL;
250 return devx_query_eqn(GET_DEVX_CTX(ctx), cpus, eqn);
251 }
252
253 static void
mlx5_glue_devx_free_uar(void * uar)254 mlx5_glue_devx_free_uar(void *uar)
255 {
256 devx_free_uar((devx_uar_handle *)uar);
257 }
258
259 static_assert(MLX5_ST_SZ_BYTES(fte_match_param) == 0x200,
260 "PRM size of fte_match_param is broken! cannot compile Windows!");
261
262 static void*
mlx5_glue_devx_fs_rule_add(void * ctx,void * in,uint32_t inlen)263 mlx5_glue_devx_fs_rule_add(void *ctx, void *in, uint32_t inlen)
264
265 {
266 struct devx_obj_handle *rule_hdl = NULL;
267
268 if (!ctx) {
269 errno = EINVAL;
270 return NULL;
271 }
272 rule_hdl = devx_fs_rule_add(GET_DEVX_CTX(ctx), in, inlen);
273 if (DEVX_IS_ERR(rule_hdl)) {
274 errno = -DEVX_PTR_ERR(rule_hdl);
275 return NULL;
276 }
277 return rule_hdl;
278 }
279
280 static int
mlx5_glue_devx_fs_rule_del(void * flow)281 mlx5_glue_devx_fs_rule_del(void *flow)
282 {
283 return devx_fs_rule_del(flow);
284 }
285
286 static int
mlx5_glue_query_rt_values(void * ctx,void * devx_clock)287 mlx5_glue_query_rt_values(void *ctx, void *devx_clock)
288 {
289 struct mlx5_context *mlx5_ctx;
290 struct mlx5_devx_clock *clock;
291 int err;
292
293 if (!ctx) {
294 errno = EINVAL;
295 return errno;
296 }
297 mlx5_ctx = (struct mlx5_context *)ctx;
298 clock = (struct mlx5_devx_clock *)devx_clock;
299 err = devx_hca_clock_query(
300 mlx5_ctx->devx_ctx,
301 &clock->p_iseg_internal_timer,
302 &clock->clock_frequency_hz,
303 &clock->is_stable_clock_frequency);
304 if (err) {
305 errno = err;
306 return errno;
307 }
308 return 0;
309 }
310
311 static int
mlx5_glue_devx_init_showdown_event(void * ctx)312 mlx5_glue_devx_init_showdown_event(void *ctx)
313 {
314 struct mlx5_context *mlx5_ctx;
315 int err;
316
317 if (!ctx) {
318 errno = EINVAL;
319 return errno;
320 }
321 mlx5_ctx = (struct mlx5_context *)ctx;
322 err = devx_query_shutdown_event(mlx5_ctx->devx_ctx,
323 &mlx5_ctx->shutdown_event_obj);
324 if (err) {
325 errno = err;
326 return errno;
327 }
328 return 0;
329 }
330
331 static int
mlx5_glue_devx_set_promisc_vport(void * ctx,uint32_t promisc_type,uint8_t f_enable)332 mlx5_glue_devx_set_promisc_vport(void *ctx, uint32_t promisc_type, uint8_t f_enable)
333 {
334 #ifdef HAVE_DEVX_SET_PROMISC_SUPPORT
335 int devx_promisc_type = MLX5_DEVX_SET_PROMISC_VPORT_PROMISC_MODE;
336 struct mlx5_context *mlx5_ctx;
337 int err;
338
339 if (!ctx) {
340 errno = EINVAL;
341 return errno;
342 }
343 mlx5_ctx = (struct mlx5_context *)ctx;
344 if (promisc_type == MC_PROMISC)
345 devx_promisc_type = MLX5_DEVX_SET_PROMISC_VPORT_ALL_MULTICAST;
346 err = devx_set_promisc_vport(mlx5_ctx->devx_ctx, devx_promisc_type, f_enable);
347 if (err) {
348 errno = err;
349 return errno;
350 }
351 return 0;
352 #else
353 (void)promisc_type;
354 (void)f_enable;
355 (void)ctx;
356 DRV_LOG(WARNING, "%s: is not supported", __func__);
357 return -ENOTSUP;
358 #endif
359 }
360
361 static int
mlx5_glue_devx_get_mtu(void * ctx,uint32_t * mtu)362 mlx5_glue_devx_get_mtu(void *ctx, uint32_t *mtu)
363 {
364 int err = 0;
365 struct mlx5_context *mlx5_ctx;
366
367 if (!ctx) {
368 errno = EINVAL;
369 return errno;
370 }
371 mlx5_ctx = (struct mlx5_context *)ctx;
372 #ifdef HAVE_DEVX_SET_GET_MTU_SUPPORT
373 err = devx_get_mtu(mlx5_ctx->devx_ctx, mtu);
374 if (err) {
375 errno = err;
376 return errno;
377 }
378 #else
379 *mtu = mlx5_ctx->mlx5_dev.mtu_bytes;
380 #endif
381
382 return err;
383 }
384
385 static int
mlx5_glue_devx_set_mtu(void * ctx,uint32_t mtu)386 mlx5_glue_devx_set_mtu(void *ctx, uint32_t mtu)
387 {
388 #ifdef HAVE_DEVX_SET_GET_MTU_SUPPORT
389 struct mlx5_context *mlx5_ctx;
390 int err;
391
392 if (!ctx) {
393 errno = EINVAL;
394 return errno;
395 }
396 mlx5_ctx = (struct mlx5_context *)ctx;
397 err = devx_set_mtu(mlx5_ctx->devx_ctx, mtu);
398 if (err) {
399 errno = err;
400 return errno;
401 }
402 return 0;
403 #else
404 (void)mtu;
405 (void)ctx;
406 DRV_LOG(WARNING, "%s: is not supported", __func__);
407 return -ENOTSUP;
408 #endif
409
410 }
411
412
413
414 alignas(RTE_CACHE_LINE_SIZE)
415 const struct mlx5_glue *mlx5_glue = &(const struct mlx5_glue){
416 .version = MLX5_GLUE_VERSION,
417 .get_device_list = mlx5_glue_devx_get_device_list,
418 .free_device_list = mlx5_glue_devx_free_device_list,
419 .open_device = mlx5_glue_devx_open_device,
420 .close_device = mlx5_glue_devx_close_device,
421 .query_device = mlx5_glue_devx_query_device,
422 .query_hca_iseg = mlx5_glue_devx_query_hca_iseg_mapping,
423 .devx_obj_create = mlx5_glue_devx_obj_create,
424 .devx_obj_destroy = mlx5_glue_devx_obj_destroy,
425 .devx_obj_query = mlx5_glue_devx_obj_query,
426 .devx_obj_modify = mlx5_glue_devx_obj_modify,
427 .devx_general_cmd = mlx5_glue_devx_general_cmd,
428 .devx_umem_reg = mlx5_glue_devx_umem_reg,
429 .devx_umem_dereg = mlx5_glue_devx_umem_dereg,
430 .devx_alloc_uar = mlx5_glue_devx_alloc_uar,
431 .devx_free_uar = mlx5_glue_devx_free_uar,
432 .devx_fs_rule_add = mlx5_glue_devx_fs_rule_add,
433 .devx_fs_rule_del = mlx5_glue_devx_fs_rule_del,
434 .devx_query_eqn = mlx5_glue_devx_query_eqn,
435 .query_rt_values = mlx5_glue_query_rt_values,
436 .devx_init_showdown_event = mlx5_glue_devx_init_showdown_event,
437 .devx_set_promisc_vport = mlx5_glue_devx_set_promisc_vport,
438 .devx_get_mtu = mlx5_glue_devx_get_mtu,
439 .devx_set_mtu = mlx5_glue_devx_set_mtu,
440 };
441