1 /* SPDX-License-Identifier: BSD-3-Clause
2 * Copyright 2020 Mellanox Technologies, Ltd
9 #include <rte_mempool.h>
10 #include <rte_bus_pci.h>
11 #include <rte_malloc.h>
12 #include <rte_errno.h>
14 #include "mlx5_devx_cmds.h"
15 #include "../mlx5_common_log.h"
16 #include "mlx5_common.h"
17 #include "mlx5_common_os.h"
18 #include "mlx5_malloc.h"
21 * Initialization routine for run-time dependency on external lib.
24 mlx5_glue_constructor(void)
29 * Release PD. Releases a given mlx5_pd object
35 * Zero if pd is released successfully, negative number otherwise.
38 mlx5_os_dealloc_pd(void *pd)
42 mlx5_devx_cmd_destroy(((struct mlx5_pd *)pd)->obj);
48 * Allocate Protection Domain object and extract its pdn using DV API.
51 * Pointer to the mlx5 device.
54 * 0 on success, a negative value otherwise.
57 mlx5_os_pd_create(struct mlx5_common_device *cdev)
61 pd = mlx5_malloc(MLX5_MEM_ZERO, sizeof(*pd), 0, SOCKET_ID_ANY);
64 struct mlx5_devx_obj *obj = mlx5_devx_cmd_alloc_pd(cdev->ctx);
71 pd->devx_ctx = cdev->ctx;
78 * Detect if a devx_device_bdf object has identical DBDF values to the
79 * rte_pci_addr found in bus/pci probing.
82 * Pointer to the devx_device_bdf structure.
84 * Pointer to the rte_pci_addr structure.
87 * 1 on Device match, 0 on mismatch.
90 mlx5_match_devx_bdf_to_addr(struct devx_device_bdf *devx_bdf,
91 struct rte_pci_addr *addr)
93 if (addr->domain != (devx_bdf->bus_id >> 8) ||
94 addr->bus != (devx_bdf->bus_id & 0xff) ||
95 addr->devid != devx_bdf->dev_id ||
96 addr->function != devx_bdf->fnc_id) {
103 * Detect if a devx_device_bdf object matches the rte_pci_addr
104 * found in bus/pci probing
105 * Compare both the Native/PF BDF and the raw_bdf representing a VF BDF.
107 * @param[in] devx_bdf
108 * Pointer to the devx_device_bdf structure.
110 * Pointer to the rte_pci_addr structure.
113 * 1 on Device match, 0 on mismatch, rte_errno code on failure.
116 mlx5_match_devx_devices_to_addr(struct devx_device_bdf *devx_bdf,
117 struct rte_pci_addr *addr)
120 struct devx_device mlx5_dev;
122 if (mlx5_match_devx_bdf_to_addr(devx_bdf, addr))
125 * Didn't match on Native/PF BDF, could still match a VF BDF,
128 err = mlx5_glue->query_device(devx_bdf, &mlx5_dev);
130 DRV_LOG(ERR, "query_device failed");
134 if (mlx5_match_devx_bdf_to_addr(&mlx5_dev.raw_bdf, addr))
140 * Look for DevX device that match to given rte_device.
143 * Pointer to the generic device.
145 * Pointer to head of DevX devices list.
147 * Number of devices in given DevX devices list.
150 * A device match on success, NULL otherwise and rte_errno is set.
152 static struct devx_device_bdf *
153 mlx5_os_get_devx_device(struct rte_device *dev,
154 struct devx_device_bdf *devx_list, int n)
156 struct devx_device_bdf *devx_match = NULL;
157 struct rte_pci_device *pci_dev = RTE_DEV_TO_PCI(dev);
158 struct rte_pci_addr *addr = &pci_dev->addr;
161 int ret = mlx5_match_devx_devices_to_addr(devx_list, addr);
170 devx_match = devx_list;
173 if (devx_match == NULL) {
174 /* No device matches, just complain and bail out. */
176 "No DevX device matches PCI device " PCI_PRI_FMT ","
177 " is DevX Configured?",
178 addr->domain, addr->bus, addr->devid, addr->function);
185 * Function API open device under Windows.
187 * This function calls the Windows glue APIs to open a device.
190 * Pointer to mlx5 device structure.
192 * Chosen classes come from user device arguments.
195 * 0 on success, a negative errno value otherwise and rte_errno is set.
198 mlx5_os_open_device(struct mlx5_common_device *cdev, uint32_t classes)
200 struct devx_device_bdf *devx_bdf_dev = NULL;
201 struct devx_device_bdf *devx_list;
202 struct mlx5_context *mlx5_ctx = NULL;
205 if (classes != MLX5_CLASS_ETH && classes != MLX5_CLASS_CRYPTO) {
207 "The chosen classes are not supported on Windows.");
212 devx_list = mlx5_glue->get_device_list(&n);
213 if (devx_list == NULL) {
214 rte_errno = errno ? errno : ENOSYS;
215 DRV_LOG(ERR, "Cannot list devices, is DevX enabled?");
218 devx_bdf_dev = mlx5_os_get_devx_device(cdev->dev, devx_list, n);
219 if (devx_bdf_dev == NULL)
221 /* Try to open DevX device with DV. */
222 mlx5_ctx = mlx5_glue->open_device(devx_bdf_dev);
223 if (mlx5_ctx == NULL) {
224 DRV_LOG(ERR, "Failed to open DevX device.");
228 if (mlx5_glue->query_device(devx_bdf_dev, &mlx5_ctx->mlx5_dev)) {
229 DRV_LOG(ERR, "Failed to query device context fields.");
233 cdev->config.devx = 1;
234 cdev->ctx = mlx5_ctx;
235 mlx5_glue->free_device_list(devx_list);
238 if (mlx5_ctx != NULL)
239 claim_zero(mlx5_glue->close_device(mlx5_ctx));
240 mlx5_glue->free_device_list(devx_list);
248 * Pointer to context.
250 * Pointer to memory start address.
252 * Size of the memory to register.
257 * umem on successful registration, NULL and errno otherwise
260 mlx5_os_umem_reg(void *ctx, void *addr, size_t size, uint32_t access)
262 struct mlx5_devx_umem *umem;
264 umem = mlx5_malloc(MLX5_MEM_ZERO,
265 (sizeof(*umem)), 0, SOCKET_ID_ANY);
270 umem->umem_hdl = mlx5_glue->devx_umem_reg(ctx, addr, size, access,
272 if (!umem->umem_hdl) {
287 * 0 on successful release, negative number otherwise
290 mlx5_os_umem_dereg(void *pumem)
292 struct mlx5_devx_umem *umem;
299 err = mlx5_glue->devx_umem_dereg(umem->umem_hdl);
305 * Register mr. Given protection doamin pointer, pointer to addr and length
306 * register the memory region.
309 * Pointer to protection domain context (type mlx5_pd).
311 * Pointer to memory start address (type devx_device_ctx).
313 * Lengtoh of the memory to register.
315 * pmd_mr struct set with lkey, address, length, pointer to mr object, mkey
318 * 0 on successful registration, -1 otherwise
321 mlx5_os_reg_mr(void *pd,
322 void *addr, size_t length, struct mlx5_pmd_mr *pmd_mr)
324 struct mlx5_devx_mkey_attr mkey_attr;
325 struct mlx5_pd *mlx5_pd = (struct mlx5_pd *)pd;
326 struct mlx5_hca_attr attr;
327 struct mlx5_devx_obj *mkey;
334 if (mlx5_devx_cmd_query_hca_attr(mlx5_pd->devx_ctx, &attr))
336 obj = mlx5_os_umem_reg(mlx5_pd->devx_ctx, addr, length,
337 IBV_ACCESS_LOCAL_WRITE);
340 memset(&mkey_attr, 0, sizeof(mkey_attr));
341 mkey_attr.addr = (uintptr_t)addr;
342 mkey_attr.size = length;
343 mkey_attr.umem_id = ((struct mlx5_devx_umem *)(obj))->umem_id;
344 mkey_attr.pd = mlx5_pd->pdn;
345 if (!haswell_broadwell_cpu) {
346 mkey_attr.relaxed_ordering_write = attr.relaxed_ordering_write;
347 mkey_attr.relaxed_ordering_read = attr.relaxed_ordering_read;
349 mkey = mlx5_devx_cmd_mkey_create(mlx5_pd->devx_ctx, &mkey_attr);
351 claim_zero(mlx5_os_umem_dereg(obj));
355 pmd_mr->len = length;
358 pmd_mr->lkey = pmd_mr->mkey->id;
366 * Pointer to PMD mr object
369 mlx5_os_dereg_mr(struct mlx5_pmd_mr *pmd_mr)
371 if (pmd_mr && pmd_mr->mkey)
372 claim_zero(mlx5_glue->devx_obj_destroy(pmd_mr->mkey->obj));
373 if (pmd_mr && pmd_mr->obj)
374 claim_zero(mlx5_os_umem_dereg(pmd_mr->obj));
375 memset(pmd_mr, 0, sizeof(*pmd_mr));
379 * Set the reg_mr and dereg_mr callbacks.
381 * @param[out] reg_mr_cb
382 * Pointer to reg_mr func
383 * @param[out] dereg_mr_cb
384 * Pointer to dereg_mr func
388 mlx5_os_set_reg_mr_cb(mlx5_reg_mr_t *reg_mr_cb, mlx5_dereg_mr_t *dereg_mr_cb)
390 *reg_mr_cb = mlx5_os_reg_mr;
391 *dereg_mr_cb = mlx5_os_dereg_mr;