596c31064af9508675807d9f4c7b288db22a154d
[dpdk.git] / drivers / net / hns3 / hns3_mp.c
1 /* SPDX-License-Identifier: BSD-3-Clause
2  * Copyright(c) 2018-2019 Hisilicon Limited.
3  */
4
5 #include <stdbool.h>
6
7 #include <rte_eal.h>
8 #include <rte_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 /*
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         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 %u 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                 rte_mb();
90                 hns3_set_rxtx_function(dev);
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  */
121 static void
122 mp_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 (!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         }
164 exit:
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  */
175 void 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  */
187 void 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  */
195 void hns3_mp_init_primary(void)
196 {
197         rte_mp_action_register(HNS3_MP_NAME, mp_primary_handle);
198 }
199
200 /*
201  * Un-initialize by primary process.
202  */
203 void hns3_mp_uninit_primary(void)
204 {
205         rte_mp_action_unregister(HNS3_MP_NAME);
206 }
207
208 /*
209  * Initialize by secondary process.
210  */
211 void hns3_mp_init_secondary(void)
212 {
213         rte_mp_action_register(HNS3_MP_NAME, mp_secondary_handle);
214 }