xref: /dpdk/drivers/common/mlx5/mlx5_common_mp.c (revision 2490bb897182f57de80fd924dd3ae48dda819b8c)
1 /* SPDX-License-Identifier: BSD-3-Clause
2  * Copyright 2019 6WIND S.A.
3  * Copyright 2019 Mellanox Technologies, Ltd
4  */
5 
6 #include <stdio.h>
7 #include <time.h>
8 
9 #include <rte_eal.h>
10 #include <rte_errno.h>
11 
12 #include "mlx5_common_mp.h"
13 #include "mlx5_common_log.h"
14 #include "mlx5_malloc.h"
15 
16 /**
17  * Request Memory Region creation to the primary process.
18  *
19  * @param cdev
20  *   Pointer to the mlx5 common device.
21  * @param addr
22  *   Target virtual address to register.
23  *
24  * @return
25  *   0 on success, a negative errno value otherwise and rte_errno is set.
26  */
27 int
28 mlx5_mp_req_mr_create(struct mlx5_common_device *cdev, uintptr_t addr)
29 {
30 	struct rte_mp_msg mp_req;
31 	struct rte_mp_msg *mp_res;
32 	struct rte_mp_reply mp_rep;
33 	struct mlx5_mp_param *req = (struct mlx5_mp_param *)mp_req.param;
34 	struct mlx5_mp_arg_mr_manage *arg = &req->args.mr_manage;
35 	struct mlx5_mp_param *res;
36 	struct timespec ts = {.tv_sec = MLX5_MP_REQ_TIMEOUT_SEC, .tv_nsec = 0};
37 	int ret;
38 
39 	MLX5_ASSERT(rte_eal_process_type() == RTE_PROC_SECONDARY);
40 	mp_init_port_agnostic_msg(&mp_req, MLX5_MP_REQ_CREATE_MR);
41 	arg->addr = addr;
42 	arg->cdev = cdev;
43 	ret = rte_mp_request_sync(&mp_req, &mp_rep, &ts);
44 	if (ret) {
45 		DRV_LOG(ERR, "Create MR request to primary process failed.");
46 		return -rte_errno;
47 	}
48 	MLX5_ASSERT(mp_rep.nb_received == 1);
49 	mp_res = &mp_rep.msgs[0];
50 	res = (struct mlx5_mp_param *)mp_res->param;
51 	ret = res->result;
52 	if (ret)
53 		rte_errno = -ret;
54 	mlx5_free(mp_rep.msgs);
55 	return ret;
56 }
57 
58 /**
59  * @param cdev
60  *   Pointer to the mlx5 common device.
61  * @param mempool
62  *   Mempool to register or unregister.
63  * @param reg
64  *   True to register the mempool, False to unregister.
65  */
66 int
67 mlx5_mp_req_mempool_reg(struct mlx5_common_device *cdev,
68 			struct rte_mempool *mempool, bool reg)
69 {
70 	struct rte_mp_msg mp_req;
71 	struct rte_mp_msg *mp_res;
72 	struct rte_mp_reply mp_rep;
73 	struct mlx5_mp_param *req = (struct mlx5_mp_param *)mp_req.param;
74 	struct mlx5_mp_arg_mr_manage *arg = &req->args.mr_manage;
75 	struct mlx5_mp_param *res;
76 	struct timespec ts = {.tv_sec = MLX5_MP_REQ_TIMEOUT_SEC, .tv_nsec = 0};
77 	enum mlx5_mp_req_type type;
78 	int ret;
79 
80 	MLX5_ASSERT(rte_eal_process_type() == RTE_PROC_SECONDARY);
81 	type = reg ? MLX5_MP_REQ_MEMPOOL_REGISTER :
82 		     MLX5_MP_REQ_MEMPOOL_UNREGISTER;
83 	mp_init_port_agnostic_msg(&mp_req, type);
84 	arg->mempool = mempool;
85 	arg->cdev = cdev;
86 	ret = rte_mp_request_sync(&mp_req, &mp_rep, &ts);
87 	if (ret) {
88 		DRV_LOG(ERR,
89 			"Mempool %sregister request to primary process failed.",
90 			reg ? "" : "un");
91 		return -rte_errno;
92 	}
93 	MLX5_ASSERT(mp_rep.nb_received == 1);
94 	mp_res = &mp_rep.msgs[0];
95 	res = (struct mlx5_mp_param *)mp_res->param;
96 	ret = res->result;
97 	if (ret)
98 		rte_errno = -ret;
99 	mlx5_free(mp_rep.msgs);
100 	return ret;
101 }
102 
103 /**
104  * Request Verbs queue state modification to the primary process.
105  *
106  * @param[in] mp_id
107  *   ID of the MP process.
108  * @param sm
109  *   State modify parameters.
110  *
111  * @return
112  *   0 on success, a negative errno value otherwise and rte_errno is set.
113  */
114 int
115 mlx5_mp_req_queue_state_modify(struct mlx5_mp_id *mp_id,
116 			       struct mlx5_mp_arg_queue_state_modify *sm)
117 {
118 	struct rte_mp_msg mp_req;
119 	struct rte_mp_msg *mp_res;
120 	struct rte_mp_reply mp_rep;
121 	struct mlx5_mp_param *req = (struct mlx5_mp_param *)mp_req.param;
122 	struct mlx5_mp_param *res;
123 	struct timespec ts = {.tv_sec = MLX5_MP_REQ_TIMEOUT_SEC, .tv_nsec = 0};
124 	int ret;
125 
126 	MLX5_ASSERT(rte_eal_process_type() == RTE_PROC_SECONDARY);
127 	mp_init_msg(mp_id, &mp_req, MLX5_MP_REQ_QUEUE_STATE_MODIFY);
128 	req->args.state_modify = *sm;
129 	ret = rte_mp_request_sync(&mp_req, &mp_rep, &ts);
130 	if (ret) {
131 		DRV_LOG(ERR, "port %u request to primary process failed",
132 			mp_id->port_id);
133 		return -rte_errno;
134 	}
135 	MLX5_ASSERT(mp_rep.nb_received == 1);
136 	mp_res = &mp_rep.msgs[0];
137 	res = (struct mlx5_mp_param *)mp_res->param;
138 	ret = res->result;
139 	mlx5_free(mp_rep.msgs);
140 	return ret;
141 }
142 
143 /**
144  * Request Verbs command file descriptor for mmap to the primary process.
145  *
146  * @param[in] mp_id
147  *   ID of the MP process.
148  *
149  * @return
150  *   fd on success, a negative errno value otherwise and rte_errno is set.
151  */
152 int
153 mlx5_mp_req_verbs_cmd_fd(struct mlx5_mp_id *mp_id)
154 {
155 	struct rte_mp_msg mp_req;
156 	struct rte_mp_msg *mp_res;
157 	struct rte_mp_reply mp_rep;
158 	struct mlx5_mp_param *res;
159 	struct timespec ts = {.tv_sec = MLX5_MP_REQ_TIMEOUT_SEC, .tv_nsec = 0};
160 	int ret;
161 
162 	MLX5_ASSERT(rte_eal_process_type() == RTE_PROC_SECONDARY);
163 	mp_init_msg(mp_id, &mp_req, MLX5_MP_REQ_VERBS_CMD_FD);
164 	ret = rte_mp_request_sync(&mp_req, &mp_rep, &ts);
165 	if (ret) {
166 		DRV_LOG(ERR, "port %u request to primary process failed",
167 			mp_id->port_id);
168 		return -rte_errno;
169 	}
170 	MLX5_ASSERT(mp_rep.nb_received == 1);
171 	mp_res = &mp_rep.msgs[0];
172 	res = (struct mlx5_mp_param *)mp_res->param;
173 	if (res->result) {
174 		rte_errno = -res->result;
175 		DRV_LOG(ERR,
176 			"port %u failed to get command FD from primary process",
177 			mp_id->port_id);
178 		ret = -rte_errno;
179 		goto exit;
180 	}
181 	MLX5_ASSERT(mp_res->num_fds == 1);
182 	ret = mp_res->fds[0];
183 	DRV_LOG(DEBUG, "port %u command FD from primary is %d",
184 		mp_id->port_id, ret);
185 exit:
186 	mlx5_free(mp_rep.msgs);
187 	return ret;
188 }
189 
190 /**
191  * Initialize by primary process.
192  */
193 int
194 mlx5_mp_init_primary(const char *name, const rte_mp_t primary_action)
195 {
196 	int ret;
197 
198 	MLX5_ASSERT(rte_eal_process_type() == RTE_PROC_PRIMARY);
199 
200 	/* primary is allowed to not support IPC */
201 	ret = rte_mp_action_register(name, primary_action);
202 	if (ret && rte_errno != ENOTSUP)
203 		return -1;
204 	return 0;
205 }
206 
207 /**
208  * Un-initialize by primary process.
209  */
210 void
211 mlx5_mp_uninit_primary(const char *name)
212 {
213 	MLX5_ASSERT(rte_eal_process_type() == RTE_PROC_PRIMARY);
214 	rte_mp_action_unregister(name);
215 }
216 
217 /**
218  * Initialize by secondary process.
219  */
220 int
221 mlx5_mp_init_secondary(const char *name, const rte_mp_t secondary_action)
222 {
223 	MLX5_ASSERT(rte_eal_process_type() == RTE_PROC_SECONDARY);
224 	return rte_mp_action_register(name, secondary_action);
225 }
226 
227 /**
228  * Un-initialize by secondary process.
229  */
230 void
231 mlx5_mp_uninit_secondary(const char *name)
232 {
233 	MLX5_ASSERT(rte_eal_process_type() == RTE_PROC_SECONDARY);
234 	rte_mp_action_unregister(name);
235 }
236