10203d33aSYongseok Koh /* SPDX-License-Identifier: BSD-3-Clause
20203d33aSYongseok Koh * Copyright 2019 6WIND S.A.
30203d33aSYongseok Koh * Copyright 2019 Mellanox Technologies, Ltd
40203d33aSYongseok Koh */
50203d33aSYongseok Koh
60203d33aSYongseok Koh #include <stdio.h>
772b452c5SDmitry Kozlyuk #include <stdlib.h>
80203d33aSYongseok Koh #include <time.h>
9*ff9c3548SLong Li #include <unistd.h>
100203d33aSYongseok Koh
110203d33aSYongseok Koh #include <rte_eal.h>
12df96fd0dSBruce Richardson #include <ethdev_driver.h>
130203d33aSYongseok Koh #include <rte_string_fns.h>
140203d33aSYongseok Koh
150203d33aSYongseok Koh #include "mlx4.h"
160203d33aSYongseok Koh #include "mlx4_rxtx.h"
170203d33aSYongseok Koh #include "mlx4_utils.h"
180203d33aSYongseok Koh
190203d33aSYongseok Koh /**
200203d33aSYongseok Koh * Initialize IPC message.
210203d33aSYongseok Koh *
220203d33aSYongseok Koh * @param[in] dev
230203d33aSYongseok Koh * Pointer to Ethernet structure.
240203d33aSYongseok Koh * @param[out] msg
250203d33aSYongseok Koh * Pointer to message to fill in.
260203d33aSYongseok Koh * @param[in] type
270203d33aSYongseok Koh * Message type.
280203d33aSYongseok Koh */
290203d33aSYongseok Koh static inline void
mp_init_msg(struct rte_eth_dev * dev,struct rte_mp_msg * msg,enum mlx4_mp_req_type type)300203d33aSYongseok Koh mp_init_msg(struct rte_eth_dev *dev, struct rte_mp_msg *msg,
310203d33aSYongseok Koh enum mlx4_mp_req_type type)
320203d33aSYongseok Koh {
330203d33aSYongseok Koh struct mlx4_mp_param *param = (struct mlx4_mp_param *)msg->param;
340203d33aSYongseok Koh
350203d33aSYongseok Koh memset(msg, 0, sizeof(*msg));
360203d33aSYongseok Koh strlcpy(msg->name, MLX4_MP_NAME, sizeof(msg->name));
370203d33aSYongseok Koh msg->len_param = sizeof(*param);
380203d33aSYongseok Koh param->type = type;
390203d33aSYongseok Koh param->port_id = dev->data->port_id;
400203d33aSYongseok Koh }
410203d33aSYongseok Koh
420203d33aSYongseok Koh /**
430203d33aSYongseok Koh * IPC message handler of primary process.
440203d33aSYongseok Koh *
450203d33aSYongseok Koh * @param[in] dev
460203d33aSYongseok Koh * Pointer to Ethernet structure.
470203d33aSYongseok Koh * @param[in] peer
480203d33aSYongseok Koh * Pointer to the peer socket path.
490203d33aSYongseok Koh *
500203d33aSYongseok Koh * @return
510203d33aSYongseok Koh * 0 on success, negative errno value otherwise and rte_errno is set.
520203d33aSYongseok Koh */
530203d33aSYongseok Koh static int
mp_primary_handle(const struct rte_mp_msg * mp_msg,const void * peer)540203d33aSYongseok Koh mp_primary_handle(const struct rte_mp_msg *mp_msg, const void *peer)
550203d33aSYongseok Koh {
560203d33aSYongseok Koh struct rte_mp_msg mp_res;
570203d33aSYongseok Koh struct mlx4_mp_param *res = (struct mlx4_mp_param *)mp_res.param;
580203d33aSYongseok Koh const struct mlx4_mp_param *param =
590203d33aSYongseok Koh (const struct mlx4_mp_param *)mp_msg->param;
600203d33aSYongseok Koh struct rte_eth_dev *dev;
610203d33aSYongseok Koh struct mlx4_priv *priv;
620b259b8eSYongseok Koh struct mlx4_mr_cache entry;
630b259b8eSYongseok Koh uint32_t lkey;
640203d33aSYongseok Koh int ret;
650203d33aSYongseok Koh
668e08df22SAlexander Kozyrev MLX4_ASSERT(rte_eal_process_type() == RTE_PROC_PRIMARY);
670203d33aSYongseok Koh if (!rte_eth_dev_is_valid_port(param->port_id)) {
680203d33aSYongseok Koh rte_errno = ENODEV;
690203d33aSYongseok Koh ERROR("port %u invalid port ID", param->port_id);
700203d33aSYongseok Koh return -rte_errno;
710203d33aSYongseok Koh }
720203d33aSYongseok Koh dev = &rte_eth_devices[param->port_id];
730203d33aSYongseok Koh priv = dev->data->dev_private;
740203d33aSYongseok Koh switch (param->type) {
750b259b8eSYongseok Koh case MLX4_MP_REQ_CREATE_MR:
760b259b8eSYongseok Koh mp_init_msg(dev, &mp_res, param->type);
770b259b8eSYongseok Koh lkey = mlx4_mr_create_primary(dev, &entry, param->args.addr);
780b259b8eSYongseok Koh if (lkey == UINT32_MAX)
790b259b8eSYongseok Koh res->result = -rte_errno;
800b259b8eSYongseok Koh ret = rte_mp_reply(&mp_res, peer);
810b259b8eSYongseok Koh break;
820203d33aSYongseok Koh case MLX4_MP_REQ_VERBS_CMD_FD:
830203d33aSYongseok Koh mp_init_msg(dev, &mp_res, param->type);
840203d33aSYongseok Koh mp_res.num_fds = 1;
850203d33aSYongseok Koh mp_res.fds[0] = priv->ctx->cmd_fd;
860203d33aSYongseok Koh res->result = 0;
870203d33aSYongseok Koh ret = rte_mp_reply(&mp_res, peer);
880203d33aSYongseok Koh break;
890203d33aSYongseok Koh default:
900203d33aSYongseok Koh rte_errno = EINVAL;
910203d33aSYongseok Koh ERROR("port %u invalid mp request type", dev->data->port_id);
920203d33aSYongseok Koh return -rte_errno;
930203d33aSYongseok Koh }
940203d33aSYongseok Koh return ret;
950203d33aSYongseok Koh }
960203d33aSYongseok Koh
970203d33aSYongseok Koh /**
980203d33aSYongseok Koh * IPC message handler of a secondary process.
990203d33aSYongseok Koh *
1000203d33aSYongseok Koh * @param[in] dev
1010203d33aSYongseok Koh * Pointer to Ethernet structure.
1020203d33aSYongseok Koh * @param[in] peer
1030203d33aSYongseok Koh * Pointer to the peer socket path.
1040203d33aSYongseok Koh *
1050203d33aSYongseok Koh * @return
1060203d33aSYongseok Koh * 0 on success, a negative errno value otherwise and rte_errno is set.
1070203d33aSYongseok Koh */
1080203d33aSYongseok Koh static int
mp_secondary_handle(const struct rte_mp_msg * mp_msg,const void * peer)1090203d33aSYongseok Koh mp_secondary_handle(const struct rte_mp_msg *mp_msg, const void *peer)
1100203d33aSYongseok Koh {
1110203d33aSYongseok Koh struct rte_mp_msg mp_res;
1120203d33aSYongseok Koh struct mlx4_mp_param *res = (struct mlx4_mp_param *)mp_res.param;
1130203d33aSYongseok Koh const struct mlx4_mp_param *param =
1140203d33aSYongseok Koh (const struct mlx4_mp_param *)mp_msg->param;
1150203d33aSYongseok Koh struct rte_eth_dev *dev;
116ed879addSSuanming Mou #ifdef HAVE_IBV_MLX4_UAR_MMAP_OFFSET
117ed879addSSuanming Mou struct mlx4_proc_priv *ppriv;
118ed879addSSuanming Mou #endif
1190203d33aSYongseok Koh int ret;
1200203d33aSYongseok Koh
1218e08df22SAlexander Kozyrev MLX4_ASSERT(rte_eal_process_type() == RTE_PROC_SECONDARY);
1220203d33aSYongseok Koh if (!rte_eth_dev_is_valid_port(param->port_id)) {
1230203d33aSYongseok Koh rte_errno = ENODEV;
1240203d33aSYongseok Koh ERROR("port %u invalid port ID", param->port_id);
1250203d33aSYongseok Koh return -rte_errno;
1260203d33aSYongseok Koh }
1270203d33aSYongseok Koh dev = &rte_eth_devices[param->port_id];
1280203d33aSYongseok Koh switch (param->type) {
1290203d33aSYongseok Koh case MLX4_MP_REQ_START_RXTX:
1300203d33aSYongseok Koh INFO("port %u starting datapath", dev->data->port_id);
1310203d33aSYongseok Koh dev->tx_pkt_burst = mlx4_tx_burst;
1320203d33aSYongseok Koh dev->rx_pkt_burst = mlx4_rx_burst;
133ed879addSSuanming Mou #ifdef HAVE_IBV_MLX4_UAR_MMAP_OFFSET
134ed879addSSuanming Mou ppriv = (struct mlx4_proc_priv *)dev->process_private;
135ed879addSSuanming Mou if (ppriv->uar_table_sz != dev->data->nb_tx_queues) {
136ed879addSSuanming Mou mlx4_tx_uar_uninit_secondary(dev);
137ed879addSSuanming Mou mlx4_proc_priv_uninit(dev);
138ed879addSSuanming Mou ret = mlx4_proc_priv_init(dev);
139*ff9c3548SLong Li if (ret) {
140*ff9c3548SLong Li close(mp_msg->fds[0]);
141ed879addSSuanming Mou return -rte_errno;
142*ff9c3548SLong Li }
143ed879addSSuanming Mou ret = mlx4_tx_uar_init_secondary(dev, mp_msg->fds[0]);
144ed879addSSuanming Mou if (ret) {
145*ff9c3548SLong Li close(mp_msg->fds[0]);
146ed879addSSuanming Mou mlx4_proc_priv_uninit(dev);
147ed879addSSuanming Mou return -rte_errno;
148ed879addSSuanming Mou }
149ed879addSSuanming Mou }
150ed879addSSuanming Mou #endif
151*ff9c3548SLong Li close(mp_msg->fds[0]);
152e5d94cf9SChengwen Feng rte_mb();
1530203d33aSYongseok Koh mp_init_msg(dev, &mp_res, param->type);
1540203d33aSYongseok Koh res->result = 0;
1550203d33aSYongseok Koh ret = rte_mp_reply(&mp_res, peer);
1560203d33aSYongseok Koh break;
1570203d33aSYongseok Koh case MLX4_MP_REQ_STOP_RXTX:
1580203d33aSYongseok Koh INFO("port %u stopping datapath", dev->data->port_id);
159a41f593fSFerruh Yigit dev->tx_pkt_burst = rte_eth_pkt_burst_dummy;
160a41f593fSFerruh Yigit dev->rx_pkt_burst = rte_eth_pkt_burst_dummy;
1610203d33aSYongseok Koh rte_mb();
1620203d33aSYongseok Koh mp_init_msg(dev, &mp_res, param->type);
1630203d33aSYongseok Koh res->result = 0;
1640203d33aSYongseok Koh ret = rte_mp_reply(&mp_res, peer);
1650203d33aSYongseok Koh break;
1660203d33aSYongseok Koh default:
1670203d33aSYongseok Koh rte_errno = EINVAL;
1680203d33aSYongseok Koh ERROR("port %u invalid mp request type", dev->data->port_id);
1690203d33aSYongseok Koh return -rte_errno;
1700203d33aSYongseok Koh }
1710203d33aSYongseok Koh return ret;
1720203d33aSYongseok Koh }
1730203d33aSYongseok Koh
1740203d33aSYongseok Koh /**
1750203d33aSYongseok Koh * Broadcast request of stopping/starting data-path to secondary processes.
1760203d33aSYongseok Koh *
1770203d33aSYongseok Koh * @param[in] dev
1780203d33aSYongseok Koh * Pointer to Ethernet structure.
1790203d33aSYongseok Koh * @param[in] type
1800203d33aSYongseok Koh * Request type.
1810203d33aSYongseok Koh */
1820203d33aSYongseok Koh static void
mp_req_on_rxtx(struct rte_eth_dev * dev,enum mlx4_mp_req_type type)1830203d33aSYongseok Koh mp_req_on_rxtx(struct rte_eth_dev *dev, enum mlx4_mp_req_type type)
1840203d33aSYongseok Koh {
1850203d33aSYongseok Koh struct rte_mp_msg mp_req;
1860203d33aSYongseok Koh struct rte_mp_msg *mp_res;
1870203d33aSYongseok Koh struct rte_mp_reply mp_rep;
1880203d33aSYongseok Koh struct mlx4_mp_param *res __rte_unused;
1890203d33aSYongseok Koh struct timespec ts = {.tv_sec = MLX4_MP_REQ_TIMEOUT_SEC, .tv_nsec = 0};
190ed879addSSuanming Mou struct mlx4_priv *priv;
1910203d33aSYongseok Koh int ret;
1920203d33aSYongseok Koh int i;
1930203d33aSYongseok Koh
1948e08df22SAlexander Kozyrev MLX4_ASSERT(rte_eal_process_type() == RTE_PROC_PRIMARY);
1950203d33aSYongseok Koh if (!mlx4_shared_data->secondary_cnt)
1960203d33aSYongseok Koh return;
1970203d33aSYongseok Koh if (type != MLX4_MP_REQ_START_RXTX && type != MLX4_MP_REQ_STOP_RXTX) {
1980203d33aSYongseok Koh ERROR("port %u unknown request (req_type %d)",
1990203d33aSYongseok Koh dev->data->port_id, type);
2000203d33aSYongseok Koh return;
2010203d33aSYongseok Koh }
2020203d33aSYongseok Koh mp_init_msg(dev, &mp_req, type);
203ed879addSSuanming Mou if (type == MLX4_MP_REQ_START_RXTX) {
204ed879addSSuanming Mou priv = dev->data->dev_private;
205ed879addSSuanming Mou mp_req.num_fds = 1;
206ed879addSSuanming Mou mp_req.fds[0] = priv->ctx->cmd_fd;
207ed879addSSuanming Mou }
2080203d33aSYongseok Koh ret = rte_mp_request_sync(&mp_req, &mp_rep, &ts);
2090203d33aSYongseok Koh if (ret) {
210c7ef9899SAnatoly Burakov if (rte_errno != ENOTSUP)
2110203d33aSYongseok Koh ERROR("port %u failed to request stop/start Rx/Tx (%d)",
2120203d33aSYongseok Koh dev->data->port_id, type);
2130203d33aSYongseok Koh goto exit;
2140203d33aSYongseok Koh }
2150203d33aSYongseok Koh if (mp_rep.nb_sent != mp_rep.nb_received) {
2160203d33aSYongseok Koh ERROR("port %u not all secondaries responded (req_type %d)",
2170203d33aSYongseok Koh dev->data->port_id, type);
2180203d33aSYongseok Koh goto exit;
2190203d33aSYongseok Koh }
2200203d33aSYongseok Koh for (i = 0; i < mp_rep.nb_received; i++) {
2210203d33aSYongseok Koh mp_res = &mp_rep.msgs[i];
2220203d33aSYongseok Koh res = (struct mlx4_mp_param *)mp_res->param;
2230203d33aSYongseok Koh if (res->result) {
2240203d33aSYongseok Koh ERROR("port %u request failed on secondary #%d",
2250203d33aSYongseok Koh dev->data->port_id, i);
2260203d33aSYongseok Koh goto exit;
2270203d33aSYongseok Koh }
2280203d33aSYongseok Koh }
2290203d33aSYongseok Koh exit:
2300203d33aSYongseok Koh free(mp_rep.msgs);
2310203d33aSYongseok Koh }
2320203d33aSYongseok Koh
2330203d33aSYongseok Koh /**
2340203d33aSYongseok Koh * Broadcast request of starting data-path to secondary processes. The request
2350203d33aSYongseok Koh * is synchronous.
2360203d33aSYongseok Koh *
2370203d33aSYongseok Koh * @param[in] dev
2380203d33aSYongseok Koh * Pointer to Ethernet structure.
2390203d33aSYongseok Koh */
2400203d33aSYongseok Koh void
mlx4_mp_req_start_rxtx(struct rte_eth_dev * dev)2410203d33aSYongseok Koh mlx4_mp_req_start_rxtx(struct rte_eth_dev *dev)
2420203d33aSYongseok Koh {
2430203d33aSYongseok Koh mp_req_on_rxtx(dev, MLX4_MP_REQ_START_RXTX);
2440203d33aSYongseok Koh }
2450203d33aSYongseok Koh
2460203d33aSYongseok Koh /**
2470203d33aSYongseok Koh * Broadcast request of stopping data-path to secondary processes. The request
2480203d33aSYongseok Koh * is synchronous.
2490203d33aSYongseok Koh *
2500203d33aSYongseok Koh * @param[in] dev
2510203d33aSYongseok Koh * Pointer to Ethernet structure.
2520203d33aSYongseok Koh */
2530203d33aSYongseok Koh void
mlx4_mp_req_stop_rxtx(struct rte_eth_dev * dev)2540203d33aSYongseok Koh mlx4_mp_req_stop_rxtx(struct rte_eth_dev *dev)
2550203d33aSYongseok Koh {
2560203d33aSYongseok Koh mp_req_on_rxtx(dev, MLX4_MP_REQ_STOP_RXTX);
2570203d33aSYongseok Koh }
2580203d33aSYongseok Koh
2590203d33aSYongseok Koh /**
2600b259b8eSYongseok Koh * Request Memory Region creation to the primary process.
2610b259b8eSYongseok Koh *
2620b259b8eSYongseok Koh * @param[in] dev
2630b259b8eSYongseok Koh * Pointer to Ethernet structure.
2640b259b8eSYongseok Koh * @param addr
2650b259b8eSYongseok Koh * Target virtual address to register.
2660b259b8eSYongseok Koh *
2670b259b8eSYongseok Koh * @return
2680b259b8eSYongseok Koh * 0 on success, a negative errno value otherwise and rte_errno is set.
2690b259b8eSYongseok Koh */
2700b259b8eSYongseok Koh int
mlx4_mp_req_mr_create(struct rte_eth_dev * dev,uintptr_t addr)2710b259b8eSYongseok Koh mlx4_mp_req_mr_create(struct rte_eth_dev *dev, uintptr_t addr)
2720b259b8eSYongseok Koh {
2730b259b8eSYongseok Koh struct rte_mp_msg mp_req;
2740b259b8eSYongseok Koh struct rte_mp_msg *mp_res;
2750b259b8eSYongseok Koh struct rte_mp_reply mp_rep;
2760b259b8eSYongseok Koh struct mlx4_mp_param *req = (struct mlx4_mp_param *)mp_req.param;
2770b259b8eSYongseok Koh struct mlx4_mp_param *res;
2780b259b8eSYongseok Koh struct timespec ts = {.tv_sec = MLX4_MP_REQ_TIMEOUT_SEC, .tv_nsec = 0};
2790b259b8eSYongseok Koh int ret;
2800b259b8eSYongseok Koh
2818e08df22SAlexander Kozyrev MLX4_ASSERT(rte_eal_process_type() == RTE_PROC_SECONDARY);
2820b259b8eSYongseok Koh mp_init_msg(dev, &mp_req, MLX4_MP_REQ_CREATE_MR);
2830b259b8eSYongseok Koh req->args.addr = addr;
2840b259b8eSYongseok Koh ret = rte_mp_request_sync(&mp_req, &mp_rep, &ts);
2850b259b8eSYongseok Koh if (ret) {
2860b259b8eSYongseok Koh ERROR("port %u request to primary process failed",
2870b259b8eSYongseok Koh dev->data->port_id);
2880b259b8eSYongseok Koh return -rte_errno;
2890b259b8eSYongseok Koh }
2908e08df22SAlexander Kozyrev MLX4_ASSERT(mp_rep.nb_received == 1);
2910b259b8eSYongseok Koh mp_res = &mp_rep.msgs[0];
2920b259b8eSYongseok Koh res = (struct mlx4_mp_param *)mp_res->param;
2930b259b8eSYongseok Koh ret = res->result;
2940b259b8eSYongseok Koh if (ret)
2950b259b8eSYongseok Koh rte_errno = -ret;
2960b259b8eSYongseok Koh free(mp_rep.msgs);
2970b259b8eSYongseok Koh return ret;
2980b259b8eSYongseok Koh }
2990b259b8eSYongseok Koh
3000b259b8eSYongseok Koh /**
3010203d33aSYongseok Koh * IPC message handler of primary process.
3020203d33aSYongseok Koh *
3030203d33aSYongseok Koh * @param[in] dev
3040203d33aSYongseok Koh * Pointer to Ethernet structure.
3050203d33aSYongseok Koh *
3060203d33aSYongseok Koh * @return
3070203d33aSYongseok Koh * fd on success, a negative errno value otherwise and rte_errno is set.
3080203d33aSYongseok Koh */
3090203d33aSYongseok Koh int
mlx4_mp_req_verbs_cmd_fd(struct rte_eth_dev * dev)3100203d33aSYongseok Koh mlx4_mp_req_verbs_cmd_fd(struct rte_eth_dev *dev)
3110203d33aSYongseok Koh {
3120203d33aSYongseok Koh struct rte_mp_msg mp_req;
3130203d33aSYongseok Koh struct rte_mp_msg *mp_res;
3140203d33aSYongseok Koh struct rte_mp_reply mp_rep;
3150203d33aSYongseok Koh struct mlx4_mp_param *res;
3160203d33aSYongseok Koh struct timespec ts = {.tv_sec = MLX4_MP_REQ_TIMEOUT_SEC, .tv_nsec = 0};
3170203d33aSYongseok Koh int ret;
3180203d33aSYongseok Koh
3198e08df22SAlexander Kozyrev MLX4_ASSERT(rte_eal_process_type() == RTE_PROC_SECONDARY);
3200203d33aSYongseok Koh mp_init_msg(dev, &mp_req, MLX4_MP_REQ_VERBS_CMD_FD);
3210203d33aSYongseok Koh ret = rte_mp_request_sync(&mp_req, &mp_rep, &ts);
3220203d33aSYongseok Koh if (ret) {
3230203d33aSYongseok Koh ERROR("port %u request to primary process failed",
3240203d33aSYongseok Koh dev->data->port_id);
3250203d33aSYongseok Koh return -rte_errno;
3260203d33aSYongseok Koh }
3278e08df22SAlexander Kozyrev MLX4_ASSERT(mp_rep.nb_received == 1);
3280203d33aSYongseok Koh mp_res = &mp_rep.msgs[0];
3290203d33aSYongseok Koh res = (struct mlx4_mp_param *)mp_res->param;
3300203d33aSYongseok Koh if (res->result) {
3310203d33aSYongseok Koh rte_errno = -res->result;
3320203d33aSYongseok Koh ERROR("port %u failed to get command FD from primary process",
3330203d33aSYongseok Koh dev->data->port_id);
3340203d33aSYongseok Koh ret = -rte_errno;
3350203d33aSYongseok Koh goto exit;
3360203d33aSYongseok Koh }
3378e08df22SAlexander Kozyrev MLX4_ASSERT(mp_res->num_fds == 1);
3380203d33aSYongseok Koh ret = mp_res->fds[0];
3390203d33aSYongseok Koh DEBUG("port %u command FD from primary is %d",
3400203d33aSYongseok Koh dev->data->port_id, ret);
3410203d33aSYongseok Koh exit:
3420203d33aSYongseok Koh free(mp_rep.msgs);
3430203d33aSYongseok Koh return ret;
3440203d33aSYongseok Koh }
3450203d33aSYongseok Koh
3460203d33aSYongseok Koh /**
3470203d33aSYongseok Koh * Initialize by primary process.
3480203d33aSYongseok Koh */
349edf73dd3SAnatoly Burakov int
mlx4_mp_init_primary(void)3500203d33aSYongseok Koh mlx4_mp_init_primary(void)
3510203d33aSYongseok Koh {
352edf73dd3SAnatoly Burakov int ret;
353edf73dd3SAnatoly Burakov
3548e08df22SAlexander Kozyrev MLX4_ASSERT(rte_eal_process_type() == RTE_PROC_PRIMARY);
355edf73dd3SAnatoly Burakov
356edf73dd3SAnatoly Burakov /* primary is allowed to not support IPC */
357edf73dd3SAnatoly Burakov ret = rte_mp_action_register(MLX4_MP_NAME, mp_primary_handle);
358edf73dd3SAnatoly Burakov if (ret && rte_errno != ENOTSUP)
359edf73dd3SAnatoly Burakov return -1;
360edf73dd3SAnatoly Burakov return 0;
3610203d33aSYongseok Koh }
3620203d33aSYongseok Koh
3630203d33aSYongseok Koh /**
3640203d33aSYongseok Koh * Un-initialize by primary process.
3650203d33aSYongseok Koh */
3660203d33aSYongseok Koh void
mlx4_mp_uninit_primary(void)3670203d33aSYongseok Koh mlx4_mp_uninit_primary(void)
3680203d33aSYongseok Koh {
3698e08df22SAlexander Kozyrev MLX4_ASSERT(rte_eal_process_type() == RTE_PROC_PRIMARY);
3700203d33aSYongseok Koh rte_mp_action_unregister(MLX4_MP_NAME);
3710203d33aSYongseok Koh }
3720203d33aSYongseok Koh
3730203d33aSYongseok Koh /**
3740203d33aSYongseok Koh * Initialize by secondary process.
3750203d33aSYongseok Koh */
376edf73dd3SAnatoly Burakov int
mlx4_mp_init_secondary(void)3770203d33aSYongseok Koh mlx4_mp_init_secondary(void)
3780203d33aSYongseok Koh {
3798e08df22SAlexander Kozyrev MLX4_ASSERT(rte_eal_process_type() == RTE_PROC_SECONDARY);
380edf73dd3SAnatoly Burakov return rte_mp_action_register(MLX4_MP_NAME, mp_secondary_handle);
3810203d33aSYongseok Koh }
3820203d33aSYongseok Koh
3830203d33aSYongseok Koh /**
3840203d33aSYongseok Koh * Un-initialize by secondary process.
3850203d33aSYongseok Koh */
3860203d33aSYongseok Koh void
mlx4_mp_uninit_secondary(void)3870203d33aSYongseok Koh mlx4_mp_uninit_secondary(void)
3880203d33aSYongseok Koh {
3898e08df22SAlexander Kozyrev MLX4_ASSERT(rte_eal_process_type() == RTE_PROC_SECONDARY);
3900203d33aSYongseok Koh rte_mp_action_unregister(MLX4_MP_NAME);
3910203d33aSYongseok Koh }
392