X-Git-Url: http://git.droids-corp.org/?a=blobdiff_plain;f=drivers%2Fnet%2Fmlx5%2Fmlx5_mp.c;h=a2b5c400004d8c9f09573e0a9e5d772feedcf25b;hb=3b025c0ca425a634b7eead08420fa5a5cfaa1445;hp=701ee1d260b67743fd2550aa36ac8b301db1a7ec;hpb=7be600c8d8ef48cbd4b73077923821798190f2f1;p=dpdk.git diff --git a/drivers/net/mlx5/mlx5_mp.c b/drivers/net/mlx5/mlx5_mp.c index 701ee1d260..a2b5c40000 100644 --- a/drivers/net/mlx5/mlx5_mp.c +++ b/drivers/net/mlx5/mlx5_mp.c @@ -3,7 +3,6 @@ * Copyright 2019 Mellanox Technologies, Ltd */ -#include #include #include @@ -11,34 +10,69 @@ #include #include +#include +#include + #include "mlx5.h" +#include "mlx5_rxtx.h" #include "mlx5_utils.h" -/** - * Initialize IPC message. - * - * @param[in] dev - * Pointer to Ethernet structure. - * @param[out] msg - * Pointer to message to fill in. - * @param[in] type - * Message type. - */ -static inline void -mp_init_msg(struct rte_eth_dev *dev, struct rte_mp_msg *msg, - enum mlx5_mp_req_type type) +int +mlx5_mp_primary_handle(const struct rte_mp_msg *mp_msg, const void *peer) { - struct mlx5_mp_param *param = (struct mlx5_mp_param *)msg->param; + struct rte_mp_msg mp_res; + struct mlx5_mp_param *res = (struct mlx5_mp_param *)mp_res.param; + const struct mlx5_mp_param *param = + (const struct mlx5_mp_param *)mp_msg->param; + struct rte_eth_dev *dev; + struct mlx5_priv *priv; + struct mr_cache_entry entry; + uint32_t lkey; + int ret; - memset(msg, 0, sizeof(*msg)); - strlcpy(msg->name, MLX5_MP_NAME, sizeof(msg->name)); - msg->len_param = sizeof(*param); - param->type = type; - param->port_id = dev->data->port_id; + MLX5_ASSERT(rte_eal_process_type() == RTE_PROC_PRIMARY); + if (!rte_eth_dev_is_valid_port(param->port_id)) { + rte_errno = ENODEV; + DRV_LOG(ERR, "port %u invalid port ID", param->port_id); + return -rte_errno; + } + dev = &rte_eth_devices[param->port_id]; + priv = dev->data->dev_private; + switch (param->type) { + case MLX5_MP_REQ_CREATE_MR: + mp_init_msg(&priv->mp_id, &mp_res, param->type); + lkey = mlx5_mr_create_primary(priv->sh->pd, + &priv->sh->share_cache, + &entry, param->args.addr, + priv->config.mr_ext_memseg_en); + if (lkey == UINT32_MAX) + res->result = -rte_errno; + ret = rte_mp_reply(&mp_res, peer); + break; + case MLX5_MP_REQ_VERBS_CMD_FD: + mp_init_msg(&priv->mp_id, &mp_res, param->type); + mp_res.num_fds = 1; + mp_res.fds[0] = ((struct ibv_context *)priv->sh->ctx)->cmd_fd; + res->result = 0; + ret = rte_mp_reply(&mp_res, peer); + break; + case MLX5_MP_REQ_QUEUE_STATE_MODIFY: + mp_init_msg(&priv->mp_id, &mp_res, param->type); + res->result = mlx5_queue_state_modify_primary + (dev, ¶m->args.state_modify); + ret = rte_mp_reply(&mp_res, peer); + break; + default: + rte_errno = EINVAL; + DRV_LOG(ERR, "port %u invalid mp request type", + dev->data->port_id); + return -rte_errno; + } + return ret; } /** - * IPC message handler of primary process. + * IPC message handler of a secondary process. * * @param[in] dev * Pointer to Ethernet structure. @@ -48,8 +82,8 @@ mp_init_msg(struct rte_eth_dev *dev, struct rte_mp_msg *msg, * @return * 0 on success, a negative errno value otherwise and rte_errno is set. */ -static int -mp_primary_handle(const struct rte_mp_msg *mp_msg, const void *peer) +int +mlx5_mp_secondary_handle(const struct rte_mp_msg *mp_msg, const void *peer) { struct rte_mp_msg mp_res; struct mlx5_mp_param *res = (struct mlx5_mp_param *)mp_res.param; @@ -59,7 +93,7 @@ mp_primary_handle(const struct rte_mp_msg *mp_msg, const void *peer) struct mlx5_priv *priv; int ret; - assert(rte_eal_process_type() == RTE_PROC_PRIMARY); + MLX5_ASSERT(rte_eal_process_type() == RTE_PROC_SECONDARY); if (!rte_eth_dev_is_valid_port(param->port_id)) { rte_errno = ENODEV; DRV_LOG(ERR, "port %u invalid port ID", param->port_id); @@ -68,10 +102,21 @@ mp_primary_handle(const struct rte_mp_msg *mp_msg, const void *peer) dev = &rte_eth_devices[param->port_id]; priv = dev->data->dev_private; switch (param->type) { - case MLX5_MP_REQ_VERBS_CMD_FD: - mp_init_msg(dev, &mp_res, param->type); - mp_res.num_fds = 1; - mp_res.fds[0] = priv->sh->ctx->cmd_fd; + case MLX5_MP_REQ_START_RXTX: + DRV_LOG(INFO, "port %u starting datapath", dev->data->port_id); + rte_mb(); + dev->rx_pkt_burst = mlx5_select_rx_function(dev); + dev->tx_pkt_burst = mlx5_select_tx_function(dev); + mp_init_msg(&priv->mp_id, &mp_res, param->type); + res->result = 0; + ret = rte_mp_reply(&mp_res, peer); + break; + case MLX5_MP_REQ_STOP_RXTX: + DRV_LOG(INFO, "port %u stopping datapath", dev->data->port_id); + dev->rx_pkt_burst = removed_rx_burst; + dev->tx_pkt_burst = removed_tx_burst; + rte_mb(); + mp_init_msg(&priv->mp_id, &mp_res, param->type); res->result = 0; ret = rte_mp_reply(&mp_res, peer); break; @@ -85,68 +130,82 @@ mp_primary_handle(const struct rte_mp_msg *mp_msg, const void *peer) } /** - * Request Verbs command file descriptor for mmap to the primary process. + * Broadcast request of stopping/starting data-path to secondary processes. * * @param[in] dev * Pointer to Ethernet structure. - * - * @return - * fd on success, a negative errno value otherwise and rte_errno is set. + * @param[in] type + * Request type. */ -int -mlx5_mp_req_verbs_cmd_fd(struct rte_eth_dev *dev) +static void +mp_req_on_rxtx(struct rte_eth_dev *dev, enum mlx5_mp_req_type type) { 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}; + struct mlx5_priv *priv = dev->data->dev_private; int ret; + int i; - assert(rte_eal_process_type() == RTE_PROC_SECONDARY); - mp_init_msg(dev, &mp_req, MLX5_MP_REQ_VERBS_CMD_FD); + MLX5_ASSERT(rte_eal_process_type() == RTE_PROC_PRIMARY); + if (!mlx5_shared_data->secondary_cnt) + return; + if (type != MLX5_MP_REQ_START_RXTX && type != MLX5_MP_REQ_STOP_RXTX) { + DRV_LOG(ERR, "port %u unknown request (req_type %d)", + dev->data->port_id, type); + return; + } + mp_init_msg(&priv->mp_id, &mp_req, type); ret = rte_mp_request_sync(&mp_req, &mp_rep, &ts); if (ret) { - DRV_LOG(ERR, "port %u request to primary process failed", - dev->data->port_id); - return -rte_errno; + if (rte_errno != ENOTSUP) + DRV_LOG(ERR, "port %u failed to request stop/start Rx/Tx (%d)", + dev->data->port_id, type); + goto exit; } - 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; + if (mp_rep.nb_sent != mp_rep.nb_received) { DRV_LOG(ERR, - "port %u failed to get command FD from primary process", - dev->data->port_id); - ret = -rte_errno; + "port %u not all secondaries responded (req_type %d)", + dev->data->port_id, type); goto exit; } - assert(mp_res->num_fds == 1); - ret = mp_res->fds[0]; - DRV_LOG(DEBUG, "port %u command FD from primary is %d", - dev->data->port_id, ret); + for (i = 0; i < mp_rep.nb_received; i++) { + mp_res = &mp_rep.msgs[i]; + res = (struct mlx5_mp_param *)mp_res->param; + if (res->result) { + DRV_LOG(ERR, "port %u request failed on secondary #%d", + dev->data->port_id, i); + goto exit; + } + } exit: free(mp_rep.msgs); - return ret; } /** - * Initialize by primary process. + * Broadcast request of starting data-path to secondary processes. The request + * is synchronous. + * + * @param[in] dev + * Pointer to Ethernet structure. */ void -mlx5_mp_init_primary(void) +mlx5_mp_req_start_rxtx(struct rte_eth_dev *dev) { - assert(rte_eal_process_type() == RTE_PROC_PRIMARY); - rte_mp_action_register(MLX5_MP_NAME, mp_primary_handle); + mp_req_on_rxtx(dev, MLX5_MP_REQ_START_RXTX); } /** - * Un-initialize by primary process. + * Broadcast request of stopping data-path to secondary processes. The request + * is synchronous. + * + * @param[in] dev + * Pointer to Ethernet structure. */ void -mlx5_mp_uninit_primary(void) +mlx5_mp_req_stop_rxtx(struct rte_eth_dev *dev) { - assert(rte_eal_process_type() == RTE_PROC_PRIMARY); - rte_mp_action_unregister(MLX5_MP_NAME); + mp_req_on_rxtx(dev, MLX5_MP_REQ_STOP_RXTX); }