1 /* SPDX-License-Identifier: BSD-3-Clause
2 * Copyright(c) 2018-2021 HiSilicon Limited.
6 #include <ethdev_driver.h>
7 #include <rte_string_fns.h>
10 #include "hns3_ethdev.h"
11 #include "hns3_logs.h"
12 #include "hns3_rxtx.h"
15 /* local data for primary or secondary process. */
16 struct hns3_process_local_data process_data;
19 * Initialize IPC message.
22 * Pointer to Ethernet structure.
24 * Pointer to message to fill in.
29 mp_init_msg(struct rte_eth_dev *dev, struct rte_mp_msg *msg,
30 enum hns3_mp_req_type type)
32 struct hns3_mp_param *param = (struct hns3_mp_param *)msg->param;
34 memset(msg, 0, sizeof(*msg));
35 strlcpy(msg->name, HNS3_MP_NAME, sizeof(msg->name));
36 msg->len_param = sizeof(*param);
38 param->port_id = dev->data->port_id;
42 * IPC message handler of primary process.
45 * Pointer to Ethernet structure.
47 * Pointer to the peer socket path.
50 * 0 on success, a negative errno value otherwise and rte_errno is set.
53 mp_primary_handle(const struct rte_mp_msg *mp_msg __rte_unused,
54 const void *peer __rte_unused)
60 * IPC message handler of a secondary process.
63 * Pointer to Ethernet structure.
65 * Pointer to the peer socket path.
68 * 0 on success, a negative errno value otherwise and rte_errno is set.
71 mp_secondary_handle(const struct rte_mp_msg *mp_msg, const void *peer)
73 struct rte_mp_msg mp_res;
74 struct hns3_mp_param *res = (struct hns3_mp_param *)mp_res.param;
75 const struct hns3_mp_param *param =
76 (const struct hns3_mp_param *)mp_msg->param;
77 eth_tx_prep_t prep = NULL;
78 struct rte_eth_dev *dev;
81 if (!rte_eth_dev_is_valid_port(param->port_id)) {
83 PMD_INIT_LOG(ERR, "port %d invalid port ID", param->port_id);
86 dev = &rte_eth_devices[param->port_id];
87 switch (param->type) {
88 case HNS3_MP_REQ_START_RXTX:
89 PMD_INIT_LOG(INFO, "port %u starting datapath",
91 hns3_set_rxtx_function(dev);
93 case HNS3_MP_REQ_STOP_RXTX:
94 PMD_INIT_LOG(INFO, "port %u stopping datapath",
96 hns3_set_rxtx_function(dev);
98 case HNS3_MP_REQ_START_TX:
99 PMD_INIT_LOG(INFO, "port %u starting Tx datapath",
101 dev->tx_pkt_burst = hns3_get_tx_function(dev, &prep);
102 dev->tx_pkt_prepare = prep;
104 case HNS3_MP_REQ_STOP_TX:
105 PMD_INIT_LOG(INFO, "port %u stopping Tx datapath",
107 dev->tx_pkt_burst = hns3_dummy_rxtx_burst;
108 dev->tx_pkt_prepare = NULL;
112 PMD_INIT_LOG(ERR, "port %u invalid mp request type",
118 mp_init_msg(dev, &mp_res, param->type);
120 ret = rte_mp_reply(&mp_res, peer);
126 mp_req_type_is_valid(enum hns3_mp_req_type type)
128 return type == HNS3_MP_REQ_START_RXTX ||
129 type == HNS3_MP_REQ_STOP_RXTX ||
130 type == HNS3_MP_REQ_START_TX ||
131 type == HNS3_MP_REQ_STOP_TX;
135 * Broadcast request of stopping/starting data-path to secondary processes.
138 * Pointer to Ethernet structure.
143 mp_req_on_rxtx(struct rte_eth_dev *dev, enum hns3_mp_req_type type)
145 struct hns3_hw *hw = HNS3_DEV_PRIVATE_TO_HW(dev->data->dev_private);
146 struct rte_mp_msg mp_req;
147 struct rte_mp_msg *mp_res;
148 struct rte_mp_reply mp_rep;
149 struct hns3_mp_param *res;
154 if (rte_eal_process_type() == RTE_PROC_SECONDARY ||
155 __atomic_load_n(&hw->secondary_cnt, __ATOMIC_RELAXED) == 0)
158 if (!mp_req_type_is_valid(type)) {
159 hns3_err(hw, "port %u unknown request (req_type %d)",
160 dev->data->port_id, type);
163 mp_init_msg(dev, &mp_req, type);
164 ts.tv_sec = HNS3_MP_REQ_TIMEOUT_SEC;
166 ret = rte_mp_request_sync(&mp_req, &mp_rep, &ts);
168 hns3_err(hw, "port %u failed to request stop/start Rx/Tx (%d)",
169 dev->data->port_id, type);
172 if (mp_rep.nb_sent != mp_rep.nb_received) {
174 "port %u not all secondaries responded (req_type %d)",
175 dev->data->port_id, type);
178 for (i = 0; i < mp_rep.nb_received; i++) {
179 mp_res = &mp_rep.msgs[i];
180 res = (struct hns3_mp_param *)mp_res->param;
182 hns3_err(hw, "port %u request failed on secondary #%d",
183 dev->data->port_id, i);
192 * Broadcast request of starting data-path to secondary processes. The request
196 * Pointer to Ethernet structure.
198 void hns3_mp_req_start_rxtx(struct rte_eth_dev *dev)
200 mp_req_on_rxtx(dev, HNS3_MP_REQ_START_RXTX);
204 * Broadcast request of stopping data-path to secondary processes. The request
208 * Pointer to Ethernet structure.
210 void hns3_mp_req_stop_rxtx(struct rte_eth_dev *dev)
212 mp_req_on_rxtx(dev, HNS3_MP_REQ_STOP_RXTX);
216 hns3_mp_req_stop_tx(struct rte_eth_dev *dev)
218 mp_req_on_rxtx(dev, HNS3_MP_REQ_STOP_TX);
222 hns3_mp_req_start_tx(struct rte_eth_dev *dev)
224 mp_req_on_rxtx(dev, HNS3_MP_REQ_START_TX);
228 * Initialize by primary process.
230 int hns3_mp_init_primary(void)
234 if (process_data.init_done)
237 /* primary is allowed to not support IPC */
238 ret = rte_mp_action_register(HNS3_MP_NAME, mp_primary_handle);
239 if (ret && rte_errno != ENOTSUP)
242 process_data.init_done = true;
247 void hns3_mp_uninit(void)
249 process_data.eth_dev_cnt--;
251 if (process_data.eth_dev_cnt == 0) {
252 rte_mp_action_unregister(HNS3_MP_NAME);
253 process_data.init_done = false;
258 * Initialize by secondary process.
260 int hns3_mp_init_secondary(void)
264 if (process_data.init_done)
267 ret = rte_mp_action_register(HNS3_MP_NAME, mp_secondary_handle);
271 process_data.init_done = true;