Branch data Line data Source code
1 : : /* SPDX-License-Identifier: BSD-3-Clause
2 : : * Copyright(c) 2025 Huawei Technologies Co., Ltd
3 : : */
4 : :
5 : : #include "hinic3_compat.h"
6 : : #include "hinic3_hwdev.h"
7 : : #include "hinic3_mbox.h"
8 : : #include "hinic3_nic_event.h"
9 : :
10 : : #define HINIC3_MSG_TO_MGMT_MAX_LEN 2016
11 : :
12 : : #define MAX_PF_MGMT_BUF_SIZE 2048UL
13 : : #define SEGMENT_LEN 48
14 : : #define MGMT_MSG_MAX_SEQ_ID \
15 : : (RTE_ALIGN(HINIC3_MSG_TO_MGMT_MAX_LEN, SEGMENT_LEN) / SEGMENT_LEN)
16 : :
17 : : #define BUF_OUT_DEFAULT_SIZE 1
18 : :
19 : : #define MGMT_MSG_SIZE_MIN 20
20 : : #define MGMT_MSG_SIZE_STEP 16
21 : : #define MGMT_MSG_RSVD_FOR_DEV 8
22 : :
23 : : static void
24 : : send_mgmt_ack(struct hinic3_msg_pf_to_mgmt *pf_to_mgmt, enum hinic3_mod_type mod,
25 : : struct hinic3_handler_info *handler_info, uint16_t msg_id)
26 : : {
27 : 0 : if (!handler_info->in_size)
28 : 0 : handler_info->in_size = BUF_OUT_DEFAULT_SIZE;
29 : :
30 : 0 : hinic3_response_mbox_to_mgmt(pf_to_mgmt->hwdev, mod, handler_info, msg_id);
31 : 0 : }
32 : :
33 : : static bool
34 : : check_mgmt_seq_id_and_seg_len(struct hinic3_recv_msg *recv_msg, uint8_t seq_id,
35 : : uint8_t seg_len, uint16_t msg_id)
36 : : {
37 : 0 : if (seq_id > MGMT_MSG_MAX_SEQ_ID || seg_len > SEGMENT_LEN)
38 : : return false;
39 : :
40 [ # # ]: 0 : if (seq_id == 0) {
41 : 0 : recv_msg->seq_id = seq_id;
42 : 0 : recv_msg->msg_id = msg_id;
43 : : } else {
44 [ # # ]: 0 : if ((seq_id != recv_msg->seq_id + 1) ||
45 [ # # ]: 0 : msg_id != recv_msg->msg_id) {
46 : 0 : recv_msg->seq_id = 0;
47 : : return false;
48 : : }
49 : :
50 : 0 : recv_msg->seq_id = seq_id;
51 : : }
52 : :
53 : : return true;
54 : : }
55 : :
56 : : static void
57 : 0 : hinic3_mgmt_recv_msg_handler(struct hinic3_msg_pf_to_mgmt *pf_to_mgmt,
58 : : struct hinic3_recv_msg *recv_msg,
59 : : __rte_unused void *param)
60 : : {
61 : 0 : void *buf_out = pf_to_mgmt->mgmt_ack_buf;
62 : : bool ack_first = false;
63 : 0 : uint16_t out_size = 0;
64 : :
65 : 0 : struct hinic3_handler_info handler_info = {
66 : 0 : .cmd = recv_msg->cmd,
67 : 0 : .buf_in = recv_msg->msg,
68 [ # # # # ]: 0 : .in_size = recv_msg->msg_len,
69 : : .buf_out = buf_out,
70 : : .out_size = &out_size,
71 : : .dst_func = HINIC3_MGMT_SRC_ID,
72 : : .direction = HINIC3_MSG_RESPONSE,
73 : : .ack_type = HINIC3_MSG_NO_ACK,
74 : : };
75 : :
76 : : memset(buf_out, 0, MAX_PF_MGMT_BUF_SIZE);
77 : :
78 : : /* Select the corresponding processing function according to the mod. */
79 [ # # # # ]: 0 : switch (recv_msg->mod) {
80 : 0 : case HINIC3_MOD_COMM:
81 : 0 : hinic3_pf_handle_mgmt_comm_event(pf_to_mgmt->hwdev,
82 : : pf_to_mgmt, &handler_info);
83 : 0 : break;
84 : 0 : case HINIC3_MOD_L2NIC:
85 : 0 : hinic3_pf_event_handler(pf_to_mgmt->hwdev,
86 : : pf_to_mgmt, &handler_info);
87 : 0 : break;
88 : 0 : case HINIC3_MOD_HILINK:
89 : 0 : hinic3_pf_mag_event_handler(pf_to_mgmt->hwdev,
90 : : pf_to_mgmt, &handler_info);
91 : 0 : break;
92 : :
93 : 0 : default:
94 : 0 : PMD_DRV_LOG(ERR,
95 : : "Not support mod, maybe need to response, mod: %d",
96 : : recv_msg->mod);
97 : 0 : break;
98 : : }
99 : :
100 [ # # ]: 0 : if (!ack_first && !recv_msg->async_mgmt_to_pf)
101 : : /* Mgmt sends async msg, sends the response. */
102 [ # # ]: 0 : send_mgmt_ack(pf_to_mgmt, recv_msg->mod, &handler_info, recv_msg->msg_id);
103 : 0 : }
104 : :
105 : : /**
106 : : * Handler a recv message from mgmt channel.
107 : : *
108 : : * @param[in] pf_to_mgmt
109 : : * PF to mgmt channel.
110 : : * @param[in] recv_msg
111 : : * Received message details.
112 : : * @param[in] param
113 : : * Customized parameter.
114 : : * @return
115 : : * 0 : When aeqe is response message.
116 : : * -1 : Default result, when wrong message or not last message.
117 : : */
118 : : static int
119 : 0 : recv_mgmt_msg_handler(struct hinic3_msg_pf_to_mgmt *pf_to_mgmt, uint8_t *header,
120 : : struct hinic3_recv_msg *recv_msg, void *param)
121 : : {
122 : 0 : uint64_t mbox_header = *((uint64_t *)header);
123 : 0 : void *msg_body = header + sizeof(mbox_header);
124 : : uint8_t seq_id, seq_len;
125 : : uint32_t offset;
126 : : uint16_t msg_id;
127 : :
128 : : /* Don't need to get anything from hw when cmd is async. */
129 [ # # ]: 0 : if (HINIC3_MSG_HEADER_GET(mbox_header, DIRECTION) ==
130 : : HINIC3_MSG_RESPONSE)
131 : : return 0;
132 : :
133 : 0 : seq_len = HINIC3_MSG_HEADER_GET(mbox_header, SEG_LEN);
134 : 0 : seq_id = HINIC3_MSG_HEADER_GET(mbox_header, SEQID);
135 : 0 : msg_id = HINIC3_MSG_HEADER_GET(mbox_header, MSG_ID);
136 : :
137 : : /* Check the consistency between seq_id and seg_len. */
138 [ # # ]: 0 : if (!check_mgmt_seq_id_and_seg_len(recv_msg, seq_id, seq_len, msg_id)) {
139 : 0 : PMD_DRV_LOG(ERR, "Mgmt msg sequence id and segment length check failed");
140 : 0 : PMD_DRV_LOG(ERR,
141 : : "front seq_id: 0x%x, current seq_id: 0x%x, seq_len: 0x%x front msg_id: %d, cur msg_id: %d",
142 : : recv_msg->seq_id, seq_id, seq_len, recv_msg->msg_id, msg_id);
143 : : /* Set seq_id to invalid seq_id. */
144 : 0 : recv_msg->seq_id = MGMT_MSG_MAX_SEQ_ID;
145 : 0 : return HINIC3_MSG_HANDLER_RES;
146 : : }
147 : :
148 : 0 : offset = seq_id * SEGMENT_LEN;
149 [ # # ]: 0 : memcpy((uint8_t *)recv_msg->msg + offset, msg_body, seq_len);
150 : :
151 [ # # ]: 0 : if (!HINIC3_MSG_HEADER_GET(mbox_header, LAST))
152 : : return HINIC3_MSG_HANDLER_RES;
153 : : /* Setting the message receiving information. */
154 : 0 : recv_msg->cmd = HINIC3_MSG_HEADER_GET(mbox_header, CMD);
155 : 0 : recv_msg->mod = HINIC3_MSG_HEADER_GET(mbox_header, MODULE);
156 : 0 : recv_msg->async_mgmt_to_pf = HINIC3_MSG_HEADER_GET(mbox_header, NO_ACK);
157 : 0 : recv_msg->msg_len = HINIC3_MSG_HEADER_GET(mbox_header, MSG_LEN);
158 : 0 : recv_msg->msg_id = HINIC3_MSG_HEADER_GET(mbox_header, MSG_ID);
159 : 0 : recv_msg->seq_id = MGMT_MSG_MAX_SEQ_ID;
160 : :
161 : 0 : hinic3_mgmt_recv_msg_handler(pf_to_mgmt, recv_msg, param);
162 : :
163 : 0 : return HINIC3_MSG_HANDLER_RES;
164 : : }
165 : :
166 : : /**
167 : : * Handler for a aeqe from mgmt channel.
168 : : *
169 : : * @param[in] hwdev
170 : : * The pointer to the private hardware device.
171 : : * @param[in] header
172 : : * The header of the message.
173 : : * @param[in] size
174 : : * Indicate size.
175 : : * @param[in] param
176 : : * Customized parameter.
177 : : * @return
178 : : * zero: When aeqe is response message
179 : : * negative: When wrong message or not last message.
180 : : */
181 : : int
182 : 0 : hinic3_mgmt_msg_aeqe_handler(struct hinic3_hwdev *hwdev, uint8_t *header,
183 : : uint8_t size, void *param)
184 : : {
185 : : struct hinic3_msg_pf_to_mgmt *pf_to_mgmt = NULL;
186 : : struct hinic3_recv_msg *recv_msg = NULL;
187 : : bool is_send_dir = false;
188 : :
189 : : /* For mbox message, invoke the mailbox processing function. */
190 [ # # ]: 0 : if ((HINIC3_MSG_HEADER_GET(*(uint64_t *)header, SOURCE) ==
191 : : HINIC3_MSG_FROM_MBOX)) {
192 : 0 : return hinic3_mbox_func_aeqe_handler(hwdev, header, size, param);
193 : : }
194 : :
195 : 0 : pf_to_mgmt = hwdev->pf_to_mgmt;
196 : :
197 : 0 : is_send_dir = (HINIC3_MSG_HEADER_GET(*(uint64_t *)header, DIRECTION) ==
198 : : HINIC3_MSG_DIRECT_SEND) ? true : false;
199 : :
200 : : /* Determine whether a message is received or responded. */
201 : : recv_msg = is_send_dir ? &pf_to_mgmt->recv_msg_from_mgmt
202 [ # # ]: 0 : : &pf_to_mgmt->recv_resp_msg_from_mgmt;
203 : :
204 : 0 : return recv_mgmt_msg_handler(pf_to_mgmt, header, recv_msg, param);
205 : : }
206 : :
207 : : /**
208 : : * Allocate received message memory.
209 : : *
210 : : * @param[in] recv_msg
211 : : * Pointer that will hold the allocated data.
212 : : * @return
213 : : * 0 on success, non-zero on failure.
214 : : */
215 : : static int
216 : : alloc_recv_msg(struct hinic3_recv_msg *recv_msg)
217 : : {
218 : 0 : recv_msg->seq_id = MGMT_MSG_MAX_SEQ_ID;
219 : :
220 : 0 : recv_msg->msg = rte_zmalloc("recv_msg", MAX_PF_MGMT_BUF_SIZE,
221 : : HINIC3_MEM_ALLOC_ALIGN_MIN);
222 [ # # # # ]: 0 : if (!recv_msg->msg)
223 : : return -ENOMEM;
224 : :
225 : : return 0;
226 : : }
227 : :
228 : : static void
229 : : free_recv_msg(struct hinic3_recv_msg *recv_msg)
230 : : {
231 : 0 : rte_free(recv_msg->msg);
232 : 0 : }
233 : :
234 : : /**
235 : : * Allocate all the message buffers of PF to mgmt channel.
236 : : *
237 : : * @param[in] pf_to_mgmt
238 : : * PF to mgmt channel.
239 : : * @return
240 : : * 0 on success, non-zero on failure.
241 : : */
242 : : static int
243 : 0 : alloc_msg_buf(struct hinic3_msg_pf_to_mgmt *pf_to_mgmt)
244 : : {
245 : : int err;
246 : :
247 : : err = alloc_recv_msg(&pf_to_mgmt->recv_msg_from_mgmt);
248 : : if (err) {
249 : 0 : PMD_DRV_LOG(ERR, "Allocate recv msg failed");
250 : 0 : return err;
251 : : }
252 : :
253 : : err = alloc_recv_msg(&pf_to_mgmt->recv_resp_msg_from_mgmt);
254 : : if (err) {
255 : 0 : PMD_DRV_LOG(ERR, "Allocate resp recv msg failed");
256 : 0 : goto alloc_msg_for_resp_err;
257 : : }
258 : :
259 : 0 : pf_to_mgmt->mgmt_ack_buf = rte_zmalloc("mgmt_ack_buf",
260 : : MAX_PF_MGMT_BUF_SIZE,
261 : : HINIC3_MEM_ALLOC_ALIGN_MIN);
262 [ # # ]: 0 : if (!pf_to_mgmt->mgmt_ack_buf) {
263 : : err = -ENOMEM;
264 : 0 : goto ack_msg_buf_err;
265 : : }
266 : :
267 : : return 0;
268 : :
269 : : ack_msg_buf_err:
270 : : free_recv_msg(&pf_to_mgmt->recv_resp_msg_from_mgmt);
271 : :
272 : 0 : alloc_msg_for_resp_err:
273 : : free_recv_msg(&pf_to_mgmt->recv_msg_from_mgmt);
274 : 0 : return err;
275 : : }
276 : :
277 : : /**
278 : : * Free all the message buffers of PF to mgmt channel.
279 : : *
280 : : * @param[in] pf_to_mgmt
281 : : * PF to mgmt channel.
282 : : */
283 : : static void
284 : 0 : free_msg_buf(struct hinic3_msg_pf_to_mgmt *pf_to_mgmt)
285 : : {
286 : 0 : rte_free(pf_to_mgmt->mgmt_ack_buf);
287 : : free_recv_msg(&pf_to_mgmt->recv_resp_msg_from_mgmt);
288 : : free_recv_msg(&pf_to_mgmt->recv_msg_from_mgmt);
289 : 0 : }
290 : :
291 : : /**
292 : : * Initialize PF to mgmt channel.
293 : : *
294 : : * @param[in] hwdev
295 : : * The pointer to the private hardware device.
296 : : * @return
297 : : * 0 on success, non-zero on failure.
298 : : */
299 : : int
300 : 0 : hinic3_pf_to_mgmt_init(struct hinic3_hwdev *hwdev)
301 : : {
302 : : struct hinic3_msg_pf_to_mgmt *pf_to_mgmt;
303 : : int err;
304 : :
305 : 0 : pf_to_mgmt = rte_zmalloc("pf_to_mgmt", sizeof(*pf_to_mgmt),
306 : : HINIC3_MEM_ALLOC_ALIGN_MIN);
307 [ # # ]: 0 : if (!pf_to_mgmt)
308 : : return -ENOMEM;
309 : :
310 : 0 : hwdev->pf_to_mgmt = pf_to_mgmt;
311 : 0 : pf_to_mgmt->hwdev = hwdev;
312 : :
313 : 0 : err = alloc_msg_buf(pf_to_mgmt);
314 [ # # ]: 0 : if (err) {
315 : 0 : PMD_DRV_LOG(ERR, "Allocate msg buffers failed");
316 : 0 : goto alloc_msg_buf_err;
317 : : }
318 : :
319 : : return 0;
320 : :
321 : : alloc_msg_buf_err:
322 : 0 : rte_free(pf_to_mgmt);
323 : :
324 : 0 : return err;
325 : : }
326 : :
327 : : /**
328 : : * Free PF to mgmt channel.
329 : : *
330 : : * @param[in] hwdev
331 : : * The pointer to the private hardware device.
332 : : */
333 : : void
334 : 0 : hinic3_pf_to_mgmt_free(struct hinic3_hwdev *hwdev)
335 : : {
336 : 0 : struct hinic3_msg_pf_to_mgmt *pf_to_mgmt = hwdev->pf_to_mgmt;
337 : :
338 : 0 : free_msg_buf(pf_to_mgmt);
339 : 0 : rte_free(pf_to_mgmt);
340 : 0 : }
|