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 */ 38 static void * 39 mlx5_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 */ 65 static void 66 mlx5_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 */ 78 void 79 mlx5_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 */ 108 int 109 mlx5_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 */ 137 void 138 mlx5_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 */ 154 void 155 mlx5_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