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