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