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