xref: /dpdk/drivers/net/hns3/hns3_mp.c (revision e12a0166c80f65e35408f4715b2f3a60763c3741)
123d4b61fSWei Hu (Xavier) /* SPDX-License-Identifier: BSD-3-Clause
253e6f86cSMin Hu (Connor)  * Copyright(c) 2018-2021 HiSilicon Limited.
323d4b61fSWei Hu (Xavier)  */
423d4b61fSWei Hu (Xavier) 
572b452c5SDmitry Kozlyuk #include <stdlib.h>
672b452c5SDmitry Kozlyuk 
723d4b61fSWei Hu (Xavier) #include <rte_eal.h>
8df96fd0dSBruce Richardson #include <ethdev_driver.h>
923d4b61fSWei Hu (Xavier) #include <rte_string_fns.h>
1023d4b61fSWei Hu (Xavier) #include <rte_io.h>
1123d4b61fSWei Hu (Xavier) 
1223d4b61fSWei Hu (Xavier) #include "hns3_ethdev.h"
1323d4b61fSWei Hu (Xavier) #include "hns3_logs.h"
1423d4b61fSWei Hu (Xavier) #include "hns3_rxtx.h"
1523d4b61fSWei Hu (Xavier) #include "hns3_mp.h"
1623d4b61fSWei Hu (Xavier) 
17841f8693SHuisong Li /* local data for primary or secondary process. */
18ff6dc76eSHuisong Li static struct hns3_process_local_data process_data;
199570b1fdSWei Hu (Xavier) 
2023d4b61fSWei Hu (Xavier) /*
2123d4b61fSWei Hu (Xavier)  * Initialize IPC message.
2223d4b61fSWei Hu (Xavier)  *
2323d4b61fSWei Hu (Xavier)  * @param[in] dev
2423d4b61fSWei Hu (Xavier)  *   Pointer to Ethernet structure.
2523d4b61fSWei Hu (Xavier)  * @param[out] msg
2623d4b61fSWei Hu (Xavier)  *   Pointer to message to fill in.
2723d4b61fSWei Hu (Xavier)  * @param[in] type
2823d4b61fSWei Hu (Xavier)  *   Message type.
2923d4b61fSWei Hu (Xavier)  */
3023d4b61fSWei Hu (Xavier) static inline void
mp_init_msg(struct rte_eth_dev * dev,struct rte_mp_msg * msg,enum hns3_mp_req_type type)3123d4b61fSWei Hu (Xavier) mp_init_msg(struct rte_eth_dev *dev, struct rte_mp_msg *msg,
3223d4b61fSWei Hu (Xavier) 	    enum hns3_mp_req_type type)
3323d4b61fSWei Hu (Xavier) {
3423d4b61fSWei Hu (Xavier) 	struct hns3_mp_param *param = (struct hns3_mp_param *)msg->param;
3523d4b61fSWei Hu (Xavier) 
3623d4b61fSWei Hu (Xavier) 	memset(msg, 0, sizeof(*msg));
3723d4b61fSWei Hu (Xavier) 	strlcpy(msg->name, HNS3_MP_NAME, sizeof(msg->name));
3823d4b61fSWei Hu (Xavier) 	msg->len_param = sizeof(*param);
3923d4b61fSWei Hu (Xavier) 	param->type = type;
4023d4b61fSWei Hu (Xavier) 	param->port_id = dev->data->port_id;
4123d4b61fSWei Hu (Xavier) }
4223d4b61fSWei Hu (Xavier) 
4323d4b61fSWei Hu (Xavier) /*
4423d4b61fSWei Hu (Xavier)  * IPC message handler of primary process.
4523d4b61fSWei Hu (Xavier)  *
4623d4b61fSWei Hu (Xavier)  * @param[in] dev
4723d4b61fSWei Hu (Xavier)  *   Pointer to Ethernet structure.
4823d4b61fSWei Hu (Xavier)  * @param[in] peer
4923d4b61fSWei Hu (Xavier)  *   Pointer to the peer socket path.
5023d4b61fSWei Hu (Xavier)  *
5123d4b61fSWei Hu (Xavier)  * @return
5223d4b61fSWei Hu (Xavier)  *   0 on success, a negative errno value otherwise and rte_errno is set.
5323d4b61fSWei Hu (Xavier)  */
5423d4b61fSWei Hu (Xavier) static int
mp_primary_handle(const struct rte_mp_msg * mp_msg __rte_unused,const void * peer __rte_unused)5523d4b61fSWei Hu (Xavier) mp_primary_handle(const struct rte_mp_msg *mp_msg __rte_unused,
5623d4b61fSWei Hu (Xavier) 		  const void *peer __rte_unused)
5723d4b61fSWei Hu (Xavier) {
5823d4b61fSWei Hu (Xavier) 	return 0;
5923d4b61fSWei Hu (Xavier) }
6023d4b61fSWei Hu (Xavier) 
6123d4b61fSWei Hu (Xavier) /*
6223d4b61fSWei Hu (Xavier)  * IPC message handler of a secondary process.
6323d4b61fSWei Hu (Xavier)  *
6423d4b61fSWei Hu (Xavier)  * @param[in] dev
6523d4b61fSWei Hu (Xavier)  *   Pointer to Ethernet structure.
6623d4b61fSWei Hu (Xavier)  * @param[in] peer
6723d4b61fSWei Hu (Xavier)  *   Pointer to the peer socket path.
6823d4b61fSWei Hu (Xavier)  *
6923d4b61fSWei Hu (Xavier)  * @return
7023d4b61fSWei Hu (Xavier)  *   0 on success, a negative errno value otherwise and rte_errno is set.
7123d4b61fSWei Hu (Xavier)  */
7223d4b61fSWei Hu (Xavier) static int
mp_secondary_handle(const struct rte_mp_msg * mp_msg,const void * peer)7323d4b61fSWei Hu (Xavier) mp_secondary_handle(const struct rte_mp_msg *mp_msg, const void *peer)
7423d4b61fSWei Hu (Xavier) {
7523d4b61fSWei Hu (Xavier) 	struct rte_mp_msg mp_res;
7623d4b61fSWei Hu (Xavier) 	struct hns3_mp_param *res = (struct hns3_mp_param *)mp_res.param;
7723d4b61fSWei Hu (Xavier) 	const struct hns3_mp_param *param =
7823d4b61fSWei Hu (Xavier) 		(const struct hns3_mp_param *)mp_msg->param;
7923d4b61fSWei Hu (Xavier) 	struct rte_eth_dev *dev;
8023d4b61fSWei Hu (Xavier) 	int ret;
8123d4b61fSWei Hu (Xavier) 
8223d4b61fSWei Hu (Xavier) 	if (!rte_eth_dev_is_valid_port(param->port_id)) {
8323d4b61fSWei Hu (Xavier) 		rte_errno = ENODEV;
842427c27eSHongbo Zheng 		PMD_INIT_LOG(ERR, "port %d invalid port ID", param->port_id);
8523d4b61fSWei Hu (Xavier) 		return -rte_errno;
8623d4b61fSWei Hu (Xavier) 	}
8723d4b61fSWei Hu (Xavier) 	dev = &rte_eth_devices[param->port_id];
8823d4b61fSWei Hu (Xavier) 	switch (param->type) {
8923d4b61fSWei Hu (Xavier) 	case HNS3_MP_REQ_START_RXTX:
9023d4b61fSWei Hu (Xavier) 		PMD_INIT_LOG(INFO, "port %u starting datapath",
9123d4b61fSWei Hu (Xavier) 			     dev->data->port_id);
924ba28c95SHuisong Li 		hns3_start_rxtx_datapath(dev);
9323d4b61fSWei Hu (Xavier) 		break;
9423d4b61fSWei Hu (Xavier) 	case HNS3_MP_REQ_STOP_RXTX:
9523d4b61fSWei Hu (Xavier) 		PMD_INIT_LOG(INFO, "port %u stopping datapath",
9623d4b61fSWei Hu (Xavier) 			     dev->data->port_id);
974ba28c95SHuisong Li 		hns3_stop_rxtx_datapath(dev);
9869f9b420SHuisong Li 		break;
9969f9b420SHuisong Li 	case HNS3_MP_REQ_START_TX:
10069f9b420SHuisong Li 		PMD_INIT_LOG(INFO, "port %u starting Tx datapath",
10169f9b420SHuisong Li 			     dev->data->port_id);
10296c33cfbSMin Hu (Connor) 		hns3_start_tx_datapath(dev);
10369f9b420SHuisong Li 		break;
10469f9b420SHuisong Li 	case HNS3_MP_REQ_STOP_TX:
10569f9b420SHuisong Li 		PMD_INIT_LOG(INFO, "port %u stopping Tx datapath",
10669f9b420SHuisong Li 			     dev->data->port_id);
10796c33cfbSMin Hu (Connor) 		hns3_stop_tx_datapath(dev);
10823d4b61fSWei Hu (Xavier) 		break;
10923d4b61fSWei Hu (Xavier) 	default:
11023d4b61fSWei Hu (Xavier) 		rte_errno = EINVAL;
11123d4b61fSWei Hu (Xavier) 		PMD_INIT_LOG(ERR, "port %u invalid mp request type",
11223d4b61fSWei Hu (Xavier) 			     dev->data->port_id);
11323d4b61fSWei Hu (Xavier) 		return -rte_errno;
11423d4b61fSWei Hu (Xavier) 	}
11569f9b420SHuisong Li 
11669f9b420SHuisong Li 	rte_mb();
11769f9b420SHuisong Li 	mp_init_msg(dev, &mp_res, param->type);
11869f9b420SHuisong Li 	res->result = 0;
11969f9b420SHuisong Li 	ret = rte_mp_reply(&mp_res, peer);
12069f9b420SHuisong Li 
12123d4b61fSWei Hu (Xavier) 	return ret;
12223d4b61fSWei Hu (Xavier) }
12323d4b61fSWei Hu (Xavier) 
12469f9b420SHuisong Li static bool
mp_req_type_is_valid(enum hns3_mp_req_type type)12569f9b420SHuisong Li mp_req_type_is_valid(enum hns3_mp_req_type type)
12669f9b420SHuisong Li {
12769f9b420SHuisong Li 	return type == HNS3_MP_REQ_START_RXTX ||
12869f9b420SHuisong Li 		type == HNS3_MP_REQ_STOP_RXTX ||
12969f9b420SHuisong Li 		type == HNS3_MP_REQ_START_TX ||
13069f9b420SHuisong Li 		type == HNS3_MP_REQ_STOP_TX;
13169f9b420SHuisong Li }
13269f9b420SHuisong Li 
13323d4b61fSWei Hu (Xavier) /*
13423d4b61fSWei Hu (Xavier)  * Broadcast request of stopping/starting data-path to secondary processes.
13523d4b61fSWei Hu (Xavier)  *
13623d4b61fSWei Hu (Xavier)  * @param[in] dev
13723d4b61fSWei Hu (Xavier)  *   Pointer to Ethernet structure.
13823d4b61fSWei Hu (Xavier)  * @param[in] type
13923d4b61fSWei Hu (Xavier)  *   Request type.
14023d4b61fSWei Hu (Xavier)  */
14123d4b61fSWei Hu (Xavier) static void
mp_req_on_rxtx(struct rte_eth_dev * dev,enum hns3_mp_req_type type)14223d4b61fSWei Hu (Xavier) mp_req_on_rxtx(struct rte_eth_dev *dev, enum hns3_mp_req_type type)
14323d4b61fSWei Hu (Xavier) {
14423d4b61fSWei Hu (Xavier) 	struct hns3_hw *hw = HNS3_DEV_PRIVATE_TO_HW(dev->data->dev_private);
14523d4b61fSWei Hu (Xavier) 	struct rte_mp_msg mp_req;
14623d4b61fSWei Hu (Xavier) 	struct rte_mp_msg *mp_res;
14723d4b61fSWei Hu (Xavier) 	struct rte_mp_reply mp_rep;
14823d4b61fSWei Hu (Xavier) 	struct hns3_mp_param *res;
14923d4b61fSWei Hu (Xavier) 	struct timespec ts;
15023d4b61fSWei Hu (Xavier) 	int ret;
15123d4b61fSWei Hu (Xavier) 	int i;
15223d4b61fSWei Hu (Xavier) 
15332326371SHuisong Li 	if (rte_eal_process_type() == RTE_PROC_SECONDARY ||
154*e12a0166STyler Retzlaff 		rte_atomic_load_explicit(&hw->secondary_cnt, rte_memory_order_relaxed) == 0)
15523d4b61fSWei Hu (Xavier) 		return;
15632326371SHuisong Li 
15769f9b420SHuisong Li 	if (!mp_req_type_is_valid(type)) {
15823d4b61fSWei Hu (Xavier) 		hns3_err(hw, "port %u unknown request (req_type %d)",
15923d4b61fSWei Hu (Xavier) 			 dev->data->port_id, type);
16023d4b61fSWei Hu (Xavier) 		return;
16123d4b61fSWei Hu (Xavier) 	}
16223d4b61fSWei Hu (Xavier) 	mp_init_msg(dev, &mp_req, type);
16323d4b61fSWei Hu (Xavier) 	ts.tv_sec = HNS3_MP_REQ_TIMEOUT_SEC;
16423d4b61fSWei Hu (Xavier) 	ts.tv_nsec = 0;
16523d4b61fSWei Hu (Xavier) 	ret = rte_mp_request_sync(&mp_req, &mp_rep, &ts);
16623d4b61fSWei Hu (Xavier) 	if (ret) {
16723d4b61fSWei Hu (Xavier) 		hns3_err(hw, "port %u failed to request stop/start Rx/Tx (%d)",
16823d4b61fSWei Hu (Xavier) 			 dev->data->port_id, type);
16923d4b61fSWei Hu (Xavier) 		goto exit;
17023d4b61fSWei Hu (Xavier) 	}
17123d4b61fSWei Hu (Xavier) 	if (mp_rep.nb_sent != mp_rep.nb_received) {
17223d4b61fSWei Hu (Xavier) 		PMD_INIT_LOG(ERR,
17323d4b61fSWei Hu (Xavier) 			"port %u not all secondaries responded (req_type %d)",
17423d4b61fSWei Hu (Xavier) 			dev->data->port_id, type);
17523d4b61fSWei Hu (Xavier) 		goto exit;
17623d4b61fSWei Hu (Xavier) 	}
17723d4b61fSWei Hu (Xavier) 	for (i = 0; i < mp_rep.nb_received; i++) {
17823d4b61fSWei Hu (Xavier) 		mp_res = &mp_rep.msgs[i];
17923d4b61fSWei Hu (Xavier) 		res = (struct hns3_mp_param *)mp_res->param;
18023d4b61fSWei Hu (Xavier) 		if (res->result) {
18123d4b61fSWei Hu (Xavier) 			hns3_err(hw, "port %u request failed on secondary #%d",
18223d4b61fSWei Hu (Xavier) 				 dev->data->port_id, i);
18323d4b61fSWei Hu (Xavier) 			goto exit;
18423d4b61fSWei Hu (Xavier) 		}
18523d4b61fSWei Hu (Xavier) 	}
18623d4b61fSWei Hu (Xavier) exit:
18723d4b61fSWei Hu (Xavier) 	free(mp_rep.msgs);
18823d4b61fSWei Hu (Xavier) }
18923d4b61fSWei Hu (Xavier) 
19023d4b61fSWei Hu (Xavier) /*
19123d4b61fSWei Hu (Xavier)  * Broadcast request of starting data-path to secondary processes. The request
19223d4b61fSWei Hu (Xavier)  * is synchronous.
19323d4b61fSWei Hu (Xavier)  *
19423d4b61fSWei Hu (Xavier)  * @param[in] dev
19523d4b61fSWei Hu (Xavier)  *   Pointer to Ethernet structure.
19623d4b61fSWei Hu (Xavier)  */
hns3_mp_req_start_rxtx(struct rte_eth_dev * dev)19723d4b61fSWei Hu (Xavier) void hns3_mp_req_start_rxtx(struct rte_eth_dev *dev)
19823d4b61fSWei Hu (Xavier) {
19923d4b61fSWei Hu (Xavier) 	mp_req_on_rxtx(dev, HNS3_MP_REQ_START_RXTX);
20023d4b61fSWei Hu (Xavier) }
20123d4b61fSWei Hu (Xavier) 
20223d4b61fSWei Hu (Xavier) /*
20323d4b61fSWei Hu (Xavier)  * Broadcast request of stopping data-path to secondary processes. The request
20423d4b61fSWei Hu (Xavier)  * is synchronous.
20523d4b61fSWei Hu (Xavier)  *
20623d4b61fSWei Hu (Xavier)  * @param[in] dev
20723d4b61fSWei Hu (Xavier)  *   Pointer to Ethernet structure.
20823d4b61fSWei Hu (Xavier)  */
hns3_mp_req_stop_rxtx(struct rte_eth_dev * dev)20923d4b61fSWei Hu (Xavier) void hns3_mp_req_stop_rxtx(struct rte_eth_dev *dev)
21023d4b61fSWei Hu (Xavier) {
21123d4b61fSWei Hu (Xavier) 	mp_req_on_rxtx(dev, HNS3_MP_REQ_STOP_RXTX);
21223d4b61fSWei Hu (Xavier) }
21323d4b61fSWei Hu (Xavier) 
21469f9b420SHuisong Li void
hns3_mp_req_stop_tx(struct rte_eth_dev * dev)21569f9b420SHuisong Li hns3_mp_req_stop_tx(struct rte_eth_dev *dev)
21669f9b420SHuisong Li {
21769f9b420SHuisong Li 	mp_req_on_rxtx(dev, HNS3_MP_REQ_STOP_TX);
21869f9b420SHuisong Li }
21969f9b420SHuisong Li 
22069f9b420SHuisong Li void
hns3_mp_req_start_tx(struct rte_eth_dev * dev)22169f9b420SHuisong Li hns3_mp_req_start_tx(struct rte_eth_dev *dev)
22269f9b420SHuisong Li {
22369f9b420SHuisong Li 	mp_req_on_rxtx(dev, HNS3_MP_REQ_START_TX);
22469f9b420SHuisong Li }
22569f9b420SHuisong Li 
22623d4b61fSWei Hu (Xavier) /*
22723d4b61fSWei Hu (Xavier)  * Initialize by primary process.
22823d4b61fSWei Hu (Xavier)  */
229ff6dc76eSHuisong Li static int
hns3_mp_init_primary(void)230ff6dc76eSHuisong Li hns3_mp_init_primary(void)
23123d4b61fSWei Hu (Xavier) {
2329570b1fdSWei Hu (Xavier) 	int ret;
2339570b1fdSWei Hu (Xavier) 
234841f8693SHuisong Li 	if (process_data.init_done)
235841f8693SHuisong Li 		return 0;
236841f8693SHuisong Li 
2379570b1fdSWei Hu (Xavier) 	/* primary is allowed to not support IPC */
2389570b1fdSWei Hu (Xavier) 	ret = rte_mp_action_register(HNS3_MP_NAME, mp_primary_handle);
2399570b1fdSWei Hu (Xavier) 	if (ret && rte_errno != ENOTSUP)
2409570b1fdSWei Hu (Xavier) 		return ret;
2419570b1fdSWei Hu (Xavier) 
242841f8693SHuisong Li 	process_data.init_done = true;
2439570b1fdSWei Hu (Xavier) 
2449570b1fdSWei Hu (Xavier) 	return 0;
24523d4b61fSWei Hu (Xavier) }
24623d4b61fSWei Hu (Xavier) 
24723d4b61fSWei Hu (Xavier) /*
24823d4b61fSWei Hu (Xavier)  * Initialize by secondary process.
24923d4b61fSWei Hu (Xavier)  */
250ff6dc76eSHuisong Li static int
hns3_mp_init_secondary(void)251ff6dc76eSHuisong Li hns3_mp_init_secondary(void)
25223d4b61fSWei Hu (Xavier) {
2539570b1fdSWei Hu (Xavier) 	int ret;
2549570b1fdSWei Hu (Xavier) 
255841f8693SHuisong Li 	if (process_data.init_done)
256841f8693SHuisong Li 		return 0;
257841f8693SHuisong Li 
2589570b1fdSWei Hu (Xavier) 	ret = rte_mp_action_register(HNS3_MP_NAME, mp_secondary_handle);
259ff6dc76eSHuisong Li 	if (ret && rte_errno != ENOTSUP)
2609570b1fdSWei Hu (Xavier) 		return ret;
2619570b1fdSWei Hu (Xavier) 
262841f8693SHuisong Li 	process_data.init_done = true;
2639570b1fdSWei Hu (Xavier) 
2649570b1fdSWei Hu (Xavier) 	return 0;
26523d4b61fSWei Hu (Xavier) }
266ff6dc76eSHuisong Li 
267ff6dc76eSHuisong Li int
hns3_mp_init(struct rte_eth_dev * dev)268ff6dc76eSHuisong Li hns3_mp_init(struct rte_eth_dev *dev)
269ff6dc76eSHuisong Li {
270ff6dc76eSHuisong Li 	struct hns3_hw *hw = HNS3_DEV_PRIVATE_TO_HW(dev->data->dev_private);
271ff6dc76eSHuisong Li 	int ret;
272ff6dc76eSHuisong Li 
273ff6dc76eSHuisong Li 	if (rte_eal_process_type() != RTE_PROC_PRIMARY) {
274ff6dc76eSHuisong Li 		ret = hns3_mp_init_secondary();
275ff6dc76eSHuisong Li 		if (ret) {
276ff6dc76eSHuisong Li 			PMD_INIT_LOG(ERR, "Failed to init for secondary process, ret = %d",
277ff6dc76eSHuisong Li 				     ret);
278ff6dc76eSHuisong Li 			return ret;
279ff6dc76eSHuisong Li 		}
280*e12a0166STyler Retzlaff 		rte_atomic_fetch_add_explicit(&hw->secondary_cnt, 1, rte_memory_order_relaxed);
281ff6dc76eSHuisong Li 	} else {
282ff6dc76eSHuisong Li 		ret = hns3_mp_init_primary();
283ff6dc76eSHuisong Li 		if (ret) {
284ff6dc76eSHuisong Li 			PMD_INIT_LOG(ERR, "Failed to init for primary process, ret = %d",
285ff6dc76eSHuisong Li 				     ret);
286ff6dc76eSHuisong Li 			return ret;
287ff6dc76eSHuisong Li 		}
288ff6dc76eSHuisong Li 	}
289ff6dc76eSHuisong Li 
290ff6dc76eSHuisong Li 	process_data.eth_dev_cnt++;
291ff6dc76eSHuisong Li 
292ff6dc76eSHuisong Li 	return 0;
293ff6dc76eSHuisong Li }
294ff6dc76eSHuisong Li 
hns3_mp_uninit(struct rte_eth_dev * dev)295ff6dc76eSHuisong Li void hns3_mp_uninit(struct rte_eth_dev *dev)
296ff6dc76eSHuisong Li {
297ff6dc76eSHuisong Li 	struct hns3_hw *hw = HNS3_DEV_PRIVATE_TO_HW(dev->data->dev_private);
298ff6dc76eSHuisong Li 
299ff6dc76eSHuisong Li 	if (rte_eal_process_type() != RTE_PROC_PRIMARY)
300*e12a0166STyler Retzlaff 		rte_atomic_fetch_sub_explicit(&hw->secondary_cnt, 1, rte_memory_order_relaxed);
301ff6dc76eSHuisong Li 
302ff6dc76eSHuisong Li 	process_data.eth_dev_cnt--;
303ff6dc76eSHuisong Li 	if (process_data.eth_dev_cnt == 0) {
304ff6dc76eSHuisong Li 		rte_mp_action_unregister(HNS3_MP_NAME);
305ff6dc76eSHuisong Li 		process_data.init_done = false;
306ff6dc76eSHuisong Li 	}
307ff6dc76eSHuisong Li }
308