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 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 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 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 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 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 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 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 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