Branch data Line data Source code
1 : : /* SPDX-License-Identifier: BSD-3-Clause
2 : : * Copyright(c) 2018-2021 HiSilicon Limited.
3 : : */
4 : :
5 : : #include <stdlib.h>
6 : :
7 : : #include <rte_eal.h>
8 : : #include <ethdev_driver.h>
9 : : #include <rte_string_fns.h>
10 : : #include <rte_io.h>
11 : :
12 : : #include "hns3_ethdev.h"
13 : : #include "hns3_logs.h"
14 : : #include "hns3_rxtx.h"
15 : : #include "hns3_mp.h"
16 : :
17 : : /* local data for primary or secondary process. */
18 : : static struct hns3_process_local_data process_data;
19 : :
20 : : /*
21 : : * Initialize IPC message.
22 : : *
23 : : * @param[in] dev
24 : : * Pointer to Ethernet structure.
25 : : * @param[out] msg
26 : : * Pointer to message to fill in.
27 : : * @param[in] type
28 : : * Message type.
29 : : */
30 : : static inline void
31 : 0 : mp_init_msg(struct rte_eth_dev *dev, struct rte_mp_msg *msg,
32 : : enum hns3_mp_req_type type)
33 : : {
34 : : struct hns3_mp_param *param = (struct hns3_mp_param *)msg->param;
35 : :
36 : : memset(msg, 0, sizeof(*msg));
37 : 0 : strlcpy(msg->name, HNS3_MP_NAME, sizeof(msg->name));
38 : 0 : msg->len_param = sizeof(*param);
39 : 0 : param->type = type;
40 : 0 : param->port_id = dev->data->port_id;
41 : 0 : }
42 : :
43 : : /*
44 : : * IPC message handler of primary process.
45 : : *
46 : : * @param[in] dev
47 : : * Pointer to Ethernet structure.
48 : : * @param[in] peer
49 : : * Pointer to the peer socket path.
50 : : *
51 : : * @return
52 : : * 0 on success, a negative errno value otherwise and rte_errno is set.
53 : : */
54 : : static int
55 : 0 : mp_primary_handle(const struct rte_mp_msg *mp_msg __rte_unused,
56 : : const void *peer __rte_unused)
57 : : {
58 : 0 : return 0;
59 : : }
60 : :
61 : : /*
62 : : * IPC message handler of a secondary process.
63 : : *
64 : : * @param[in] dev
65 : : * Pointer to Ethernet structure.
66 : : * @param[in] peer
67 : : * Pointer to the peer socket path.
68 : : *
69 : : * @return
70 : : * 0 on success, a negative errno value otherwise and rte_errno is set.
71 : : */
72 : : static int
73 : 0 : mp_secondary_handle(const struct rte_mp_msg *mp_msg, const void *peer)
74 : : {
75 : : struct rte_mp_msg mp_res;
76 : : struct hns3_mp_param *res = (struct hns3_mp_param *)mp_res.param;
77 : : const struct hns3_mp_param *param =
78 : : (const struct hns3_mp_param *)mp_msg->param;
79 : : struct rte_eth_dev *dev;
80 : : int ret;
81 : :
82 [ # # ]: 0 : if (!rte_eth_dev_is_valid_port(param->port_id)) {
83 : 0 : rte_errno = ENODEV;
84 : 0 : PMD_INIT_LOG(ERR, "port %d invalid port ID", param->port_id);
85 : 0 : return -rte_errno;
86 : : }
87 : 0 : dev = &rte_eth_devices[param->port_id];
88 [ # # # # : 0 : switch (param->type) {
# ]
89 : 0 : case HNS3_MP_REQ_START_RXTX:
90 : 0 : PMD_INIT_LOG(INFO, "port %u starting datapath",
91 : : dev->data->port_id);
92 : 0 : hns3_start_rxtx_datapath(dev);
93 : 0 : break;
94 : 0 : case HNS3_MP_REQ_STOP_RXTX:
95 : 0 : PMD_INIT_LOG(INFO, "port %u stopping datapath",
96 : : dev->data->port_id);
97 : 0 : hns3_stop_rxtx_datapath(dev);
98 : 0 : break;
99 : 0 : case HNS3_MP_REQ_START_TX:
100 : 0 : PMD_INIT_LOG(INFO, "port %u starting Tx datapath",
101 : : dev->data->port_id);
102 : 0 : hns3_start_tx_datapath(dev);
103 : 0 : break;
104 : 0 : case HNS3_MP_REQ_STOP_TX:
105 : 0 : PMD_INIT_LOG(INFO, "port %u stopping Tx datapath",
106 : : dev->data->port_id);
107 : 0 : hns3_stop_tx_datapath(dev);
108 : 0 : break;
109 : 0 : default:
110 : 0 : rte_errno = EINVAL;
111 : 0 : PMD_INIT_LOG(ERR, "port %u invalid mp request type",
112 : : dev->data->port_id);
113 : 0 : return -rte_errno;
114 : : }
115 : :
116 : : rte_mb();
117 : 0 : mp_init_msg(dev, &mp_res, param->type);
118 : 0 : res->result = 0;
119 : 0 : ret = rte_mp_reply(&mp_res, peer);
120 : :
121 : 0 : 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 : 0 : 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 : 0 : mp_req_on_rxtx(struct rte_eth_dev *dev, enum hns3_mp_req_type type)
143 : : {
144 : 0 : 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 [ # # ]: 0 : if (rte_eal_process_type() == RTE_PROC_SECONDARY ||
154 [ # # ]: 0 : rte_atomic_load_explicit(&hw->secondary_cnt, rte_memory_order_relaxed) == 0)
155 : 0 : return;
156 : :
157 [ # # ]: 0 : if (!mp_req_type_is_valid(type)) {
158 : 0 : hns3_err(hw, "port %u unknown request (req_type %d)",
159 : : dev->data->port_id, type);
160 : 0 : return;
161 : : }
162 : 0 : mp_init_msg(dev, &mp_req, type);
163 : 0 : ts.tv_sec = HNS3_MP_REQ_TIMEOUT_SEC;
164 : 0 : ts.tv_nsec = 0;
165 : 0 : ret = rte_mp_request_sync(&mp_req, &mp_rep, &ts);
166 [ # # ]: 0 : if (ret) {
167 : 0 : hns3_err(hw, "port %u failed to request stop/start Rx/Tx (%d)",
168 : : dev->data->port_id, type);
169 : 0 : goto exit;
170 : : }
171 [ # # ]: 0 : if (mp_rep.nb_sent != mp_rep.nb_received) {
172 : 0 : PMD_INIT_LOG(ERR,
173 : : "port %u not all secondaries responded (req_type %d)",
174 : : dev->data->port_id, type);
175 : 0 : goto exit;
176 : : }
177 [ # # ]: 0 : for (i = 0; i < mp_rep.nb_received; i++) {
178 : 0 : mp_res = &mp_rep.msgs[i];
179 : : res = (struct hns3_mp_param *)mp_res->param;
180 [ # # ]: 0 : if (res->result) {
181 : 0 : hns3_err(hw, "port %u request failed on secondary #%d",
182 : : dev->data->port_id, i);
183 : 0 : goto exit;
184 : : }
185 : : }
186 : 0 : exit:
187 : 0 : free(mp_rep.msgs);
188 : : }
189 : :
190 : : /*
191 : : * Broadcast request of starting data-path to secondary processes. The request
192 : : * is synchronous.
193 : : *
194 : : * @param[in] dev
195 : : * Pointer to Ethernet structure.
196 : : */
197 : 0 : void hns3_mp_req_start_rxtx(struct rte_eth_dev *dev)
198 : : {
199 : 0 : mp_req_on_rxtx(dev, HNS3_MP_REQ_START_RXTX);
200 : 0 : }
201 : :
202 : : /*
203 : : * Broadcast request of stopping data-path to secondary processes. The request
204 : : * is synchronous.
205 : : *
206 : : * @param[in] dev
207 : : * Pointer to Ethernet structure.
208 : : */
209 : 0 : void hns3_mp_req_stop_rxtx(struct rte_eth_dev *dev)
210 : : {
211 : 0 : mp_req_on_rxtx(dev, HNS3_MP_REQ_STOP_RXTX);
212 : 0 : }
213 : :
214 : : void
215 : 0 : hns3_mp_req_stop_tx(struct rte_eth_dev *dev)
216 : : {
217 : 0 : mp_req_on_rxtx(dev, HNS3_MP_REQ_STOP_TX);
218 : 0 : }
219 : :
220 : : void
221 : 0 : hns3_mp_req_start_tx(struct rte_eth_dev *dev)
222 : : {
223 : 0 : mp_req_on_rxtx(dev, HNS3_MP_REQ_START_TX);
224 : 0 : }
225 : :
226 : : /*
227 : : * Initialize by primary process.
228 : : */
229 : : static int
230 : 0 : hns3_mp_init_primary(void)
231 : : {
232 : : int ret;
233 : :
234 [ # # ]: 0 : if (process_data.init_done)
235 : : return 0;
236 : :
237 : : /* primary is allowed to not support IPC */
238 : 0 : ret = rte_mp_action_register(HNS3_MP_NAME, mp_primary_handle);
239 [ # # # # ]: 0 : if (ret && rte_errno != ENOTSUP)
240 : : return ret;
241 : :
242 : 0 : process_data.init_done = true;
243 : :
244 : 0 : return 0;
245 : : }
246 : :
247 : : /*
248 : : * Initialize by secondary process.
249 : : */
250 : : static int
251 : 0 : hns3_mp_init_secondary(void)
252 : : {
253 : : int ret;
254 : :
255 [ # # ]: 0 : if (process_data.init_done)
256 : : return 0;
257 : :
258 : 0 : ret = rte_mp_action_register(HNS3_MP_NAME, mp_secondary_handle);
259 [ # # # # ]: 0 : if (ret && rte_errno != ENOTSUP)
260 : : return ret;
261 : :
262 : 0 : process_data.init_done = true;
263 : :
264 : 0 : return 0;
265 : : }
266 : :
267 : : int
268 : 0 : hns3_mp_init(struct rte_eth_dev *dev)
269 : : {
270 : 0 : struct hns3_hw *hw = HNS3_DEV_PRIVATE_TO_HW(dev->data->dev_private);
271 : : int ret;
272 : :
273 [ # # ]: 0 : if (rte_eal_process_type() != RTE_PROC_PRIMARY) {
274 : 0 : ret = hns3_mp_init_secondary();
275 [ # # ]: 0 : if (ret) {
276 : 0 : PMD_INIT_LOG(ERR, "Failed to init for secondary process, ret = %d",
277 : : ret);
278 : 0 : return ret;
279 : : }
280 : 0 : rte_atomic_fetch_add_explicit(&hw->secondary_cnt, 1, rte_memory_order_relaxed);
281 : : } else {
282 : 0 : ret = hns3_mp_init_primary();
283 [ # # ]: 0 : if (ret) {
284 : 0 : PMD_INIT_LOG(ERR, "Failed to init for primary process, ret = %d",
285 : : ret);
286 : 0 : return ret;
287 : : }
288 : : }
289 : :
290 : 0 : process_data.eth_dev_cnt++;
291 : :
292 : 0 : return 0;
293 : : }
294 : :
295 : 0 : void hns3_mp_uninit(struct rte_eth_dev *dev)
296 : : {
297 : 0 : struct hns3_hw *hw = HNS3_DEV_PRIVATE_TO_HW(dev->data->dev_private);
298 : :
299 [ # # ]: 0 : if (rte_eal_process_type() != RTE_PROC_PRIMARY)
300 : 0 : rte_atomic_fetch_sub_explicit(&hw->secondary_cnt, 1, rte_memory_order_relaxed);
301 : :
302 : 0 : process_data.eth_dev_cnt--;
303 [ # # ]: 0 : if (process_data.eth_dev_cnt == 0) {
304 : 0 : rte_mp_action_unregister(HNS3_MP_NAME);
305 : 0 : process_data.init_done = false;
306 : : }
307 : 0 : }
|