f-stack/dpdk/drivers/common/mlx5/linux/mlx5_common_verbs.c

160 lines
3.7 KiB
C

/* SPDX-License-Identifier: BSD-3-Clause
* Copyright 2020 Mellanox Technologies, Ltd
*/
#include <stddef.h>
#include <errno.h>
#include <string.h>
#include <stdint.h>
#include <unistd.h>
#include <sys/mman.h>
#include <inttypes.h>
#include <rte_errno.h>
#include <rte_eal_paging.h>
#include "mlx5_common_utils.h"
#include "mlx5_common_log.h"
#include "mlx5_autoconf.h"
#include <mlx5_glue.h>
#include <mlx5_malloc.h>
#include <mlx5_common.h>
#include <mlx5_common_mr.h>
/**
* Verbs callback to allocate a memory. This function should allocate the space
* according to the size provided residing inside a huge page.
* Please note that all allocation must respect the alignment from libmlx5
* (i.e. currently rte_mem_page_size()).
*
* @param[in] size
* The size in bytes of the memory to allocate.
* @param[in] data
* A pointer to the callback data.
*
* @return
* Allocated buffer, NULL otherwise and rte_errno is set.
*/
static void *
mlx5_alloc_verbs_buf(size_t size, void *data)
{
struct rte_device *dev = data;
void *ret;
size_t alignment = rte_mem_page_size();
if (alignment == (size_t)-1) {
DRV_LOG(ERR, "Failed to get mem page size");
rte_errno = ENOMEM;
return NULL;
}
MLX5_ASSERT(data != NULL);
ret = mlx5_malloc(0, size, alignment, dev->numa_node);
if (!ret && size)
rte_errno = ENOMEM;
return ret;
}
/**
* Verbs callback to free a memory.
*
* @param[in] ptr
* A pointer to the memory to free.
* @param[in] data
* A pointer to the callback data.
*/
static void
mlx5_free_verbs_buf(void *ptr, void *data __rte_unused)
{
MLX5_ASSERT(data != NULL);
mlx5_free(ptr);
}
/**
* Hint libmlx5 to use PMD allocator for data plane resources.
*
* @param dev
* Pointer to the generic device.
*/
void
mlx5_set_context_attr(struct rte_device *dev, struct ibv_context *ctx)
{
struct mlx5dv_ctx_allocators allocator = {
.alloc = &mlx5_alloc_verbs_buf,
.free = &mlx5_free_verbs_buf,
.data = dev,
};
/* Hint libmlx5 to use PMD allocator for data plane resources */
mlx5_glue->dv_set_context_attr(ctx, MLX5DV_CTX_ATTR_BUF_ALLOCATORS,
(void *)((uintptr_t)&allocator));
}
/**
* Register mr. Given protection domain pointer, pointer to addr and length
* register the memory region.
*
* @param[in] pd
* Pointer to protection domain context.
* @param[in] addr
* Pointer to memory start address.
* @param[in] length
* Length of the memory to register.
* @param[out] pmd_mr
* pmd_mr struct set with lkey, address, length and pointer to mr object
*
* @return
* 0 on successful registration, -1 otherwise
*/
int
mlx5_common_verbs_reg_mr(void *pd, void *addr, size_t length,
struct mlx5_pmd_mr *pmd_mr)
{
struct ibv_mr *ibv_mr;
ibv_mr = mlx5_glue->reg_mr(pd, addr, length,
IBV_ACCESS_LOCAL_WRITE |
(haswell_broadwell_cpu ? 0 :
IBV_ACCESS_RELAXED_ORDERING));
if (!ibv_mr)
return -1;
*pmd_mr = (struct mlx5_pmd_mr){
.lkey = ibv_mr->lkey,
.addr = ibv_mr->addr,
.len = ibv_mr->length,
.obj = (void *)ibv_mr,
};
return 0;
}
/**
* Deregister mr. Given the mlx5 pmd MR - deregister the MR
*
* @param[in] pmd_mr
* pmd_mr struct set with lkey, address, length and pointer to mr object
*
*/
void
mlx5_common_verbs_dereg_mr(struct mlx5_pmd_mr *pmd_mr)
{
if (pmd_mr && pmd_mr->obj != NULL) {
claim_zero(mlx5_glue->dereg_mr(pmd_mr->obj));
memset(pmd_mr, 0, sizeof(*pmd_mr));
}
}
/**
* Set the reg_mr and dereg_mr callbacks.
*
* @param[out] reg_mr_cb
* Pointer to reg_mr func
* @param[out] dereg_mr_cb
* Pointer to dereg_mr func
*/
void
mlx5_os_set_reg_mr_cb(mlx5_reg_mr_t *reg_mr_cb, mlx5_dereg_mr_t *dereg_mr_cb)
{
*reg_mr_cb = mlx5_common_verbs_reg_mr;
*dereg_mr_cb = mlx5_common_verbs_dereg_mr;
}