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
mlx5_mp_req_mr_create(struct mlx5_mp_id * mp_id,uintptr_t addr)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
mlx5_mp_req_queue_state_modify(struct mlx5_mp_id * mp_id,struct mlx5_mp_arg_queue_state_modify * sm)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
mlx5_mp_req_verbs_cmd_fd(struct mlx5_mp_id * mp_id)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
mlx5_mp_init_primary(const char * name,const rte_mp_t primary_action)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
mlx5_mp_uninit_primary(const char * name)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
mlx5_mp_init_secondary(const char * name,const rte_mp_t secondary_action)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
mlx5_mp_uninit_secondary(const char * name)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