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