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