dpdk/drivers/common/mlx5/linux/mlx5_common_verbs.c
<<
>>
Prefs
   1/* SPDX-License-Identifier: BSD-3-Clause
   2 * Copyright 2020 Mellanox Technologies, Ltd
   3 */
   4
   5#include <stddef.h>
   6#include <errno.h>
   7#include <string.h>
   8#include <stdint.h>
   9#include <unistd.h>
  10#include <sys/mman.h>
  11#include <inttypes.h>
  12
  13#include <rte_errno.h>
  14#include <rte_eal_paging.h>
  15
  16#include "mlx5_common_utils.h"
  17#include "mlx5_common_log.h"
  18#include "mlx5_autoconf.h"
  19#include <mlx5_glue.h>
  20#include <mlx5_malloc.h>
  21#include <mlx5_common.h>
  22#include <mlx5_common_mr.h>
  23
  24/**
  25 * Verbs callback to allocate a memory. This function should allocate the space
  26 * according to the size provided residing inside a huge page.
  27 * Please note that all allocation must respect the alignment from libmlx5
  28 * (i.e. currently rte_mem_page_size()).
  29 *
  30 * @param[in] size
  31 *   The size in bytes of the memory to allocate.
  32 * @param[in] data
  33 *   A pointer to the callback data.
  34 *
  35 * @return
  36 *   Allocated buffer, NULL otherwise and rte_errno is set.
  37 */
  38static void *
  39mlx5_alloc_verbs_buf(size_t size, void *data)
  40{
  41        struct rte_device *dev = data;
  42        void *ret;
  43        size_t alignment = rte_mem_page_size();
  44        if (alignment == (size_t)-1) {
  45                DRV_LOG(ERR, "Failed to get mem page size");
  46                rte_errno = ENOMEM;
  47                return NULL;
  48        }
  49
  50        MLX5_ASSERT(data != NULL);
  51        ret = mlx5_malloc(0, size, alignment, dev->numa_node);
  52        if (!ret && size)
  53                rte_errno = ENOMEM;
  54        return ret;
  55}
  56
  57/**
  58 * Verbs callback to free a memory.
  59 *
  60 * @param[in] ptr
  61 *   A pointer to the memory to free.
  62 * @param[in] data
  63 *   A pointer to the callback data.
  64 */
  65static void
  66mlx5_free_verbs_buf(void *ptr, void *data __rte_unused)
  67{
  68        MLX5_ASSERT(data != NULL);
  69        mlx5_free(ptr);
  70}
  71
  72/**
  73 * Hint libmlx5 to use PMD allocator for data plane resources.
  74 *
  75 * @param dev
  76 *   Pointer to the generic device.
  77 */
  78void
  79mlx5_set_context_attr(struct rte_device *dev, struct ibv_context *ctx)
  80{
  81        struct mlx5dv_ctx_allocators allocator = {
  82                .alloc = &mlx5_alloc_verbs_buf,
  83                .free = &mlx5_free_verbs_buf,
  84                .data = dev,
  85        };
  86
  87        /* Hint libmlx5 to use PMD allocator for data plane resources */
  88        mlx5_glue->dv_set_context_attr(ctx, MLX5DV_CTX_ATTR_BUF_ALLOCATORS,
  89                                       (void *)((uintptr_t)&allocator));
  90}
  91
  92/**
  93 * Register mr. Given protection domain pointer, pointer to addr and length
  94 * register the memory region.
  95 *
  96 * @param[in] pd
  97 *   Pointer to protection domain context.
  98 * @param[in] addr
  99 *   Pointer to memory start address.
 100 * @param[in] length
 101 *   Length of the memory to register.
 102 * @param[out] pmd_mr
 103 *   pmd_mr struct set with lkey, address, length and pointer to mr object
 104 *
 105 * @return
 106 *   0 on successful registration, -1 otherwise
 107 */
 108int
 109mlx5_common_verbs_reg_mr(void *pd, void *addr, size_t length,
 110                         struct mlx5_pmd_mr *pmd_mr)
 111{
 112        struct ibv_mr *ibv_mr;
 113
 114        ibv_mr = mlx5_glue->reg_mr(pd, addr, length,
 115                                   IBV_ACCESS_LOCAL_WRITE |
 116                                   (haswell_broadwell_cpu ? 0 :
 117                                   IBV_ACCESS_RELAXED_ORDERING));
 118        if (!ibv_mr)
 119                return -1;
 120
 121        *pmd_mr = (struct mlx5_pmd_mr){
 122                .lkey = ibv_mr->lkey,
 123                .addr = ibv_mr->addr,
 124                .len = ibv_mr->length,
 125                .obj = (void *)ibv_mr,
 126        };
 127        return 0;
 128}
 129
 130/**
 131 * Deregister mr. Given the mlx5 pmd MR - deregister the MR
 132 *
 133 * @param[in] pmd_mr
 134 *   pmd_mr struct set with lkey, address, length and pointer to mr object
 135 *
 136 */
 137void
 138mlx5_common_verbs_dereg_mr(struct mlx5_pmd_mr *pmd_mr)
 139{
 140        if (pmd_mr && pmd_mr->obj != NULL) {
 141                claim_zero(mlx5_glue->dereg_mr(pmd_mr->obj));
 142                memset(pmd_mr, 0, sizeof(*pmd_mr));
 143        }
 144}
 145
 146/**
 147 * Set the reg_mr and dereg_mr callbacks.
 148 *
 149 * @param[out] reg_mr_cb
 150 *   Pointer to reg_mr func
 151 * @param[out] dereg_mr_cb
 152 *   Pointer to dereg_mr func
 153 */
 154void
 155mlx5_os_set_reg_mr_cb(mlx5_reg_mr_t *reg_mr_cb, mlx5_dereg_mr_t *dereg_mr_cb)
 156{
 157        *reg_mr_cb = mlx5_common_verbs_reg_mr;
 158        *dereg_mr_cb = mlx5_common_verbs_dereg_mr;
 159}
 160