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