/* SPDX-License-Identifier: BSD-3-Clause * Copyright 2020 Mellanox Technologies, Ltd */ #include #include #include #include #include #include #include #include "mlx5_glue.h" #include "../mlx5_common_log.h" #include "mlx5_win_ext.h" /* * The returned value of this API is an array of pointers to mlx5 * devices under Windows. The interesting parameters of a device: * Device PCI parameters: domain, bus, device id, function. * Device name. */ static void * mlx5_glue_devx_get_device_list(int *num_devices) { struct devx_device_bdf *devx_bdf_devs = NULL; size_t n_devx_devx = 0; int32_t ret = devx_get_device_list(&n_devx_devx, &devx_bdf_devs); if (ret) { errno = ret; *num_devices = 0; return NULL; } *num_devices = (int)n_devx_devx; return devx_bdf_devs; } static void mlx5_glue_devx_free_device_list(void *list) { if (!list) { errno = EINVAL; return; } devx_free_device_list(list); } static int mlx5_glue_devx_close_device(void *ctx) { mlx5_context_st *mlx5_ctx; int rc; if (!ctx) return -EINVAL; mlx5_ctx = (mlx5_context_st *)ctx; rc = devx_close_device(mlx5_ctx->devx_ctx); free(mlx5_ctx); return rc; } static void * mlx5_glue_devx_open_device(void *device) { struct mlx5_context *mlx5_ctx; if (!device) { errno = EINVAL; return NULL; } mlx5_ctx = malloc((sizeof(struct mlx5_context))); if (!mlx5_ctx) { errno = ENOMEM; return NULL; } memset(mlx5_ctx, 0, sizeof(*mlx5_ctx)); mlx5_ctx->devx_ctx = devx_open_device(device); if (DEVX_IS_ERR(mlx5_ctx->devx_ctx)) { errno = -DEVX_PTR_ERR(mlx5_ctx->devx_ctx); free(mlx5_ctx); return NULL; } return mlx5_ctx; } static int mlx5_glue_devx_query_device(void *device_bdf, void *dev_inf) { struct devx_device_bdf *dev_bdf; struct devx_device *mlx5_dev; if (!device_bdf) return -EINVAL; dev_bdf = (struct devx_device_bdf *)device_bdf; mlx5_dev = (struct devx_device *)dev_inf; int err = devx_query_device(dev_bdf, mlx5_dev); if (err) return -E_FAIL; return 0; } static void * mlx5_glue_devx_query_hca_iseg_mapping(void *ctx, uint32_t *cb_iseg) { struct mlx5_context *mlx5_ctx; void *pv_iseg; int err; if (!ctx) { errno = EINVAL; return NULL; } mlx5_ctx = (struct mlx5_context *)ctx; err = devx_query_hca_iseg_mapping(mlx5_ctx->devx_ctx, cb_iseg, &pv_iseg); if (err) { errno = err; return NULL; } return pv_iseg; } static void * mlx5_glue_devx_obj_create(void *ctx, void *in, size_t inlen, void *out, size_t outlen) { mlx5_devx_obj_st *devx_obj; if (!ctx) { errno = EINVAL; return NULL; } devx_obj = malloc((sizeof(*devx_obj))); if (!devx_obj) { errno = ENOMEM; return NULL; } memset(devx_obj, 0, sizeof(*devx_obj)); devx_obj->devx_ctx = GET_DEVX_CTX(ctx); devx_obj->obj = devx_obj_create(devx_obj->devx_ctx, in, inlen, out, outlen); if (DEVX_IS_ERR(devx_obj->obj)) { errno = -DEVX_PTR_ERR(devx_obj->obj); free(devx_obj); return NULL; } return devx_obj; } static int mlx5_glue_devx_obj_destroy(void *obj) { mlx5_devx_obj_st *devx_obj; if (!obj) return -EINVAL; devx_obj = obj; int rc = devx_obj_destroy(devx_obj->obj); free(devx_obj); return rc; } static int mlx5_glue_devx_general_cmd(void *ctx, void *in, size_t inlen, void *out, size_t outlen) { if (!ctx) return -EINVAL; return devx_cmd(GET_DEVX_CTX(ctx), in, inlen, out, outlen); } static int mlx5_glue_devx_obj_query(void *obj, void *in, size_t inlen, void *out, size_t outlen) { return devx_cmd(GET_OBJ_CTX(obj), in, inlen, out, outlen); } static int mlx5_glue_devx_obj_modify(void *obj, void *in, size_t inlen, void *out, size_t outlen) { return devx_cmd(GET_OBJ_CTX(obj), in, inlen, out, outlen); } static int mlx5_glue_devx_umem_dereg(void *pumem) { struct devx_obj_handle *umem; if (!pumem) return -EINVAL; umem = pumem; return devx_umem_unreg(umem); } static void * mlx5_glue_devx_umem_reg(void *ctx, void *addr, size_t size, uint32_t access, uint32_t *id) { struct devx_obj_handle *umem_hdl; int w_access = DEVX_UMEM_ACCESS_READ; if (!ctx) { errno = EINVAL; return NULL; } if (access) w_access |= DEVX_UMEM_ACCESS_WRITE; umem_hdl = devx_umem_reg(GET_DEVX_CTX(ctx), addr, size, w_access, id); if (DEVX_IS_ERR(umem_hdl)) { errno = -DEVX_PTR_ERR(umem_hdl); return NULL; } return umem_hdl; } static void * mlx5_glue_devx_alloc_uar(void *ctx, uint32_t flags) { devx_uar_handle *uar; if (!ctx) { errno = EINVAL; return NULL; } uar = devx_alloc_uar(GET_DEVX_CTX(ctx), flags); if (DEVX_IS_ERR(uar)) { errno = -DEVX_PTR_ERR(uar); return NULL; } return uar; } static int mlx5_glue_devx_query_eqn(void *ctx, uint32_t cpus, uint32_t *eqn) { if (!ctx) return -EINVAL; return devx_query_eqn(GET_DEVX_CTX(ctx), cpus, eqn); } static void mlx5_glue_devx_free_uar(void *uar) { devx_free_uar((devx_uar_handle *)uar); } static_assert(MLX5_ST_SZ_BYTES(fte_match_param) == 0x200, "PRM size of fte_match_param is broken! cannot compile Windows!"); static void* mlx5_glue_devx_fs_rule_add(void *ctx, void *in, uint32_t inlen) { struct devx_obj_handle *rule_hdl = NULL; if (!ctx) { errno = EINVAL; return NULL; } rule_hdl = devx_fs_rule_add(GET_DEVX_CTX(ctx), in, inlen); if (DEVX_IS_ERR(rule_hdl)) { errno = -DEVX_PTR_ERR(rule_hdl); return NULL; } return rule_hdl; } static int mlx5_glue_devx_fs_rule_del(void *flow) { return devx_fs_rule_del(flow); } static int mlx5_glue_query_rt_values(void *ctx, void *devx_clock) { struct mlx5_context *mlx5_ctx; struct mlx5_devx_clock *clock; int err; if (!ctx) { errno = EINVAL; return errno; } mlx5_ctx = (struct mlx5_context *)ctx; clock = (struct mlx5_devx_clock *)devx_clock; err = devx_hca_clock_query( mlx5_ctx->devx_ctx, &clock->p_iseg_internal_timer, &clock->clock_frequency_hz, &clock->is_stable_clock_frequency); if (err) { errno = err; return errno; } return 0; } static int mlx5_glue_devx_init_showdown_event(void *ctx) { struct mlx5_context *mlx5_ctx; int err; if (!ctx) { errno = EINVAL; return errno; } mlx5_ctx = (struct mlx5_context *)ctx; err = devx_query_shutdown_event(mlx5_ctx->devx_ctx, &mlx5_ctx->shutdown_event_obj); if (err) { errno = err; return errno; } return 0; } static int mlx5_glue_devx_set_promisc_vport(void *ctx, uint32_t promisc_type, uint8_t f_enable) { #ifdef HAVE_DEVX_SET_PROMISC_SUPPORT int devx_promisc_type = MLX5_DEVX_SET_PROMISC_VPORT_PROMISC_MODE; struct mlx5_context *mlx5_ctx; int err; if (!ctx) { errno = EINVAL; return errno; } mlx5_ctx = (struct mlx5_context *)ctx; if (promisc_type == MC_PROMISC) devx_promisc_type = MLX5_DEVX_SET_PROMISC_VPORT_ALL_MULTICAST; err = devx_set_promisc_vport(mlx5_ctx->devx_ctx, devx_promisc_type, f_enable); if (err) { errno = err; return errno; } return 0; #else (void)promisc_type; (void)f_enable; (void)ctx; DRV_LOG(WARNING, "%s: is not supported", __func__); return -ENOTSUP; #endif } static int mlx5_glue_devx_get_mtu(void *ctx, uint32_t *mtu) { int err = 0; struct mlx5_context *mlx5_ctx; if (!ctx) { errno = EINVAL; return errno; } mlx5_ctx = (struct mlx5_context *)ctx; #ifdef HAVE_DEVX_SET_GET_MTU_SUPPORT err = devx_get_mtu(mlx5_ctx->devx_ctx, mtu); if (err) { errno = err; return errno; } #else *mtu = mlx5_ctx->mlx5_dev.mtu_bytes; #endif return err; } static int mlx5_glue_devx_set_mtu(void *ctx, uint32_t mtu) { #ifdef HAVE_DEVX_SET_GET_MTU_SUPPORT struct mlx5_context *mlx5_ctx; int err; if (!ctx) { errno = EINVAL; return errno; } mlx5_ctx = (struct mlx5_context *)ctx; err = devx_set_mtu(mlx5_ctx->devx_ctx, mtu); if (err) { errno = err; return errno; } return 0; #else (void)mtu; (void)ctx; DRV_LOG(WARNING, "%s: is not supported", __func__); return -ENOTSUP; #endif } alignas(RTE_CACHE_LINE_SIZE) const struct mlx5_glue *mlx5_glue = &(const struct mlx5_glue){ .version = MLX5_GLUE_VERSION, .get_device_list = mlx5_glue_devx_get_device_list, .free_device_list = mlx5_glue_devx_free_device_list, .open_device = mlx5_glue_devx_open_device, .close_device = mlx5_glue_devx_close_device, .query_device = mlx5_glue_devx_query_device, .query_hca_iseg = mlx5_glue_devx_query_hca_iseg_mapping, .devx_obj_create = mlx5_glue_devx_obj_create, .devx_obj_destroy = mlx5_glue_devx_obj_destroy, .devx_obj_query = mlx5_glue_devx_obj_query, .devx_obj_modify = mlx5_glue_devx_obj_modify, .devx_general_cmd = mlx5_glue_devx_general_cmd, .devx_umem_reg = mlx5_glue_devx_umem_reg, .devx_umem_dereg = mlx5_glue_devx_umem_dereg, .devx_alloc_uar = mlx5_glue_devx_alloc_uar, .devx_free_uar = mlx5_glue_devx_free_uar, .devx_fs_rule_add = mlx5_glue_devx_fs_rule_add, .devx_fs_rule_del = mlx5_glue_devx_fs_rule_del, .devx_query_eqn = mlx5_glue_devx_query_eqn, .query_rt_values = mlx5_glue_query_rt_values, .devx_init_showdown_event = mlx5_glue_devx_init_showdown_event, .devx_set_promisc_vport = mlx5_glue_devx_set_promisc_vport, .devx_get_mtu = mlx5_glue_devx_get_mtu, .devx_set_mtu = mlx5_glue_devx_set_mtu, };