xref: /dpdk/drivers/common/mlx5/mlx5_common_mp.c (revision 08ac03580ef29aef529d6fd1633a9052c6ceaacc)
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
mlx5_mp_req_mr_create(struct mlx5_common_device * cdev,uintptr_t addr)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
mlx5_mp_req_mempool_reg(struct mlx5_common_device * cdev,struct rte_mempool * mempool,bool reg,bool is_extmem)67 mlx5_mp_req_mempool_reg(struct mlx5_common_device *cdev,
68 			struct rte_mempool *mempool, bool reg,
69 			bool is_extmem)
70 {
71 	struct rte_mp_msg mp_req;
72 	struct rte_mp_msg *mp_res;
73 	struct rte_mp_reply mp_rep;
74 	struct mlx5_mp_param *req = (struct mlx5_mp_param *)mp_req.param;
75 	struct mlx5_mp_arg_mr_manage *arg = &req->args.mr_manage;
76 	struct mlx5_mp_param *res;
77 	struct timespec ts = {.tv_sec = MLX5_MP_REQ_TIMEOUT_SEC, .tv_nsec = 0};
78 	enum mlx5_mp_req_type type;
79 	int ret;
80 
81 	MLX5_ASSERT(rte_eal_process_type() == RTE_PROC_SECONDARY);
82 	type = reg ? MLX5_MP_REQ_MEMPOOL_REGISTER :
83 		     MLX5_MP_REQ_MEMPOOL_UNREGISTER;
84 	mp_init_port_agnostic_msg(&mp_req, type);
85 	arg->mempool = mempool;
86 	arg->is_extmem = is_extmem;
87 	arg->cdev = cdev;
88 	ret = rte_mp_request_sync(&mp_req, &mp_rep, &ts);
89 	if (ret) {
90 		DRV_LOG(ERR,
91 			"Mempool %sregister request to primary process failed.",
92 			reg ? "" : "un");
93 		return -rte_errno;
94 	}
95 	MLX5_ASSERT(mp_rep.nb_received == 1);
96 	mp_res = &mp_rep.msgs[0];
97 	res = (struct mlx5_mp_param *)mp_res->param;
98 	ret = res->result;
99 	if (ret)
100 		rte_errno = -ret;
101 	mlx5_free(mp_rep.msgs);
102 	return ret;
103 }
104 
105 /**
106  * Request Verbs queue state modification to the primary process.
107  *
108  * @param[in] mp_id
109  *   ID of the MP process.
110  * @param sm
111  *   State modify parameters.
112  *
113  * @return
114  *   0 on success, a negative errno value otherwise and rte_errno is set.
115  */
116 int
mlx5_mp_req_queue_state_modify(struct mlx5_mp_id * mp_id,struct mlx5_mp_arg_queue_state_modify * sm)117 mlx5_mp_req_queue_state_modify(struct mlx5_mp_id *mp_id,
118 			       struct mlx5_mp_arg_queue_state_modify *sm)
119 {
120 	struct rte_mp_msg mp_req;
121 	struct rte_mp_msg *mp_res;
122 	struct rte_mp_reply mp_rep;
123 	struct mlx5_mp_param *req = (struct mlx5_mp_param *)mp_req.param;
124 	struct mlx5_mp_param *res;
125 	struct timespec ts = {.tv_sec = MLX5_MP_REQ_TIMEOUT_SEC, .tv_nsec = 0};
126 	int ret;
127 
128 	MLX5_ASSERT(rte_eal_process_type() == RTE_PROC_SECONDARY);
129 	mp_init_msg(mp_id, &mp_req, MLX5_MP_REQ_QUEUE_STATE_MODIFY);
130 	req->args.state_modify = *sm;
131 	ret = rte_mp_request_sync(&mp_req, &mp_rep, &ts);
132 	if (ret) {
133 		DRV_LOG(ERR, "port %u request to primary process failed",
134 			mp_id->port_id);
135 		return -rte_errno;
136 	}
137 	MLX5_ASSERT(mp_rep.nb_received == 1);
138 	mp_res = &mp_rep.msgs[0];
139 	res = (struct mlx5_mp_param *)mp_res->param;
140 	ret = res->result;
141 	mlx5_free(mp_rep.msgs);
142 	return ret;
143 }
144 
145 /**
146  * Request Verbs command file descriptor for mmap to the primary process.
147  *
148  * @param[in] mp_id
149  *   ID of the MP process.
150  *
151  * @return
152  *   fd on success, a negative errno value otherwise and rte_errno is set.
153  */
154 int
mlx5_mp_req_verbs_cmd_fd(struct mlx5_mp_id * mp_id)155 mlx5_mp_req_verbs_cmd_fd(struct mlx5_mp_id *mp_id)
156 {
157 	struct rte_mp_msg mp_req;
158 	struct rte_mp_msg *mp_res;
159 	struct rte_mp_reply mp_rep;
160 	struct mlx5_mp_param *res;
161 	struct timespec ts = {.tv_sec = MLX5_MP_REQ_TIMEOUT_SEC, .tv_nsec = 0};
162 	int ret;
163 
164 	MLX5_ASSERT(rte_eal_process_type() == RTE_PROC_SECONDARY);
165 	mp_init_msg(mp_id, &mp_req, MLX5_MP_REQ_VERBS_CMD_FD);
166 	ret = rte_mp_request_sync(&mp_req, &mp_rep, &ts);
167 	if (ret) {
168 		DRV_LOG(ERR, "port %u request to primary process failed",
169 			mp_id->port_id);
170 		return -rte_errno;
171 	}
172 	MLX5_ASSERT(mp_rep.nb_received == 1);
173 	mp_res = &mp_rep.msgs[0];
174 	res = (struct mlx5_mp_param *)mp_res->param;
175 	if (res->result) {
176 		rte_errno = -res->result;
177 		DRV_LOG(ERR,
178 			"port %u failed to get command FD from primary process",
179 			mp_id->port_id);
180 		ret = -rte_errno;
181 		goto exit;
182 	}
183 	MLX5_ASSERT(mp_res->num_fds == 1);
184 	ret = mp_res->fds[0];
185 	DRV_LOG(DEBUG, "port %u command FD from primary is %d",
186 		mp_id->port_id, ret);
187 exit:
188 	mlx5_free(mp_rep.msgs);
189 	return ret;
190 }
191 
192 /**
193  * Initialize by primary process.
194  */
195 int
mlx5_mp_init_primary(const char * name,const rte_mp_t primary_action)196 mlx5_mp_init_primary(const char *name, const rte_mp_t primary_action)
197 {
198 	int ret;
199 
200 	MLX5_ASSERT(rte_eal_process_type() == RTE_PROC_PRIMARY);
201 
202 	/* primary is allowed to not support IPC */
203 	ret = rte_mp_action_register(name, primary_action);
204 	if (ret && rte_errno != ENOTSUP)
205 		return -1;
206 	return 0;
207 }
208 
209 /**
210  * Un-initialize by primary process.
211  */
212 void
mlx5_mp_uninit_primary(const char * name)213 mlx5_mp_uninit_primary(const char *name)
214 {
215 	MLX5_ASSERT(rte_eal_process_type() == RTE_PROC_PRIMARY);
216 	rte_mp_action_unregister(name);
217 }
218 
219 /**
220  * Initialize by secondary process.
221  */
222 int
mlx5_mp_init_secondary(const char * name,const rte_mp_t secondary_action)223 mlx5_mp_init_secondary(const char *name, const rte_mp_t secondary_action)
224 {
225 	MLX5_ASSERT(rte_eal_process_type() == RTE_PROC_SECONDARY);
226 	return rte_mp_action_register(name, secondary_action);
227 }
228 
229 /**
230  * Un-initialize by secondary process.
231  */
232 void
mlx5_mp_uninit_secondary(const char * name)233 mlx5_mp_uninit_secondary(const char *name)
234 {
235 	MLX5_ASSERT(rte_eal_process_type() == RTE_PROC_SECONDARY);
236 	rte_mp_action_unregister(name);
237 }
238