dpdk/drivers/net/hns3/hns3_mp.c
<<
>>
Prefs
   1/* SPDX-License-Identifier: BSD-3-Clause
   2 * Copyright(c) 2018-2021 HiSilicon Limited.
   3 */
   4
   5#include <rte_eal.h>
   6#include <ethdev_driver.h>
   7#include <rte_string_fns.h>
   8#include <rte_io.h>
   9
  10#include "hns3_ethdev.h"
  11#include "hns3_logs.h"
  12#include "hns3_rxtx.h"
  13#include "hns3_mp.h"
  14
  15static bool hns3_inited;
  16
  17/*
  18 * Initialize IPC message.
  19 *
  20 * @param[in] dev
  21 *   Pointer to Ethernet structure.
  22 * @param[out] msg
  23 *   Pointer to message to fill in.
  24 * @param[in] type
  25 *   Message type.
  26 */
  27static inline void
  28mp_init_msg(struct rte_eth_dev *dev, struct rte_mp_msg *msg,
  29            enum hns3_mp_req_type type)
  30{
  31        struct hns3_mp_param *param = (struct hns3_mp_param *)msg->param;
  32
  33        memset(msg, 0, sizeof(*msg));
  34        strlcpy(msg->name, HNS3_MP_NAME, sizeof(msg->name));
  35        msg->len_param = sizeof(*param);
  36        param->type = type;
  37        param->port_id = dev->data->port_id;
  38}
  39
  40/*
  41 * IPC message handler of primary process.
  42 *
  43 * @param[in] dev
  44 *   Pointer to Ethernet structure.
  45 * @param[in] peer
  46 *   Pointer to the peer socket path.
  47 *
  48 * @return
  49 *   0 on success, a negative errno value otherwise and rte_errno is set.
  50 */
  51static int
  52mp_primary_handle(const struct rte_mp_msg *mp_msg __rte_unused,
  53                  const void *peer __rte_unused)
  54{
  55        return 0;
  56}
  57
  58/*
  59 * IPC message handler of a secondary process.
  60 *
  61 * @param[in] dev
  62 *   Pointer to Ethernet structure.
  63 * @param[in] peer
  64 *   Pointer to the peer socket path.
  65 *
  66 * @return
  67 *   0 on success, a negative errno value otherwise and rte_errno is set.
  68 */
  69static int
  70mp_secondary_handle(const struct rte_mp_msg *mp_msg, const void *peer)
  71{
  72        struct rte_mp_msg mp_res;
  73        struct hns3_mp_param *res = (struct hns3_mp_param *)mp_res.param;
  74        const struct hns3_mp_param *param =
  75                (const struct hns3_mp_param *)mp_msg->param;
  76        struct rte_eth_dev *dev;
  77        int ret;
  78
  79        if (!rte_eth_dev_is_valid_port(param->port_id)) {
  80                rte_errno = ENODEV;
  81                PMD_INIT_LOG(ERR, "port %d invalid port ID", param->port_id);
  82                return -rte_errno;
  83        }
  84        dev = &rte_eth_devices[param->port_id];
  85        switch (param->type) {
  86        case HNS3_MP_REQ_START_RXTX:
  87                PMD_INIT_LOG(INFO, "port %u starting datapath",
  88                             dev->data->port_id);
  89                hns3_set_rxtx_function(dev);
  90                rte_mb();
  91                mp_init_msg(dev, &mp_res, param->type);
  92                res->result = 0;
  93                ret = rte_mp_reply(&mp_res, peer);
  94                break;
  95        case HNS3_MP_REQ_STOP_RXTX:
  96                PMD_INIT_LOG(INFO, "port %u stopping datapath",
  97                             dev->data->port_id);
  98                hns3_set_rxtx_function(dev);
  99                rte_mb();
 100                mp_init_msg(dev, &mp_res, param->type);
 101                res->result = 0;
 102                ret = rte_mp_reply(&mp_res, peer);
 103                break;
 104        default:
 105                rte_errno = EINVAL;
 106                PMD_INIT_LOG(ERR, "port %u invalid mp request type",
 107                             dev->data->port_id);
 108                return -rte_errno;
 109        }
 110        return ret;
 111}
 112
 113/*
 114 * Broadcast request of stopping/starting data-path to secondary processes.
 115 *
 116 * @param[in] dev
 117 *   Pointer to Ethernet structure.
 118 * @param[in] type
 119 *   Request type.
 120 */
 121static void
 122mp_req_on_rxtx(struct rte_eth_dev *dev, enum hns3_mp_req_type type)
 123{
 124        struct hns3_hw *hw = HNS3_DEV_PRIVATE_TO_HW(dev->data->dev_private);
 125        struct rte_mp_msg mp_req;
 126        struct rte_mp_msg *mp_res;
 127        struct rte_mp_reply mp_rep;
 128        struct hns3_mp_param *res;
 129        struct timespec ts;
 130        int ret;
 131        int i;
 132
 133        if (rte_eal_process_type() == RTE_PROC_SECONDARY || !hw->secondary_cnt)
 134                return;
 135        if (type != HNS3_MP_REQ_START_RXTX && type != HNS3_MP_REQ_STOP_RXTX) {
 136                hns3_err(hw, "port %u unknown request (req_type %d)",
 137                         dev->data->port_id, type);
 138                return;
 139        }
 140        mp_init_msg(dev, &mp_req, type);
 141        ts.tv_sec = HNS3_MP_REQ_TIMEOUT_SEC;
 142        ts.tv_nsec = 0;
 143        ret = rte_mp_request_sync(&mp_req, &mp_rep, &ts);
 144        if (ret) {
 145                hns3_err(hw, "port %u failed to request stop/start Rx/Tx (%d)",
 146                         dev->data->port_id, type);
 147                goto exit;
 148        }
 149        if (mp_rep.nb_sent != mp_rep.nb_received) {
 150                PMD_INIT_LOG(ERR,
 151                        "port %u not all secondaries responded (req_type %d)",
 152                        dev->data->port_id, type);
 153                goto exit;
 154        }
 155        for (i = 0; i < mp_rep.nb_received; i++) {
 156                mp_res = &mp_rep.msgs[i];
 157                res = (struct hns3_mp_param *)mp_res->param;
 158                if (res->result) {
 159                        hns3_err(hw, "port %u request failed on secondary #%d",
 160                                 dev->data->port_id, i);
 161                        goto exit;
 162                }
 163        }
 164exit:
 165        free(mp_rep.msgs);
 166}
 167
 168/*
 169 * Broadcast request of starting data-path to secondary processes. The request
 170 * is synchronous.
 171 *
 172 * @param[in] dev
 173 *   Pointer to Ethernet structure.
 174 */
 175void hns3_mp_req_start_rxtx(struct rte_eth_dev *dev)
 176{
 177        mp_req_on_rxtx(dev, HNS3_MP_REQ_START_RXTX);
 178}
 179
 180/*
 181 * Broadcast request of stopping data-path to secondary processes. The request
 182 * is synchronous.
 183 *
 184 * @param[in] dev
 185 *   Pointer to Ethernet structure.
 186 */
 187void hns3_mp_req_stop_rxtx(struct rte_eth_dev *dev)
 188{
 189        mp_req_on_rxtx(dev, HNS3_MP_REQ_STOP_RXTX);
 190}
 191
 192/*
 193 * Initialize by primary process.
 194 */
 195int hns3_mp_init_primary(void)
 196{
 197        int ret;
 198
 199        if (!hns3_inited) {
 200                /* primary is allowed to not support IPC */
 201                ret = rte_mp_action_register(HNS3_MP_NAME, mp_primary_handle);
 202                if (ret && rte_errno != ENOTSUP)
 203                        return ret;
 204
 205                hns3_inited = true;
 206        }
 207
 208        return 0;
 209}
 210
 211/*
 212 * Un-initialize by primary process.
 213 */
 214void hns3_mp_uninit_primary(void)
 215{
 216        if (hns3_inited)
 217                rte_mp_action_unregister(HNS3_MP_NAME);
 218}
 219
 220/*
 221 * Initialize by secondary process.
 222 */
 223int hns3_mp_init_secondary(void)
 224{
 225        int ret;
 226
 227        if (!hns3_inited) {
 228                ret = rte_mp_action_register(HNS3_MP_NAME, mp_secondary_handle);
 229                if (ret)
 230                        return ret;
 231
 232                hns3_inited = true;
 233        }
 234
 235        return 0;
 236}
 237