xref: /dpdk/drivers/common/mlx5/mlx5_common_mp.c (revision 10b71caecbe1cddcbb65c050ca775fba575e88db)
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_utils.h"
14 #include "mlx5_malloc.h"
15 
16 /**
17  * Request Memory Region creation to the primary process.
18  *
19  * @param[in] mp_id
20  *   ID of the MP process.
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_mp_id *mp_id, 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_param *res;
35 	struct timespec ts = {.tv_sec = MLX5_MP_REQ_TIMEOUT_SEC, .tv_nsec = 0};
36 	int ret;
37 
38 	MLX5_ASSERT(rte_eal_process_type() == RTE_PROC_SECONDARY);
39 	mp_init_msg(mp_id, &mp_req, MLX5_MP_REQ_CREATE_MR);
40 	req->args.addr = addr;
41 	ret = rte_mp_request_sync(&mp_req, &mp_rep, &ts);
42 	if (ret) {
43 		DRV_LOG(ERR, "port %u request to primary process failed",
44 			mp_id->port_id);
45 		return -rte_errno;
46 	}
47 	MLX5_ASSERT(mp_rep.nb_received == 1);
48 	mp_res = &mp_rep.msgs[0];
49 	res = (struct mlx5_mp_param *)mp_res->param;
50 	ret = res->result;
51 	if (ret)
52 		rte_errno = -ret;
53 	mlx5_free(mp_rep.msgs);
54 	return ret;
55 }
56 
57 /**
58  * Request Verbs queue state modification to the primary process.
59  *
60  * @param[in] mp_id
61  *   ID of the MP process.
62  * @param sm
63  *   State modify parameters.
64  *
65  * @return
66  *   0 on success, a negative errno value otherwise and rte_errno is set.
67  */
68 int
69 mlx5_mp_req_queue_state_modify(struct mlx5_mp_id *mp_id,
70 			       struct mlx5_mp_arg_queue_state_modify *sm)
71 {
72 	struct rte_mp_msg mp_req;
73 	struct rte_mp_msg *mp_res;
74 	struct rte_mp_reply mp_rep;
75 	struct mlx5_mp_param *req = (struct mlx5_mp_param *)mp_req.param;
76 	struct mlx5_mp_param *res;
77 	struct timespec ts = {.tv_sec = MLX5_MP_REQ_TIMEOUT_SEC, .tv_nsec = 0};
78 	int ret;
79 
80 	MLX5_ASSERT(rte_eal_process_type() == RTE_PROC_SECONDARY);
81 	mp_init_msg(mp_id, &mp_req, MLX5_MP_REQ_QUEUE_STATE_MODIFY);
82 	req->args.state_modify = *sm;
83 	ret = rte_mp_request_sync(&mp_req, &mp_rep, &ts);
84 	if (ret) {
85 		DRV_LOG(ERR, "port %u request to primary process failed",
86 			mp_id->port_id);
87 		return -rte_errno;
88 	}
89 	MLX5_ASSERT(mp_rep.nb_received == 1);
90 	mp_res = &mp_rep.msgs[0];
91 	res = (struct mlx5_mp_param *)mp_res->param;
92 	ret = res->result;
93 	mlx5_free(mp_rep.msgs);
94 	return ret;
95 }
96 
97 /**
98  * Request Verbs command file descriptor for mmap to the primary process.
99  *
100  * @param[in] mp_id
101  *   ID of the MP process.
102  *
103  * @return
104  *   fd on success, a negative errno value otherwise and rte_errno is set.
105  */
106 int
107 mlx5_mp_req_verbs_cmd_fd(struct mlx5_mp_id *mp_id)
108 {
109 	struct rte_mp_msg mp_req;
110 	struct rte_mp_msg *mp_res;
111 	struct rte_mp_reply mp_rep;
112 	struct mlx5_mp_param *res;
113 	struct timespec ts = {.tv_sec = MLX5_MP_REQ_TIMEOUT_SEC, .tv_nsec = 0};
114 	int ret;
115 
116 	MLX5_ASSERT(rte_eal_process_type() == RTE_PROC_SECONDARY);
117 	mp_init_msg(mp_id, &mp_req, MLX5_MP_REQ_VERBS_CMD_FD);
118 	ret = rte_mp_request_sync(&mp_req, &mp_rep, &ts);
119 	if (ret) {
120 		DRV_LOG(ERR, "port %u request to primary process failed",
121 			mp_id->port_id);
122 		return -rte_errno;
123 	}
124 	MLX5_ASSERT(mp_rep.nb_received == 1);
125 	mp_res = &mp_rep.msgs[0];
126 	res = (struct mlx5_mp_param *)mp_res->param;
127 	if (res->result) {
128 		rte_errno = -res->result;
129 		DRV_LOG(ERR,
130 			"port %u failed to get command FD from primary process",
131 			mp_id->port_id);
132 		ret = -rte_errno;
133 		goto exit;
134 	}
135 	MLX5_ASSERT(mp_res->num_fds == 1);
136 	ret = mp_res->fds[0];
137 	DRV_LOG(DEBUG, "port %u command FD from primary is %d",
138 		mp_id->port_id, ret);
139 exit:
140 	mlx5_free(mp_rep.msgs);
141 	return ret;
142 }
143 
144 /**
145  * Initialize by primary process.
146  */
147 int
148 mlx5_mp_init_primary(const char *name, const rte_mp_t primary_action)
149 {
150 	int ret;
151 
152 	MLX5_ASSERT(rte_eal_process_type() == RTE_PROC_PRIMARY);
153 
154 	/* primary is allowed to not support IPC */
155 	ret = rte_mp_action_register(name, primary_action);
156 	if (ret && rte_errno != ENOTSUP)
157 		return -1;
158 	return 0;
159 }
160 
161 /**
162  * Un-initialize by primary process.
163  */
164 void
165 mlx5_mp_uninit_primary(const char *name)
166 {
167 	MLX5_ASSERT(rte_eal_process_type() == RTE_PROC_PRIMARY);
168 	rte_mp_action_unregister(name);
169 }
170 
171 /**
172  * Initialize by secondary process.
173  */
174 int
175 mlx5_mp_init_secondary(const char *name, const rte_mp_t secondary_action)
176 {
177 	MLX5_ASSERT(rte_eal_process_type() == RTE_PROC_SECONDARY);
178 	return rte_mp_action_register(name, secondary_action);
179 }
180 
181 /**
182  * Un-initialize by secondary process.
183  */
184 void
185 mlx5_mp_uninit_secondary(const char *name)
186 {
187 	MLX5_ASSERT(rte_eal_process_type() == RTE_PROC_SECONDARY);
188 	rte_mp_action_unregister(name);
189 }
190