xref: /dpdk/drivers/common/mlx5/linux/mlx5_common_verbs.c (revision 887183effa2aeef70508b37fe304a3f7c526d334)
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