xref: /dpdk/drivers/common/mlx5/linux/mlx5_common_verbs.c (revision 5fbc75ace1f83b3616a3614fdcb27ca70db063c0)
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 *
mlx5_alloc_verbs_buf(size_t size,void * data)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
mlx5_free_verbs_buf(void * ptr,void * data __rte_unused)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
mlx5_set_context_attr(struct rte_device * dev,struct ibv_context * ctx)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
mlx5_common_verbs_reg_mr(void * pd,void * addr,size_t length,struct mlx5_pmd_mr * pmd_mr)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
mlx5_common_verbs_dereg_mr(struct mlx5_pmd_mr * pmd_mr)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
mlx5_os_set_reg_mr_cb(mlx5_reg_mr_t * reg_mr_cb,mlx5_dereg_mr_t * dereg_mr_cb)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