xref: /dpdk/drivers/common/mlx5/windows/mlx5_glue.c (revision cb91f12f4a0c094b27110ccb7c187b8d260e685f)
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