> -----Original Message----- > From: Vu Pham <vuhu...@mellanox.com> > Sent: Tuesday, April 7, 2020 20:01 > To: dev@dpdk.org > Cc: Slava Ovsiienko <viachesl...@mellanox.com>; Ori Kam > <or...@mellanox.com>; Matan Azrad <ma...@mellanox.com>; Raslan > Darawsheh <rasl...@mellanox.com>; Vu Pham <vuhu...@mellanox.com> > Subject: [PATCH v3 1/4] common/mlx5: refactor multi-process IPC handling > codes to common driver > > Refactor common multi-process handling codes from net PMD to common > driver. Using tuple mp_id{name, port_id} as standard input parameter for all > multi-process IPC APIs instead of using rte_eth_dev. > > Signed-off-by: Vu Pham <vuhu...@mellanox.com> Acked-by: Viacheslav Ovsiienko <viachesl...@mellanox.com>
> --- > drivers/common/mlx5/mlx5_common_mp.c | 188 > ++++++++++++++++++++++++ > drivers/common/mlx5/mlx5_common_mp.h | 98 ++++++++++++ > drivers/common/mlx5/rte_common_mlx5_version.map | 13 ++ > 3 files changed, 299 insertions(+) > create mode 100644 drivers/common/mlx5/mlx5_common_mp.c > create mode 100644 drivers/common/mlx5/mlx5_common_mp.h > > diff --git a/drivers/common/mlx5/mlx5_common_mp.c > b/drivers/common/mlx5/mlx5_common_mp.c > new file mode 100644 > index 0000000000..da55143bc1 > --- /dev/null > +++ b/drivers/common/mlx5/mlx5_common_mp.c > @@ -0,0 +1,188 @@ > +/* SPDX-License-Identifier: BSD-3-Clause > + * Copyright 2019 6WIND S.A. > + * Copyright 2019 Mellanox Technologies, Ltd */ > + > +#include <stdio.h> > +#include <time.h> > + > +#include <rte_eal.h> > +#include <rte_errno.h> > + > +#include "mlx5_common_mp.h" > +#include "mlx5_common_utils.h" > + > +/** > + * Request Memory Region creation to the primary process. > + * > + * @param[in] mp_id > + * ID of the MP process. > + * @param addr > + * Target virtual address to register. > + * > + * @return > + * 0 on success, a negative errno value otherwise and rte_errno is set. > + */ > +int > +mlx5_mp_req_mr_create(struct mlx5_mp_id *mp_id, uintptr_t addr) { > + struct rte_mp_msg mp_req; > + struct rte_mp_msg *mp_res; > + struct rte_mp_reply mp_rep; > + struct mlx5_mp_param *req = (struct mlx5_mp_param > *)mp_req.param; > + struct mlx5_mp_param *res; > + struct timespec ts = {.tv_sec = MLX5_MP_REQ_TIMEOUT_SEC, .tv_nsec > = 0}; > + int ret; > + > + MLX5_ASSERT(rte_eal_process_type() == RTE_PROC_SECONDARY); > + mp_init_msg(mp_id, &mp_req, MLX5_MP_REQ_CREATE_MR); > + req->args.addr = addr; > + ret = rte_mp_request_sync(&mp_req, &mp_rep, &ts); > + if (ret) { > + DRV_LOG(ERR, "port %u request to primary process failed", > + mp_id->port_id); > + return -rte_errno; > + } > + MLX5_ASSERT(mp_rep.nb_received == 1); > + mp_res = &mp_rep.msgs[0]; > + res = (struct mlx5_mp_param *)mp_res->param; > + ret = res->result; > + if (ret) > + rte_errno = -ret; > + free(mp_rep.msgs); > + return ret; > +} > + > +/** > + * Request Verbs queue state modification to the primary process. > + * > + * @param[in] mp_id > + * ID of the MP process. > + * @param sm > + * State modify parameters. > + * > + * @return > + * 0 on success, a negative errno value otherwise and rte_errno is set. > + */ > +int > +mlx5_mp_req_queue_state_modify(struct mlx5_mp_id *mp_id, > + struct mlx5_mp_arg_queue_state_modify *sm) { > + struct rte_mp_msg mp_req; > + struct rte_mp_msg *mp_res; > + struct rte_mp_reply mp_rep; > + struct mlx5_mp_param *req = (struct mlx5_mp_param > *)mp_req.param; > + struct mlx5_mp_param *res; > + struct timespec ts = {.tv_sec = MLX5_MP_REQ_TIMEOUT_SEC, .tv_nsec > = 0}; > + int ret; > + > + MLX5_ASSERT(rte_eal_process_type() == RTE_PROC_SECONDARY); > + mp_init_msg(mp_id, &mp_req, > MLX5_MP_REQ_QUEUE_STATE_MODIFY); > + req->args.state_modify = *sm; > + ret = rte_mp_request_sync(&mp_req, &mp_rep, &ts); > + if (ret) { > + DRV_LOG(ERR, "port %u request to primary process failed", > + mp_id->port_id); > + return -rte_errno; > + } > + MLX5_ASSERT(mp_rep.nb_received == 1); > + mp_res = &mp_rep.msgs[0]; > + res = (struct mlx5_mp_param *)mp_res->param; > + ret = res->result; > + free(mp_rep.msgs); > + return ret; > +} > + > +/** > + * Request Verbs command file descriptor for mmap to the primary process. > + * > + * @param[in] mp_id > + * ID of the MP process. > + * > + * @return > + * fd on success, a negative errno value otherwise and rte_errno is set. > + */ > +int > +mlx5_mp_req_verbs_cmd_fd(struct mlx5_mp_id *mp_id) { > + struct rte_mp_msg mp_req; > + struct rte_mp_msg *mp_res; > + struct rte_mp_reply mp_rep; > + struct mlx5_mp_param *res; > + struct timespec ts = {.tv_sec = MLX5_MP_REQ_TIMEOUT_SEC, .tv_nsec > = 0}; > + int ret; > + > + MLX5_ASSERT(rte_eal_process_type() == RTE_PROC_SECONDARY); > + mp_init_msg(mp_id, &mp_req, MLX5_MP_REQ_VERBS_CMD_FD); > + ret = rte_mp_request_sync(&mp_req, &mp_rep, &ts); > + if (ret) { > + DRV_LOG(ERR, "port %u request to primary process failed", > + mp_id->port_id); > + return -rte_errno; > + } > + MLX5_ASSERT(mp_rep.nb_received == 1); > + mp_res = &mp_rep.msgs[0]; > + res = (struct mlx5_mp_param *)mp_res->param; > + if (res->result) { > + rte_errno = -res->result; > + DRV_LOG(ERR, > + "port %u failed to get command FD from primary > process", > + mp_id->port_id); > + ret = -rte_errno; > + goto exit; > + } > + MLX5_ASSERT(mp_res->num_fds == 1); > + ret = mp_res->fds[0]; > + DRV_LOG(DEBUG, "port %u command FD from primary is %d", > + mp_id->port_id, ret); > +exit: > + free(mp_rep.msgs); > + return ret; > +} > + > +/** > + * Initialize by primary process. > + */ > +int > +mlx5_mp_init_primary(const char *name, const rte_mp_t primary_action) { > + int ret; > + > + MLX5_ASSERT(rte_eal_process_type() == RTE_PROC_PRIMARY); > + > + /* primary is allowed to not support IPC */ > + ret = rte_mp_action_register(name, primary_action); > + if (ret && rte_errno != ENOTSUP) > + return -1; > + return 0; > +} > + > +/** > + * Un-initialize by primary process. > + */ > +void > +mlx5_mp_uninit_primary(const char *name) { > + MLX5_ASSERT(rte_eal_process_type() == RTE_PROC_PRIMARY); > + rte_mp_action_unregister(name); > +} > + > +/** > + * Initialize by secondary process. > + */ > +int > +mlx5_mp_init_secondary(const char *name, const rte_mp_t > +secondary_action) { > + MLX5_ASSERT(rte_eal_process_type() == RTE_PROC_SECONDARY); > + return rte_mp_action_register(name, secondary_action); } > + > +/** > + * Un-initialize by secondary process. > + */ > +void > +mlx5_mp_uninit_secondary(const char *name) { > + MLX5_ASSERT(rte_eal_process_type() == RTE_PROC_SECONDARY); > + rte_mp_action_unregister(name); > +} > diff --git a/drivers/common/mlx5/mlx5_common_mp.h > b/drivers/common/mlx5/mlx5_common_mp.h > new file mode 100644 > index 0000000000..7aab77acb2 > --- /dev/null > +++ b/drivers/common/mlx5/mlx5_common_mp.h > @@ -0,0 +1,98 @@ > +/* SPDX-License-Identifier: BSD-3-Clause > + * Copyright 2018 6WIND S.A. > + * Copyright 2018 Mellanox Technologies, Ltd */ > + > +#ifndef RTE_PMD_MLX5_COMMON_MP_H_ > +#define RTE_PMD_MLX5_COMMON_MP_H_ > + > +/* Verbs header. */ > +/* ISO C doesn't support unnamed structs/unions, disabling -pedantic. > +*/ #ifdef PEDANTIC #pragma GCC diagnostic ignored "-Wpedantic" > +#endif > +#include <infiniband/verbs.h> > +#ifdef PEDANTIC > +#pragma GCC diagnostic error "-Wpedantic" > +#endif > + > +#include <rte_eal.h> > +#include <rte_string_fns.h> > + > +/* Request types for IPC. */ > +enum mlx5_mp_req_type { > + MLX5_MP_REQ_VERBS_CMD_FD = 1, > + MLX5_MP_REQ_CREATE_MR, > + MLX5_MP_REQ_START_RXTX, > + MLX5_MP_REQ_STOP_RXTX, > + MLX5_MP_REQ_QUEUE_STATE_MODIFY, > +}; > + > +struct mlx5_mp_arg_queue_state_modify { > + uint8_t is_wq; /* Set if WQ. */ > + uint16_t queue_id; /* DPDK queue ID. */ > + enum ibv_wq_state state; /* WQ requested state. */ }; > + > +/* Pameters for IPC. */ > +struct mlx5_mp_param { > + enum mlx5_mp_req_type type; > + int port_id; > + int result; > + RTE_STD_C11 > + union { > + uintptr_t addr; /* MLX5_MP_REQ_CREATE_MR */ > + struct mlx5_mp_arg_queue_state_modify state_modify; > + /* MLX5_MP_REQ_QUEUE_STATE_MODIFY */ > + } args; > +}; > + > +/* Identifier of a MP process */ > +struct mlx5_mp_id { > + char name[RTE_MP_MAX_NAME_LEN]; > + uint16_t port_id; > +}; > + > +/** Request timeout for IPC. */ > +#define MLX5_MP_REQ_TIMEOUT_SEC 5 > + > +/** > + * Initialize IPC message. > + * > + * @param[in] port_id > + * Port ID of the device. > + * @param[out] msg > + * Pointer to message to fill in. > + * @param[in] type > + * Message type. > + */ > +static inline void > +mp_init_msg(struct mlx5_mp_id *mp_id, struct rte_mp_msg *msg, > + enum mlx5_mp_req_type type) > +{ > + struct mlx5_mp_param *param = (struct mlx5_mp_param *)msg- > >param; > + > + memset(msg, 0, sizeof(*msg)); > + strlcpy(msg->name, mp_id->name, sizeof(msg->name)); > + msg->len_param = sizeof(*param); > + param->type = type; > + param->port_id = mp_id->port_id; > +} > + > +__rte_experimental > +int mlx5_mp_init_primary(const char *name, const rte_mp_t > +primary_action); __rte_experimental void mlx5_mp_uninit_primary(const > +char *name); __rte_experimental int mlx5_mp_init_secondary(const char > +*name, const rte_mp_t secondary_action); __rte_experimental void > +mlx5_mp_uninit_secondary(const char *name); __rte_experimental int > +mlx5_mp_req_mr_create(struct mlx5_mp_id *mp_id, uintptr_t addr); > +__rte_experimental int mlx5_mp_req_queue_state_modify(struct > mlx5_mp_id > +*mp_id, > + struct mlx5_mp_arg_queue_state_modify > *sm); __rte_experimental > +int mlx5_mp_req_verbs_cmd_fd(struct mlx5_mp_id *mp_id); > + > +#endif /* RTE_PMD_MLX5_COMMON_MP_H_ */ > diff --git a/drivers/common/mlx5/rte_common_mlx5_version.map > b/drivers/common/mlx5/rte_common_mlx5_version.map > index aede2a0a51..265703d1c9 100644 > --- a/drivers/common/mlx5/rte_common_mlx5_version.map > +++ b/drivers/common/mlx5/rte_common_mlx5_version.map > @@ -48,4 +48,17 @@ DPDK_20.0.1 { > mlx5_nl_vlan_vmwa_delete; > > mlx5_translate_port_name; > + > +}; > + > +EXPERIMENTAL { > + global: > + > + mlx5_mp_init_primary; > + mlx5_mp_uninit_primary; > + mlx5_mp_init_secondary; > + mlx5_mp_uninit_secondary; > + mlx5_mp_req_mr_create; > + mlx5_mp_req_queue_state_modify; > + mlx5_mp_req_verbs_cmd_fd; > }; > -- > 2.16.6