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