doc: remove references to the old build system
[dpdk.git] / drivers / net / hns3 / hns3_mp.c
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
15 static 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  */
27 static inline void
28 mp_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  */
51 static int
52 mp_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  */
69 static int
70 mp_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         eth_tx_prep_t prep = NULL;
77         struct rte_eth_dev *dev;
78         int ret;
79
80         if (!rte_eth_dev_is_valid_port(param->port_id)) {
81                 rte_errno = ENODEV;
82                 PMD_INIT_LOG(ERR, "port %d invalid port ID", param->port_id);
83                 return -rte_errno;
84         }
85         dev = &rte_eth_devices[param->port_id];
86         switch (param->type) {
87         case HNS3_MP_REQ_START_RXTX:
88                 PMD_INIT_LOG(INFO, "port %u starting datapath",
89                              dev->data->port_id);
90                 hns3_set_rxtx_function(dev);
91                 break;
92         case HNS3_MP_REQ_STOP_RXTX:
93                 PMD_INIT_LOG(INFO, "port %u stopping datapath",
94                              dev->data->port_id);
95                 hns3_set_rxtx_function(dev);
96                 break;
97         case HNS3_MP_REQ_START_TX:
98                 PMD_INIT_LOG(INFO, "port %u starting Tx datapath",
99                              dev->data->port_id);
100                 dev->tx_pkt_burst = hns3_get_tx_function(dev, &prep);
101                 dev->tx_pkt_prepare = prep;
102                 break;
103         case HNS3_MP_REQ_STOP_TX:
104                 PMD_INIT_LOG(INFO, "port %u stopping Tx datapath",
105                              dev->data->port_id);
106                 dev->tx_pkt_burst = hns3_dummy_rxtx_burst;
107                 dev->tx_pkt_prepare = NULL;
108                 break;
109         default:
110                 rte_errno = EINVAL;
111                 PMD_INIT_LOG(ERR, "port %u invalid mp request type",
112                              dev->data->port_id);
113                 return -rte_errno;
114         }
115
116         rte_mb();
117         mp_init_msg(dev, &mp_res, param->type);
118         res->result = 0;
119         ret = rte_mp_reply(&mp_res, peer);
120
121         return ret;
122 }
123
124 static bool
125 mp_req_type_is_valid(enum hns3_mp_req_type type)
126 {
127         return type == HNS3_MP_REQ_START_RXTX ||
128                 type == HNS3_MP_REQ_STOP_RXTX ||
129                 type == HNS3_MP_REQ_START_TX ||
130                 type == HNS3_MP_REQ_STOP_TX;
131 }
132
133 /*
134  * Broadcast request of stopping/starting data-path to secondary processes.
135  *
136  * @param[in] dev
137  *   Pointer to Ethernet structure.
138  * @param[in] type
139  *   Request type.
140  */
141 static void
142 mp_req_on_rxtx(struct rte_eth_dev *dev, enum hns3_mp_req_type type)
143 {
144         struct hns3_hw *hw = HNS3_DEV_PRIVATE_TO_HW(dev->data->dev_private);
145         struct rte_mp_msg mp_req;
146         struct rte_mp_msg *mp_res;
147         struct rte_mp_reply mp_rep;
148         struct hns3_mp_param *res;
149         struct timespec ts;
150         int ret;
151         int i;
152
153         if (rte_eal_process_type() == RTE_PROC_SECONDARY || !hw->secondary_cnt)
154                 return;
155         if (!mp_req_type_is_valid(type)) {
156                 hns3_err(hw, "port %u unknown request (req_type %d)",
157                          dev->data->port_id, type);
158                 return;
159         }
160         mp_init_msg(dev, &mp_req, type);
161         ts.tv_sec = HNS3_MP_REQ_TIMEOUT_SEC;
162         ts.tv_nsec = 0;
163         ret = rte_mp_request_sync(&mp_req, &mp_rep, &ts);
164         if (ret) {
165                 hns3_err(hw, "port %u failed to request stop/start Rx/Tx (%d)",
166                          dev->data->port_id, type);
167                 goto exit;
168         }
169         if (mp_rep.nb_sent != mp_rep.nb_received) {
170                 PMD_INIT_LOG(ERR,
171                         "port %u not all secondaries responded (req_type %d)",
172                         dev->data->port_id, type);
173                 goto exit;
174         }
175         for (i = 0; i < mp_rep.nb_received; i++) {
176                 mp_res = &mp_rep.msgs[i];
177                 res = (struct hns3_mp_param *)mp_res->param;
178                 if (res->result) {
179                         hns3_err(hw, "port %u request failed on secondary #%d",
180                                  dev->data->port_id, i);
181                         goto exit;
182                 }
183         }
184 exit:
185         free(mp_rep.msgs);
186 }
187
188 /*
189  * Broadcast request of starting data-path to secondary processes. The request
190  * is synchronous.
191  *
192  * @param[in] dev
193  *   Pointer to Ethernet structure.
194  */
195 void hns3_mp_req_start_rxtx(struct rte_eth_dev *dev)
196 {
197         mp_req_on_rxtx(dev, HNS3_MP_REQ_START_RXTX);
198 }
199
200 /*
201  * Broadcast request of stopping data-path to secondary processes. The request
202  * is synchronous.
203  *
204  * @param[in] dev
205  *   Pointer to Ethernet structure.
206  */
207 void hns3_mp_req_stop_rxtx(struct rte_eth_dev *dev)
208 {
209         mp_req_on_rxtx(dev, HNS3_MP_REQ_STOP_RXTX);
210 }
211
212 void
213 hns3_mp_req_stop_tx(struct rte_eth_dev *dev)
214 {
215         mp_req_on_rxtx(dev, HNS3_MP_REQ_STOP_TX);
216 }
217
218 void
219 hns3_mp_req_start_tx(struct rte_eth_dev *dev)
220 {
221         mp_req_on_rxtx(dev, HNS3_MP_REQ_START_TX);
222 }
223
224 /*
225  * Initialize by primary process.
226  */
227 int hns3_mp_init_primary(void)
228 {
229         int ret;
230
231         if (!hns3_inited) {
232                 /* primary is allowed to not support IPC */
233                 ret = rte_mp_action_register(HNS3_MP_NAME, mp_primary_handle);
234                 if (ret && rte_errno != ENOTSUP)
235                         return ret;
236
237                 hns3_inited = true;
238         }
239
240         return 0;
241 }
242
243 /*
244  * Un-initialize by primary process.
245  */
246 void hns3_mp_uninit_primary(void)
247 {
248         if (hns3_inited)
249                 rte_mp_action_unregister(HNS3_MP_NAME);
250 }
251
252 /*
253  * Initialize by secondary process.
254  */
255 int hns3_mp_init_secondary(void)
256 {
257         int ret;
258
259         if (!hns3_inited) {
260                 ret = rte_mp_action_register(HNS3_MP_NAME, mp_secondary_handle);
261                 if (ret)
262                         return ret;
263
264                 hns3_inited = true;
265         }
266
267         return 0;
268 }