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_csr.h"
7 : : #include "hinic3_eqs.h"
8 : : #include "hinic3_hw_cfg.h"
9 : : #include "hinic3_hwdev.h"
10 : : #include "hinic3_hwif.h"
11 : : #include "hinic3_mbox.h"
12 : : #include "hinic3_nic_event.h"
13 : :
14 : : #define HINIC3_MBOX_INT_DST_FUNC_SHIFT 0
15 : : #define HINIC3_MBOX_INT_DST_AEQN_SHIFT 10
16 : : #define HINIC3_MBOX_INT_SRC_RESP_AEQN_SHIFT 12
17 : : #define HINIC3_MBOX_INT_STAT_DMA_SHIFT 14
18 : : /* The size of data to be send (unit of 4 bytes). */
19 : : #define HINIC3_MBOX_INT_TX_SIZE_SHIFT 20
20 : : /* SO_RO(strong order, relax order). */
21 : : #define HINIC3_MBOX_INT_STAT_DMA_SO_RO_SHIFT 25
22 : : #define HINIC3_MBOX_INT_WB_EN_SHIFT 28
23 : :
24 : : #define HINIC3_MBOX_INT_DST_AEQN_MASK 0x3
25 : : #define HINIC3_MBOX_INT_SRC_RESP_AEQN_MASK 0x3
26 : : #define HINIC3_MBOX_INT_STAT_DMA_MASK 0x3F
27 : : #define HINIC3_MBOX_INT_TX_SIZE_MASK 0x1F
28 : : #define HINIC3_MBOX_INT_STAT_DMA_SO_RO_MASK 0x3
29 : : #define HINIC3_MBOX_INT_WB_EN_MASK 0x1
30 : :
31 : : #define HINIC3_MBOX_INT_SET(val, field) \
32 : : (((val) & HINIC3_MBOX_INT_##field##_MASK) \
33 : : << HINIC3_MBOX_INT_##field##_SHIFT)
34 : :
35 : : enum hinic3_mbox_tx_status {
36 : : TX_NOT_DONE = 1,
37 : : };
38 : :
39 : : #define HINIC3_MBOX_CTRL_TRIGGER_AEQE_SHIFT 0
40 : :
41 : : /*
42 : : * Specifies the issue request for the message data.
43 : : * 0 - Tx request is done;
44 : : * 1 - Tx request is in process.
45 : : */
46 : : #define HINIC3_MBOX_CTRL_TX_STATUS_SHIFT 1
47 : : #define HINIC3_MBOX_CTRL_DST_FUNC_SHIFT 16
48 : :
49 : : #define HINIC3_MBOX_CTRL_TRIGGER_AEQE_MASK 0x1
50 : : #define HINIC3_MBOX_CTRL_TX_STATUS_MASK 0x1
51 : : #define HINIC3_MBOX_CTRL_DST_FUNC_MASK 0x1FFF
52 : :
53 : : #define HINIC3_MBOX_CTRL_SET(val, field) \
54 : : (((val) & HINIC3_MBOX_CTRL_##field##_MASK) \
55 : : << HINIC3_MBOX_CTRL_##field##_SHIFT)
56 : :
57 : : #define MBOX_SEGLEN_MASK \
58 : : HINIC3_MSG_HEADER_SET(HINIC3_MSG_HEADER_SEG_LEN_MASK, SEG_LEN)
59 : :
60 : : #define MBOX_MSG_POLLING_TIMEOUT 500000 /* Unit is 10us. */
61 : : #define HINIC3_MBOX_COMP_TIME 40000U /* Unit is 1ms. */
62 : :
63 : : #define MBOX_MAX_BUF_SZ 2048UL
64 : : #define MBOX_HEADER_SZ 8
65 : : #define HINIC3_MBOX_DATA_SIZE (MBOX_MAX_BUF_SZ - MBOX_HEADER_SZ)
66 : :
67 : : #define MBOX_TLP_HEADER_SZ 16
68 : :
69 : : /* Mbox size is 64B, 8B for mbox_header, 8B reserved. */
70 : : #define MBOX_SEG_LEN 48
71 : : #define MBOX_SEG_LEN_ALIGN 4
72 : : #define MBOX_WB_STATUS_LEN 16UL
73 : :
74 : : /* Mbox write back status is 16B, only first 4B is used. */
75 : : #define MBOX_WB_STATUS_ERRCODE_MASK 0xFFFF
76 : : #define MBOX_WB_STATUS_MASK 0xFF
77 : : #define MBOX_WB_ERROR_CODE_MASK 0xFF00
78 : : #define MBOX_WB_STATUS_FINISHED_SUCCESS 0xFF
79 : : #define MBOX_WB_STATUS_FINISHED_WITH_ERR 0xFE
80 : : #define MBOX_WB_STATUS_NOT_FINISHED 0x00
81 : :
82 : : /* Determine the write back status. */
83 : : #define MBOX_STATUS_FINISHED(wb) \
84 : : (((wb) & MBOX_WB_STATUS_MASK) != MBOX_WB_STATUS_NOT_FINISHED)
85 : : #define MBOX_STATUS_SUCCESS(wb) \
86 : : (((wb) & MBOX_WB_STATUS_MASK) == MBOX_WB_STATUS_FINISHED_SUCCESS)
87 : : #define MBOX_STATUS_ERRCODE(wb) ((wb) & MBOX_WB_ERROR_CODE_MASK)
88 : :
89 : : /* Indicate the value related to the sequence ID. */
90 : : #define SEQ_ID_START_VAL 0
91 : : #define SEQ_ID_MAX_VAL 42
92 : :
93 : : #define DST_AEQ_IDX_DEFAULT_VAL 0
94 : : #define SRC_AEQ_IDX_DEFAULT_VAL 0
95 : : #define NO_DMA_ATTRIBUTE_VAL 0
96 : :
97 : : #define MBOX_MSG_NO_DATA_LEN 1
98 : :
99 : : /* Obtain the specified content of the mailbox. */
100 : : #define MBOX_BODY_FROM_HDR(header) ((uint8_t *)(header) + MBOX_HEADER_SZ)
101 : : #define MBOX_AREA(hwif) \
102 : : ((hwif)->cfg_regs_base + HINIC3_FUNC_CSR_MAILBOX_DATA_OFF)
103 : :
104 : : #define IS_PF_OR_PPF_SRC(src_func_idx) ((src_func_idx) < HINIC3_MAX_PF_FUNCS)
105 : :
106 : : #define MBOX_RESPONSE_ERROR 0x1
107 : : #define MBOX_MSG_ID_MASK 0xF
108 : : #define MBOX_MSG_ID(func_to_func) ((func_to_func)->send_msg_id)
109 : : #define MBOX_MSG_ID_INC(func_to_func) \
110 : : ({ \
111 : : typeof(func_to_func) __func = (func_to_func); \
112 : : MBOX_MSG_ID(__func) = (MBOX_MSG_ID(__func) + 1) & \
113 : : MBOX_MSG_ID_MASK; \
114 : : })
115 : :
116 : : /* Max message counter waits to process for one function. */
117 : : #define HINIC3_MAX_MSG_CNT_TO_PROCESS 10
118 : :
119 : : enum mbox_ordering_type { STRONG_ORDER = 0 };
120 : :
121 : : enum mbox_write_back_type { WRITE_BACK = 1 };
122 : :
123 : : enum mbox_aeq_trig_type { NOT_TRIGGER = 0, TRIGGER = 1 };
124 : :
125 : : static int send_mbox_to_func(struct hinic3_mbox *func_to_func,
126 : : enum hinic3_mod_type mod,
127 : : struct hinic3_handler_info *handler_info,
128 : : struct mbox_msg_info *msg_info);
129 : : static int send_tlp_mbox_to_func(struct hinic3_mbox *func_to_func,
130 : : enum hinic3_mod_type mod,
131 : : struct hinic3_handler_info *handler_info,
132 : : struct mbox_msg_info *msg_info);
133 : :
134 : : static int
135 : 0 : recv_vf_mbox_handler(struct hinic3_mbox *func_to_func,
136 : : struct hinic3_recv_mbox *recv_mbox, void *buf_out,
137 : : uint16_t *out_size, __rte_unused void *param)
138 : : {
139 : : int err = 0;
140 : : struct hinic3_handler_info handler_info;
141 : 0 : handler_info.cmd = recv_mbox->cmd;
142 : 0 : handler_info.buf_in = recv_mbox->mbox;
143 : 0 : handler_info.in_size = recv_mbox->mbox_len;
144 : 0 : handler_info.buf_out = buf_out;
145 : 0 : handler_info.out_size = out_size;
146 : :
147 : : /*
148 : : * Invoke the corresponding processing function according to the type of
149 : : * the received mailbox.
150 : : */
151 [ # # # # : 0 : switch (recv_mbox->mod) {
# ]
152 : 0 : case HINIC3_MOD_COMM:
153 : 0 : err = hinic3_vf_handle_pf_comm_mbox(func_to_func->hwdev,
154 : : func_to_func, &handler_info);
155 : 0 : break;
156 : 0 : case HINIC3_MOD_CFGM:
157 : 0 : err = hinic3_cfg_mbx_vf_proc_msg(func_to_func->hwdev,
158 : 0 : func_to_func->hwdev->cfg_mgmt, &handler_info);
159 : 0 : break;
160 : 0 : case HINIC3_MOD_L2NIC:
161 : 0 : err = hinic3_vf_event_handler(func_to_func->hwdev,
162 : 0 : func_to_func->hwdev->cfg_mgmt, &handler_info);
163 : 0 : break;
164 : 0 : case HINIC3_MOD_HILINK:
165 : 0 : err = hinic3_vf_mag_event_handler(func_to_func->hwdev,
166 : 0 : func_to_func->hwdev->cfg_mgmt, &handler_info);
167 : 0 : break;
168 : 0 : default:
169 : 0 : PMD_DRV_LOG(ERR, "No handler, mod: %d", recv_mbox->mod);
170 : : err = HINIC3_MBOX_VF_CMD_ERROR;
171 : 0 : break;
172 : : }
173 : :
174 : 0 : return err;
175 : : }
176 : :
177 : : /**
178 : : * Respond to the accept packet, construct a response message, and send it.
179 : : *
180 : : * @param[in] func_to_func
181 : : * Context for inter-function communication.
182 : : * @param[in] recv_mbox
183 : : * Pointer to the received inter-function mailbox structure.
184 : : * @param[in] err
185 : : * Error Code.
186 : : * @param[in] out_size
187 : : * Output Size.
188 : : * @param[in] src_func_idx
189 : : * Index of the source function.
190 : : */
191 : : static void
192 : 0 : response_for_recv_func_mbox(struct hinic3_mbox *func_to_func,
193 : : struct hinic3_recv_mbox *recv_mbox, int err,
194 : : uint16_t out_size, uint16_t src_func_idx)
195 : : {
196 : 0 : struct mbox_msg_info msg_info = {0};
197 : 0 : struct hinic3_handler_info handler_info = {
198 : 0 : .cmd = recv_mbox->cmd,
199 : 0 : .buf_in = recv_mbox->buf_out,
200 : : .in_size = out_size,
201 : : .dst_func = HINIC3_MGMT_SRC_ID,
202 : : .direction = HINIC3_MSG_RESPONSE,
203 : : .ack_type = HINIC3_MSG_NO_ACK,
204 : : };
205 [ # # ]: 0 : if (recv_mbox->ack_type == HINIC3_MSG_ACK) {
206 : 0 : msg_info.msg_id = recv_mbox->msg_info.msg_id;
207 [ # # ]: 0 : if (err)
208 : 0 : msg_info.status = HINIC3_MBOX_PF_SEND_ERR;
209 : :
210 : : /* Select the sending function based on the packet type. */
211 [ # # ]: 0 : if (IS_TLP_MBX(src_func_idx))
212 : 0 : send_tlp_mbox_to_func(func_to_func, recv_mbox->mod,
213 : : &handler_info, &msg_info);
214 : : else
215 : 0 : send_mbox_to_func(func_to_func, recv_mbox->mod,
216 : : &handler_info, &msg_info);
217 : : }
218 : 0 : }
219 : :
220 : : static bool
221 : : check_func_mbox_ack_first(uint8_t mod)
222 : : {
223 : : return mod == HINIC3_MOD_HILINK;
224 : : }
225 : :
226 : : static void
227 : 0 : recv_func_mbox_handler(struct hinic3_mbox *func_to_func, struct hinic3_recv_mbox *recv_mbox,
228 : : uint16_t src_func_idx, void *param)
229 : : {
230 : 0 : struct hinic3_hwdev *hwdev = func_to_func->hwdev;
231 : 0 : void *buf_out = recv_mbox->buf_out;
232 : : bool ack_first = false;
233 : 0 : uint16_t out_size = MBOX_MAX_BUF_SZ;
234 : : int err = 0;
235 : : /* Check whether the response is the first ACK message. */
236 : 0 : ack_first = check_func_mbox_ack_first(recv_mbox->mod);
237 [ # # # # ]: 0 : if (ack_first && recv_mbox->ack_type == HINIC3_MSG_ACK) {
238 : 0 : response_for_recv_func_mbox(func_to_func, recv_mbox, err,
239 : : out_size, src_func_idx);
240 : : }
241 : :
242 : : /* Processe mailbox information in the VF. */
243 [ # # ]: 0 : if (HINIC3_IS_VF(hwdev)) {
244 : 0 : err = recv_vf_mbox_handler(func_to_func, recv_mbox, buf_out,
245 : : &out_size, param);
246 : : } else {
247 : : err = -EINVAL;
248 : 0 : PMD_DRV_LOG(ERR,
249 : : "PMD doesn't support non-VF handle mailbox message");
250 : : }
251 : :
252 [ # # # # ]: 0 : if (!out_size || err)
253 : 0 : out_size = MBOX_MSG_NO_DATA_LEN;
254 : :
255 [ # # # # ]: 0 : if (!ack_first && recv_mbox->ack_type == HINIC3_MSG_ACK) {
256 : 0 : response_for_recv_func_mbox(func_to_func, recv_mbox, err,
257 : : out_size, src_func_idx);
258 : : }
259 : 0 : }
260 : :
261 : : /**
262 : : * Processe mailbox responses from functions.
263 : : *
264 : : * @param[in] func_to_func
265 : : * Mailbox for inter-function communication.
266 : : * @param[in] recv_mbox
267 : : * Received mailbox message.
268 : : * @return
269 : : * 0 on success, non-zero on failure.
270 : : */
271 : : static int
272 : 0 : resp_mbox_handler(struct hinic3_mbox *func_to_func,
273 : : struct hinic3_recv_mbox *recv_mbox)
274 : : {
275 : : int ret;
276 : 0 : rte_spinlock_lock(&func_to_func->mbox_lock);
277 [ # # ]: 0 : if (recv_mbox->msg_info.msg_id == func_to_func->send_msg_id &&
278 [ # # ]: 0 : func_to_func->event_flag == EVENT_START) {
279 : 0 : func_to_func->event_flag = EVENT_SUCCESS;
280 : 0 : ret = 0;
281 : : } else {
282 : 0 : PMD_DRV_LOG(ERR,
283 : : "Mbox response timeout, current send msg id(0x%x), recv msg id(0x%x), status(0x%x)",
284 : : func_to_func->send_msg_id,
285 : : recv_mbox->msg_info.msg_id,
286 : : recv_mbox->msg_info.status);
287 : : ret = HINIC3_MSG_HANDLER_RES;
288 : : }
289 : : rte_spinlock_unlock(&func_to_func->mbox_lock);
290 : 0 : return ret;
291 : : }
292 : :
293 : : /**
294 : : * Check whether the received mailbox message segment is valid.
295 : : *
296 : : * @param[out] recv_mbox
297 : : * Received mailbox message.
298 : : * @param[in] mbox_header
299 : : * Mailbox header.
300 : : * @return
301 : : * The value true indicates valid, and the value false indicates invalid.
302 : : */
303 : : static bool
304 : 0 : check_mbox_segment(struct hinic3_recv_mbox *recv_mbox, uint64_t mbox_header)
305 : : {
306 : : uint8_t seq_id, seg_len, msg_id, mod;
307 : : uint16_t src_func_idx, cmd;
308 : :
309 : : /* Get info from the mailbox header. */
310 : 0 : seq_id = HINIC3_MSG_HEADER_GET(mbox_header, SEQID);
311 : 0 : seg_len = HINIC3_MSG_HEADER_GET(mbox_header, SEG_LEN);
312 : 0 : src_func_idx = HINIC3_MSG_HEADER_GET(mbox_header, SRC_GLB_FUNC_IDX);
313 : 0 : msg_id = HINIC3_MSG_HEADER_GET(mbox_header, MSG_ID);
314 : 0 : mod = HINIC3_MSG_HEADER_GET(mbox_header, MODULE);
315 : 0 : cmd = HINIC3_MSG_HEADER_GET(mbox_header, CMD);
316 : :
317 [ # # ]: 0 : if (seq_id > SEQ_ID_MAX_VAL || seg_len > MBOX_SEG_LEN)
318 : 0 : goto seg_err;
319 : :
320 : : /* New message segment, which saves its information to recv_mbox. */
321 [ # # ]: 0 : if (seq_id == 0) {
322 : 0 : recv_mbox->seq_id = seq_id;
323 : 0 : recv_mbox->msg_info.msg_id = msg_id;
324 : 0 : recv_mbox->mod = mod;
325 : 0 : recv_mbox->cmd = cmd;
326 : : } else {
327 [ # # ]: 0 : if ((seq_id != recv_mbox->seq_id + 1) ||
328 [ # # ]: 0 : msg_id != recv_mbox->msg_info.msg_id ||
329 [ # # # # ]: 0 : mod != recv_mbox->mod || cmd != recv_mbox->cmd)
330 : 0 : goto seg_err;
331 : :
332 : 0 : recv_mbox->seq_id = seq_id;
333 : : }
334 : :
335 : : return true;
336 : :
337 : 0 : seg_err:
338 : 0 : PMD_DRV_LOG(ERR, "Mailbox segment check failed");
339 : 0 : PMD_DRV_LOG(ERR,
340 : : "src func id: 0x%x, front seg info: seq id: 0x%x, msg id: 0x%x, mod: 0x%x, cmd: 0x%x",
341 : : src_func_idx, recv_mbox->seq_id, recv_mbox->msg_info.msg_id,
342 : : recv_mbox->mod, recv_mbox->cmd);
343 : 0 : PMD_DRV_LOG(ERR,
344 : : "Current seg info: seg len: 0x%x, seq id: 0x%x, msg id: 0x%x, mod: 0x%x, cmd: 0x%x",
345 : : seg_len, seq_id, msg_id, mod, cmd);
346 : :
347 : 0 : return false;
348 : : }
349 : :
350 : : static int
351 : 0 : recv_mbox_handler(struct hinic3_mbox *func_to_func, void *header,
352 : : struct hinic3_recv_mbox *recv_mbox, void *param)
353 : : {
354 : 0 : uint64_t mbox_header = *((uint64_t *)header);
355 : 0 : void *mbox_body = MBOX_BODY_FROM_HDR(header);
356 : : uint16_t src_func_idx;
357 : : int pos;
358 : : uint8_t seq_id;
359 : : /* Obtain information from the mailbox header. */
360 : 0 : seq_id = HINIC3_MSG_HEADER_GET(mbox_header, SEQID);
361 : 0 : src_func_idx = HINIC3_MSG_HEADER_GET(mbox_header, SRC_GLB_FUNC_IDX);
362 : :
363 [ # # ]: 0 : if (!check_mbox_segment(recv_mbox, mbox_header)) {
364 : 0 : recv_mbox->seq_id = SEQ_ID_MAX_VAL;
365 : 0 : return HINIC3_MSG_HANDLER_RES;
366 : : }
367 : :
368 : 0 : pos = seq_id * MBOX_SEG_LEN;
369 : 0 : memcpy(((uint8_t *)recv_mbox->mbox + pos), mbox_body,
370 [ # # ]: 0 : HINIC3_MSG_HEADER_GET(mbox_header, SEG_LEN));
371 : :
372 [ # # ]: 0 : if (!HINIC3_MSG_HEADER_GET(mbox_header, LAST))
373 : : return HINIC3_MSG_HANDLER_RES;
374 : : /* Setting the information about the recv mailbox. */
375 : 0 : recv_mbox->cmd = HINIC3_MSG_HEADER_GET(mbox_header, CMD);
376 : 0 : recv_mbox->mod = HINIC3_MSG_HEADER_GET(mbox_header, MODULE);
377 : 0 : recv_mbox->mbox_len = HINIC3_MSG_HEADER_GET(mbox_header, MSG_LEN);
378 : 0 : recv_mbox->ack_type = HINIC3_MSG_HEADER_GET(mbox_header, NO_ACK);
379 : 0 : recv_mbox->msg_info.msg_id = HINIC3_MSG_HEADER_GET(mbox_header, MSG_ID);
380 : 0 : recv_mbox->msg_info.status = HINIC3_MSG_HEADER_GET(mbox_header, STATUS);
381 : 0 : recv_mbox->seq_id = SEQ_ID_MAX_VAL;
382 : :
383 : : /*
384 : : * If the received message is a response message, call the mbox response
385 : : * processing function.
386 : : */
387 [ # # ]: 0 : if (HINIC3_MSG_HEADER_GET(mbox_header, DIRECTION) ==
388 : : HINIC3_MSG_RESPONSE) {
389 : 0 : return resp_mbox_handler(func_to_func, recv_mbox);
390 : : }
391 : :
392 : 0 : recv_func_mbox_handler(func_to_func, recv_mbox, src_func_idx, param);
393 : 0 : return HINIC3_MSG_HANDLER_RES;
394 : : }
395 : :
396 : : static inline uint16_t
397 : : hinic3_mbox_get_index(uint64_t func)
398 : : {
399 : : return (func == HINIC3_MGMT_SRC_ID) ? HINIC3_MBOX_MPU_INDEX
400 : 0 : : HINIC3_MBOX_PF_INDEX;
401 : : }
402 : :
403 : : int
404 : 0 : hinic3_mbox_func_aeqe_handler(struct hinic3_hwdev *hwdev, uint8_t *header,
405 : : __rte_unused uint8_t size, void *param)
406 : : {
407 : : struct hinic3_mbox *func_to_func = NULL;
408 : : struct hinic3_recv_mbox *recv_mbox = NULL;
409 : 0 : uint64_t mbox_header = *((uint64_t *)header);
410 : : uint64_t src, dir;
411 : : /* Obtain the mailbox for communication between functions. */
412 : 0 : func_to_func = hwdev->func_to_func;
413 : :
414 : 0 : dir = HINIC3_MSG_HEADER_GET(mbox_header, DIRECTION);
415 : 0 : src = HINIC3_MSG_HEADER_GET(mbox_header, SRC_GLB_FUNC_IDX);
416 : :
417 : 0 : src = hinic3_mbox_get_index(src);
418 : : recv_mbox = (dir == HINIC3_MSG_DIRECT_SEND)
419 : : ? &func_to_func->mbox_send[src]
420 [ # # ]: 0 : : &func_to_func->mbox_resp[src];
421 : : /* Processing Received Mailbox info. */
422 : 0 : return recv_mbox_handler(func_to_func, header, recv_mbox, param);
423 : : }
424 : :
425 : : static void
426 : : clear_mbox_status(struct hinic3_send_mbox *mbox)
427 : : {
428 : 0 : *mbox->wb_status = 0;
429 : :
430 : : /* Clear mailbox write back status. */
431 : : rte_atomic_thread_fence(rte_memory_order_release);
432 : : }
433 : :
434 : : static void
435 : 0 : mbox_copy_header(struct hinic3_send_mbox *mbox, uint64_t *header)
436 : : {
437 : : uint32_t *data = (uint32_t *)header;
438 : : uint32_t i, idx_max = MBOX_HEADER_SZ / sizeof(uint32_t);
439 : :
440 [ # # ]: 0 : for (i = 0; i < idx_max; i++) {
441 : 0 : rte_write32(rte_cpu_to_be_32(*(data + i)),
442 [ # # ]: 0 : mbox->data + i * sizeof(uint32_t));
443 : : }
444 : 0 : }
445 : :
446 : : #define MBOX_DMA_MSG_INIT_XOR_VAL 0x5a5a5a5a
447 : : static uint32_t
448 : : mbox_dma_msg_xor(uint32_t *data, uint16_t msg_len)
449 : : {
450 : : uint32_t xor = MBOX_DMA_MSG_INIT_XOR_VAL;
451 : 0 : uint16_t dw_len = msg_len / sizeof(uint32_t);
452 : : uint16_t i;
453 : :
454 [ # # ]: 0 : for (i = 0; i < dw_len; i++)
455 : 0 : xor ^= data[i];
456 : :
457 : : return xor;
458 : : }
459 : :
460 : : static void
461 : 0 : mbox_copy_send_data_addr(struct hinic3_send_mbox *mbox, uint16_t seg_len)
462 : : {
463 : : uint32_t addr_h, addr_l, xor;
464 : :
465 : 0 : xor = mbox_dma_msg_xor(mbox->sbuff_vaddr, seg_len);
466 : 0 : addr_h = upper_32_bits(mbox->sbuff_paddr);
467 : 0 : addr_l = lower_32_bits(mbox->sbuff_paddr);
468 : :
469 [ # # ]: 0 : rte_write32(rte_cpu_to_be_32(xor), mbox->data + MBOX_HEADER_SZ);
470 : 0 : rte_write32(rte_cpu_to_be_32(addr_h),
471 [ # # ]: 0 : mbox->data + MBOX_HEADER_SZ + sizeof(uint32_t));
472 : 0 : rte_write32(rte_cpu_to_be_32(addr_l),
473 [ # # ]: 0 : mbox->data + MBOX_HEADER_SZ + 0x2 * sizeof(uint32_t));
474 : 0 : rte_write32(rte_cpu_to_be_32((uint32_t)seg_len),
475 [ # # ]: 0 : mbox->data + MBOX_HEADER_SZ + 0x3 * sizeof(uint32_t));
476 : : /* Reserved field. */
477 : 0 : rte_write32(0, mbox->data + MBOX_HEADER_SZ + 0x4 * sizeof(uint32_t));
478 : 0 : rte_write32(0, mbox->data + MBOX_HEADER_SZ + 0x5 * sizeof(uint32_t));
479 : 0 : }
480 : :
481 : : static void
482 : 0 : mbox_copy_send_data(struct hinic3_send_mbox *mbox, void *seg, uint16_t seg_len)
483 : : {
484 : : uint32_t *data = seg;
485 : : uint32_t chk_sz = sizeof(uint32_t);
486 : : uint32_t i, idx_max;
487 : 0 : uint8_t mbox_max_buf[MBOX_SEG_LEN] = {0};
488 : :
489 : : /* The mbox message should be aligned in 4 bytes. */
490 [ # # ]: 0 : if (seg_len % chk_sz) {
491 [ # # ]: 0 : if (seg_len <= sizeof(mbox_max_buf)) {
492 : 0 : memcpy(mbox_max_buf, seg, seg_len);
493 : : data = (uint32_t *)mbox_max_buf;
494 : : } else {
495 : 0 : PMD_DRV_LOG(ERR, "mbox_max_buf overflow: seg_len=%u.", seg_len);
496 : 0 : return;
497 : : }
498 : : }
499 : :
500 : 0 : idx_max = RTE_ALIGN(seg_len, chk_sz) / chk_sz;
501 : :
502 [ # # ]: 0 : for (i = 0; i < idx_max; i++) {
503 : 0 : rte_write32(rte_cpu_to_be_32(*(data + i)),
504 [ # # ]: 0 : mbox->data + MBOX_HEADER_SZ + i * sizeof(uint32_t));
505 : : }
506 : : }
507 : :
508 : : static void
509 : 0 : write_mbox_msg_attr(struct hinic3_mbox *func_to_func, uint16_t dst_func,
510 : : uint16_t dst_aeqn, uint16_t seg_len)
511 : : {
512 : : uint32_t mbox_int, mbox_ctrl;
513 : :
514 : : /* If VF, function ids must self-learning by HW(PPF=1 PF=0). */
515 [ # # # # ]: 0 : if (HINIC3_IS_VF(func_to_func->hwdev) &&
516 : : dst_func != HINIC3_MGMT_SRC_ID) {
517 [ # # ]: 0 : if (dst_func == HINIC3_HWIF_PPF_IDX(func_to_func->hwdev->hwif))
518 : : dst_func = 1;
519 : : else
520 : : dst_func = 0;
521 : : }
522 : : /* Set the interrupt attribute of the mailbox. */
523 : 0 : mbox_int = HINIC3_MBOX_INT_SET(dst_aeqn, DST_AEQN) |
524 : 0 : HINIC3_MBOX_INT_SET(0, SRC_RESP_AEQN) |
525 : : HINIC3_MBOX_INT_SET(NO_DMA_ATTRIBUTE_VAL, STAT_DMA) |
526 : 0 : HINIC3_MBOX_INT_SET(RTE_ALIGN(seg_len + MBOX_HEADER_SZ,
527 : 0 : MBOX_SEG_LEN_ALIGN) >> 2, TX_SIZE) |
528 : 0 : HINIC3_MBOX_INT_SET(STRONG_ORDER, STAT_DMA_SO_RO) |
529 : : HINIC3_MBOX_INT_SET(WRITE_BACK, WB_EN);
530 : :
531 : : /* The interrupt attribute is written to the interrupt register. */
532 : 0 : hinic3_hwif_write_reg(func_to_func->hwdev->hwif,
533 : : HINIC3_FUNC_CSR_MAILBOX_INT_OFFSET_OFF, mbox_int);
534 : :
535 : : rte_atomic_thread_fence(rte_memory_order_release); /**< Writing the mbox intr attributes */
536 : :
537 : : /* Set the control attributes of the mailbox and write to register. */
538 : : mbox_ctrl = HINIC3_MBOX_CTRL_SET(TX_NOT_DONE, TX_STATUS);
539 : : mbox_ctrl |= HINIC3_MBOX_CTRL_SET(NOT_TRIGGER, TRIGGER_AEQE);
540 : 0 : mbox_ctrl |= HINIC3_MBOX_CTRL_SET(dst_func, DST_FUNC);
541 : 0 : hinic3_hwif_write_reg(func_to_func->hwdev->hwif,
542 : : HINIC3_FUNC_CSR_MAILBOX_CONTROL_OFF, mbox_ctrl);
543 : 0 : }
544 : :
545 : : /**
546 : : * Read the value of the mailbox register of the hardware device.
547 : : *
548 : : * @param[in] hwdev
549 : : * Pointer to hardware device structure.
550 : : */
551 : : static void
552 : 0 : dump_mbox_reg(struct hinic3_hwdev *hwdev)
553 : : {
554 : : uint32_t val;
555 : : /* Read the value of the MBOX control register. */
556 : 0 : val = hinic3_hwif_read_reg(hwdev->hwif,
557 : : HINIC3_FUNC_CSR_MAILBOX_CONTROL_OFF);
558 : 0 : PMD_DRV_LOG(ERR, "Mailbox control reg: 0x%x", val);
559 : : /* Read the value of the MBOX interrupt offset register. */
560 : 0 : val = hinic3_hwif_read_reg(hwdev->hwif,
561 : : HINIC3_FUNC_CSR_MAILBOX_INT_OFFSET_OFF);
562 : 0 : PMD_DRV_LOG(ERR, "Mailbox interrupt offset: 0x%x", val);
563 : 0 : }
564 : :
565 : : static uint16_t
566 : 0 : get_mbox_status(struct hinic3_send_mbox *mbox)
567 : : {
568 : : /* Write back is 16B, but only use first 4B. */
569 [ # # ]: 0 : uint64_t wb_val = rte_be_to_cpu_64(*mbox->wb_status);
570 : :
571 : : rte_atomic_thread_fence(rte_memory_order_acquire); /**< Verify reading before check. */
572 : :
573 : 0 : return wb_val & MBOX_WB_STATUS_ERRCODE_MASK;
574 : : }
575 : :
576 : : /**
577 : : * Sending Mailbox Message Segment.
578 : : *
579 : : * @param[in] func_to_func
580 : : * Mailbox for inter-function communication.
581 : : * @param[in] header
582 : : * Mailbox header.
583 : : * @param[in] dst_func
584 : : * Indicate destination func.
585 : : * @param[in] seg
586 : : * Segment data to be sent.
587 : : * @param[in] seg_len
588 : : * Length of the segment to be sent.
589 : : * @param[in] msg_info
590 : : * Indicate the message information.
591 : : * @return
592 : : * 0 on success, non-zero on failure.
593 : : */
594 : : static int
595 : 0 : send_mbox_seg(struct hinic3_mbox *func_to_func, uint64_t header, uint16_t dst_func,
596 : : void *seg, uint16_t seg_len, __rte_unused void *msg_info)
597 : : {
598 : 0 : struct hinic3_send_mbox *send_mbox = &func_to_func->send_mbox;
599 : 0 : struct hinic3_hwdev *hwdev = func_to_func->hwdev;
600 : 0 : uint8_t num_aeqs = hwdev->hwif->attr.num_aeqs;
601 : : uint16_t dst_aeqn, wb_status = 0, errcode;
602 : 0 : uint16_t seq_dir = HINIC3_MSG_HEADER_GET(header, DIRECTION);
603 : : uint32_t cnt = 0;
604 : :
605 : : /* Mbox to mgmt cpu, hardware doesn't care dst aeq id. */
606 [ # # ]: 0 : if (num_aeqs >= 2)
607 : : dst_aeqn = (seq_dir == HINIC3_MSG_DIRECT_SEND)
608 : : ? HINIC3_ASYNC_MSG_AEQ
609 : : : HINIC3_MBOX_RSP_MSG_AEQ;
610 : : else
611 : : dst_aeqn = 0;
612 : :
613 : : clear_mbox_status(send_mbox);
614 : 0 : mbox_copy_header(send_mbox, &header);
615 : 0 : mbox_copy_send_data(send_mbox, seg, seg_len);
616 : :
617 : : /* Set mailbox msg seg len. */
618 : 0 : write_mbox_msg_attr(func_to_func, dst_func, dst_aeqn, seg_len);
619 : : rte_atomic_thread_fence(rte_memory_order_release); /**< Writing the mbox msg attributes. */
620 : :
621 : : /* Wait until the status of the mailbox changes to Complete. */
622 [ # # ]: 0 : while (cnt < MBOX_MSG_POLLING_TIMEOUT) {
623 : 0 : wb_status = get_mbox_status(send_mbox);
624 [ # # ]: 0 : if (MBOX_STATUS_FINISHED(wb_status))
625 : : break;
626 : :
627 : 0 : rte_delay_us(10);
628 : 0 : cnt++;
629 : : }
630 : :
631 [ # # ]: 0 : if (cnt == MBOX_MSG_POLLING_TIMEOUT) {
632 : 0 : PMD_DRV_LOG(ERR,
633 : : "Send mailbox segment timeout, wb status: 0x%x",
634 : : wb_status);
635 : 0 : dump_mbox_reg(hwdev);
636 : 0 : return -ETIMEDOUT;
637 : : }
638 : :
639 [ # # ]: 0 : if (!MBOX_STATUS_SUCCESS(wb_status)) {
640 : 0 : PMD_DRV_LOG(ERR,
641 : : "Send mailbox segment to function %d error, wb status: 0x%x",
642 : : dst_func, wb_status);
643 : 0 : errcode = MBOX_STATUS_ERRCODE(wb_status);
644 [ # # ]: 0 : return errcode ? errcode : -EFAULT;
645 : : }
646 : :
647 : : return 0;
648 : : }
649 : :
650 : : static int
651 : 0 : send_tlp_mbox_seg(struct hinic3_mbox *func_to_func, uint64_t header, uint16_t dst_func,
652 : : void *seg, uint16_t seg_len, __rte_unused void *msg_info)
653 : : {
654 : 0 : struct hinic3_send_mbox *send_mbox = &func_to_func->send_mbox;
655 : 0 : struct hinic3_hwdev *hwdev = func_to_func->hwdev;
656 : 0 : uint8_t num_aeqs = hwdev->hwif->attr.num_aeqs;
657 : : uint16_t dst_aeqn, errcode, wb_status = 0;
658 : 0 : uint16_t seq_dir = HINIC3_MSG_HEADER_GET(header, DIRECTION);
659 : : uint32_t cnt = 0;
660 : :
661 : : /* Mbox to mgmt cpu, hardware doesn't care dst aeq id. */
662 [ # # ]: 0 : if (num_aeqs >= 2)
663 : : dst_aeqn = (seq_dir == HINIC3_MSG_DIRECT_SEND)
664 : : ? HINIC3_ASYNC_MSG_AEQ
665 : : : HINIC3_MBOX_RSP_MSG_AEQ;
666 : : else
667 : : dst_aeqn = 0;
668 : :
669 : : clear_mbox_status(send_mbox);
670 : 0 : mbox_copy_header(send_mbox, &header);
671 : :
672 : : /* Copy data to DMA buffer. */
673 : 0 : memcpy(send_mbox->sbuff_vaddr, seg, seg_len);
674 : :
675 : : /*
676 : : * Copy data address to mailbox ctrl CSR(Control and Status Register).
677 : : */
678 : 0 : mbox_copy_send_data_addr(send_mbox, seg_len);
679 : :
680 : : /* Set mailbox msg header size. */
681 : 0 : write_mbox_msg_attr(func_to_func, dst_func, dst_aeqn, MBOX_TLP_HEADER_SZ);
682 : :
683 : : rte_atomic_thread_fence(rte_memory_order_release); /**< Writing the mbox msg attributes. */
684 : :
685 : : /* Wait until the status of the mailbox changes to Complete. */
686 [ # # ]: 0 : while (cnt < MBOX_MSG_POLLING_TIMEOUT) {
687 : 0 : wb_status = get_mbox_status(send_mbox);
688 [ # # ]: 0 : if (MBOX_STATUS_FINISHED(wb_status))
689 : : break;
690 : :
691 : 0 : rte_delay_us(10);
692 : 0 : cnt++;
693 : : }
694 : :
695 [ # # ]: 0 : if (cnt == MBOX_MSG_POLLING_TIMEOUT) {
696 : 0 : PMD_DRV_LOG(ERR,
697 : : "Send mailbox segment timeout, wb status: 0x%x",
698 : : wb_status);
699 : 0 : dump_mbox_reg(hwdev);
700 : 0 : return -ETIMEDOUT;
701 : : }
702 : :
703 [ # # ]: 0 : if (!MBOX_STATUS_SUCCESS(wb_status)) {
704 : 0 : PMD_DRV_LOG(ERR,
705 : : "Send mailbox segment to function %d error, wb status: 0x%x",
706 : : dst_func, wb_status);
707 : 0 : errcode = MBOX_STATUS_ERRCODE(wb_status);
708 [ # # ]: 0 : return errcode ? errcode : -EFAULT;
709 : : }
710 : :
711 : : return 0;
712 : : }
713 : :
714 : : static int
715 : 0 : send_mbox_to_func(struct hinic3_mbox *func_to_func, enum hinic3_mod_type mod,
716 : : struct hinic3_handler_info *handler_info, struct mbox_msg_info *msg_info)
717 : : {
718 : : int err = 0;
719 : : uint32_t seq_id = 0;
720 : : uint16_t seg_len = MBOX_SEG_LEN;
721 : 0 : uint16_t rsp_aeq_id, left = handler_info->in_size;
722 : 0 : uint8_t *msg_seg = (uint8_t *)handler_info->buf_in;
723 : : uint64_t header = 0;
724 : :
725 : : rsp_aeq_id = HINIC3_MBOX_RSP_MSG_AEQ;
726 : :
727 : : /* Set the header message. */
728 : 0 : header = HINIC3_MSG_HEADER_SET(handler_info->in_size, MSG_LEN) |
729 : 0 : HINIC3_MSG_HEADER_SET(mod, MODULE) |
730 : : HINIC3_MSG_HEADER_SET(seg_len, SEG_LEN) |
731 : 0 : HINIC3_MSG_HEADER_SET(handler_info->ack_type, NO_ACK) |
732 : : HINIC3_MSG_HEADER_SET(HINIC3_DATA_INLINE, DATA_TYPE) |
733 : 0 : HINIC3_MSG_HEADER_SET(SEQ_ID_START_VAL, SEQID) |
734 : 0 : HINIC3_MSG_HEADER_SET(NOT_LAST_SEGMENT, LAST) |
735 : 0 : HINIC3_MSG_HEADER_SET(handler_info->direction, DIRECTION) |
736 : 0 : HINIC3_MSG_HEADER_SET(handler_info->cmd, CMD) |
737 : : /* The VF's offset to it's associated PF. */
738 : 0 : HINIC3_MSG_HEADER_SET(msg_info->msg_id, MSG_ID) |
739 : : HINIC3_MSG_HEADER_SET(rsp_aeq_id, AEQ_ID) |
740 : 0 : HINIC3_MSG_HEADER_SET(HINIC3_MSG_FROM_MBOX, SOURCE) |
741 [ # # ]: 0 : HINIC3_MSG_HEADER_SET(!!msg_info->status, STATUS);
742 : : /* Loop until all messages are sent. */
743 [ # # ]: 0 : while (!(HINIC3_MSG_HEADER_GET(header, LAST))) {
744 [ # # ]: 0 : if (left <= MBOX_SEG_LEN) {
745 : 0 : header &= ~MBOX_SEGLEN_MASK;
746 : 0 : header |= HINIC3_MSG_HEADER_SET(left, SEG_LEN);
747 : 0 : header |= HINIC3_MSG_HEADER_SET(LAST_SEGMENT, LAST);
748 : :
749 : : seg_len = left;
750 : : }
751 : :
752 : 0 : err = send_mbox_seg(func_to_func, header, handler_info->dst_func,
753 : : msg_seg, seg_len, msg_info);
754 [ # # ]: 0 : if (err) {
755 : 0 : PMD_DRV_LOG(ERR,
756 : : "Send mbox seg failed, seq_id: 0x%" PRIx64,
757 : : HINIC3_MSG_HEADER_GET(header, SEQID));
758 : :
759 : 0 : goto send_err;
760 : : }
761 : :
762 : 0 : left -= MBOX_SEG_LEN;
763 : 0 : msg_seg += MBOX_SEG_LEN;
764 : :
765 : 0 : seq_id++;
766 : 0 : header &= ~(HINIC3_MSG_HEADER_SET(HINIC3_MSG_HEADER_SEQID_MASK, SEQID));
767 : 0 : header |= HINIC3_MSG_HEADER_SET(seq_id, SEQID);
768 : : }
769 : 0 : send_err:
770 : 0 : return err;
771 : : }
772 : :
773 : : static int
774 : 0 : send_tlp_mbox_to_func(struct hinic3_mbox *func_to_func, enum hinic3_mod_type mod,
775 : : struct hinic3_handler_info *handler_info, struct mbox_msg_info *msg_info)
776 : : {
777 : 0 : struct hinic3_hwdev *hwdev = func_to_func->hwdev;
778 : 0 : uint8_t *msg_seg = (uint8_t *)handler_info->buf_in;
779 : : int err = 0;
780 : : uint16_t rsp_aeq_id;
781 : : uint64_t header = 0;
782 : :
783 : : rsp_aeq_id = HINIC3_MBOX_RSP_MSG_AEQ;
784 : :
785 : : /* Set the header message. */
786 : 0 : header = HINIC3_MSG_HEADER_SET(MBOX_TLP_HEADER_SZ, MSG_LEN) |
787 : : HINIC3_MSG_HEADER_SET(MBOX_TLP_HEADER_SZ, SEG_LEN) |
788 : 0 : HINIC3_MSG_HEADER_SET(mod, MODULE) |
789 : 0 : HINIC3_MSG_HEADER_SET(LAST_SEGMENT, LAST) |
790 : 0 : HINIC3_MSG_HEADER_SET(handler_info->ack_type, NO_ACK) |
791 : : HINIC3_MSG_HEADER_SET(HINIC3_DATA_DMA, DATA_TYPE) |
792 : 0 : HINIC3_MSG_HEADER_SET(SEQ_ID_START_VAL, SEQID) |
793 : 0 : HINIC3_MSG_HEADER_SET(handler_info->direction, DIRECTION) |
794 : 0 : HINIC3_MSG_HEADER_SET(handler_info->cmd, CMD) |
795 : : /* The VF's offset to it's associated PF. */
796 : 0 : HINIC3_MSG_HEADER_SET(msg_info->msg_id, MSG_ID) |
797 : : HINIC3_MSG_HEADER_SET(rsp_aeq_id, AEQ_ID) |
798 : 0 : HINIC3_MSG_HEADER_SET(HINIC3_MSG_FROM_MBOX, SOURCE) |
799 [ # # ]: 0 : HINIC3_MSG_HEADER_SET(!!msg_info->status, STATUS) |
800 : 0 : HINIC3_MSG_HEADER_SET(hinic3_global_func_id(hwdev),
801 : : SRC_GLB_FUNC_IDX);
802 : :
803 : : /* Send a message. */
804 : 0 : err = send_tlp_mbox_seg(func_to_func, header, handler_info->dst_func,
805 : 0 : msg_seg, handler_info->in_size, msg_info);
806 [ # # ]: 0 : if (err) {
807 : 0 : PMD_DRV_LOG(ERR, "Send mbox seg failed, seq_id: 0x%" PRIx64,
808 : : HINIC3_MSG_HEADER_GET(header, SEQID));
809 : : }
810 : :
811 : 0 : return err;
812 : : }
813 : :
814 : : /**
815 : : * Set mailbox F2F(Function to Function) event status.
816 : : *
817 : : * @param[out] func_to_func
818 : : * Context for inter-function communication.
819 : : * @param[in] event_flag
820 : : * Event status enumerated value.
821 : : */
822 : : static void
823 : : set_mbox_to_func_event(struct hinic3_mbox *func_to_func,
824 : : enum mbox_event_state event_flag)
825 : : {
826 : 0 : rte_spinlock_lock(&func_to_func->mbox_lock);
827 : 0 : func_to_func->event_flag = event_flag;
828 : : rte_spinlock_unlock(&func_to_func->mbox_lock);
829 : : }
830 : :
831 : : /**
832 : : * Send data from one function to another and receive responses.
833 : : *
834 : : * @param[in] func_to_func
835 : : * Context for inter-function communication.
836 : : * @param[in] mod
837 : : * Command queue module type.
838 : : * @param[in] handler_info
839 : : * wrapped information for function
840 : : * @param[in] timeout
841 : : * Timeout interval for waiting for a response.
842 : : * @return
843 : : * 0 on success, non-zero on failure.
844 : : */
845 : : static int
846 : 0 : hinic3_mbox_to_func(struct hinic3_mbox *func_to_func, enum hinic3_mod_type mod,
847 : : struct hinic3_handler_info *handler_info, uint32_t timeout)
848 : : {
849 : : /* Use mbox_resp to hole data which responded from other function. */
850 : : struct hinic3_recv_mbox *mbox_for_resp = NULL;
851 : 0 : struct mbox_msg_info msg_info = {0};
852 : : struct hinic3_eq *aeq = NULL;
853 : : uint16_t mbox_rsp_idx;
854 : : uint32_t time;
855 : : int err;
856 : :
857 : 0 : mbox_rsp_idx = hinic3_mbox_get_index(handler_info->dst_func);
858 : 0 : mbox_for_resp = &func_to_func->mbox_resp[mbox_rsp_idx];
859 : :
860 : : /* Set message ID and start event. */
861 : 0 : msg_info.msg_id = MBOX_MSG_ID_INC(func_to_func);
862 : : set_mbox_to_func_event(func_to_func, EVENT_START);
863 : :
864 : : /* Select a function to send messages based on the dst_func type. */
865 [ # # ]: 0 : if (IS_TLP_MBX(handler_info->dst_func))
866 : 0 : err = send_tlp_mbox_to_func(func_to_func, mod, handler_info, &msg_info);
867 : : else
868 : 0 : err = send_mbox_to_func(func_to_func, mod, handler_info, &msg_info);
869 : :
870 [ # # ]: 0 : if (err) {
871 : 0 : PMD_DRV_LOG(ERR, "Send mailbox failed, msg_id: %d", msg_info.msg_id);
872 : : set_mbox_to_func_event(func_to_func, EVENT_FAIL);
873 : 0 : goto send_err;
874 : : }
875 : :
876 : : /* Wait for the response message. */
877 [ # # ]: 0 : time = timeout ? timeout : HINIC3_MBOX_COMP_TIME;
878 : 0 : aeq = &func_to_func->hwdev->aeqs->aeq[HINIC3_MBOX_RSP_MSG_AEQ];
879 : 0 : err = hinic3_aeq_poll_msg(aeq, time, NULL);
880 [ # # ]: 0 : if (err) {
881 : : set_mbox_to_func_event(func_to_func, EVENT_TIMEOUT);
882 : 0 : PMD_DRV_LOG(ERR, "Send mailbox message time out");
883 : : err = -ETIMEDOUT;
884 : 0 : goto send_err;
885 : : }
886 : :
887 : : /* Check whether mod and command of the rsp message match the sent message. */
888 [ # # # # ]: 0 : if (mod != mbox_for_resp->mod || handler_info->cmd != mbox_for_resp->cmd) {
889 : 0 : PMD_DRV_LOG(ERR,
890 : : "Invalid response mbox message, mod: 0x%x, cmd: 0x%x, expect mod: 0x%x, cmd: 0x%x",
891 : : mbox_for_resp->mod, mbox_for_resp->cmd, mod, handler_info->cmd);
892 : : err = -EFAULT;
893 : 0 : goto send_err;
894 : : }
895 : :
896 : : /* Check the response status. */
897 [ # # ]: 0 : if (mbox_for_resp->msg_info.status) {
898 : 0 : err = mbox_for_resp->msg_info.status;
899 : 0 : goto send_err;
900 : : }
901 : :
902 : : /* Check whether the length of the response message is valid. */
903 [ # # # # ]: 0 : if (handler_info->buf_out && handler_info->out_size) {
904 [ # # ]: 0 : if (*handler_info->out_size < mbox_for_resp->mbox_len) {
905 : 0 : PMD_DRV_LOG(ERR,
906 : : "Invalid response mbox message length: %d for mod: %d cmd: %d, should less than: %d",
907 : : mbox_for_resp->mbox_len, mod,
908 : : handler_info->cmd, *handler_info->out_size);
909 : : err = -EFAULT;
910 : 0 : goto send_err;
911 : : }
912 : :
913 [ # # ]: 0 : if (mbox_for_resp->mbox_len)
914 : 0 : memcpy(handler_info->buf_out, mbox_for_resp->mbox,
915 : : mbox_for_resp->mbox_len);
916 : :
917 : 0 : *handler_info->out_size = mbox_for_resp->mbox_len;
918 : : }
919 : 0 : send_err:
920 : 0 : return err;
921 : : }
922 : :
923 : : static int
924 : 0 : mbox_func_params_valid(__rte_unused struct hinic3_mbox *func_to_func,
925 : : void *buf_in, uint16_t in_size)
926 : : {
927 [ # # ]: 0 : if (!buf_in || !in_size)
928 : : return -EINVAL;
929 : :
930 [ # # ]: 0 : if (in_size > HINIC3_MBOX_DATA_SIZE) {
931 : 0 : PMD_DRV_LOG(ERR, "Mbox msg len(%d) exceed limit(%" PRIu64 ")",
932 : : in_size, HINIC3_MBOX_DATA_SIZE);
933 : 0 : return -EINVAL;
934 : : }
935 : :
936 : : return 0;
937 : : }
938 : :
939 : : int
940 : 0 : hinic3_send_mbox_to_mgmt(struct hinic3_hwdev *hwdev, enum hinic3_mod_type mod,
941 : : struct hinic3_handler_info *handler_info, uint32_t timeout)
942 : : {
943 : 0 : struct hinic3_mbox *func_to_func = hwdev->func_to_func;
944 : : int err;
945 : : /* Verify the validity of the input parameters. */
946 : 0 : err = mbox_func_params_valid(func_to_func, handler_info->buf_in, handler_info->in_size);
947 [ # # ]: 0 : if (err)
948 : : return err;
949 : :
950 : 0 : return hinic3_mbox_to_func(func_to_func, mod, handler_info, timeout);
951 : : }
952 : :
953 : : void
954 : 0 : hinic3_response_mbox_to_mgmt(struct hinic3_hwdev *hwdev, enum hinic3_mod_type mod,
955 : : struct hinic3_handler_info *handler_info, uint16_t msg_id)
956 : : {
957 : : struct mbox_msg_info msg_info;
958 : 0 : msg_info.msg_id = (uint8_t)msg_id;
959 : 0 : msg_info.status = 0;
960 : :
961 : 0 : send_tlp_mbox_to_func(hwdev->func_to_func, mod, handler_info, &msg_info);
962 : 0 : }
963 : :
964 : : static int
965 : 0 : init_mbox_info(struct hinic3_recv_mbox *mbox_info, int mbox_max_buf_sz)
966 : : {
967 : : int err;
968 : :
969 : 0 : mbox_info->seq_id = SEQ_ID_MAX_VAL;
970 : :
971 : 0 : mbox_info->mbox =
972 : 0 : rte_zmalloc("mbox", (size_t)mbox_max_buf_sz, 1); /*lint !e571*/
973 [ # # ]: 0 : if (!mbox_info->mbox)
974 : : return -ENOMEM;
975 : :
976 : 0 : mbox_info->buf_out = rte_zmalloc("mbox_buf_out",
977 : : (size_t)mbox_max_buf_sz, 1); /*lint !e571*/
978 [ # # ]: 0 : if (!mbox_info->buf_out) {
979 : : err = -ENOMEM;
980 : 0 : goto alloc_buf_out_err;
981 : : }
982 : :
983 : : return 0;
984 : :
985 : : alloc_buf_out_err:
986 : 0 : rte_free(mbox_info->mbox);
987 : :
988 : 0 : return err;
989 : : }
990 : :
991 : : static void
992 : : clean_mbox_info(struct hinic3_recv_mbox *mbox_info)
993 : : {
994 : 0 : rte_free(mbox_info->buf_out);
995 : 0 : rte_free(mbox_info->mbox);
996 : : }
997 : :
998 : : static int
999 : 0 : alloc_mbox_info(struct hinic3_recv_mbox *mbox_info, int mbox_max_buf_sz)
1000 : : {
1001 : : uint16_t func_idx, i;
1002 : : int err;
1003 : :
1004 [ # # ]: 0 : for (func_idx = 0; func_idx < HINIC3_MAX_FUNCTIONS + 1; func_idx++) {
1005 : 0 : err = init_mbox_info(&mbox_info[func_idx], mbox_max_buf_sz);
1006 [ # # ]: 0 : if (err) {
1007 : 0 : PMD_DRV_LOG(ERR, "Init mbox info failed");
1008 : 0 : goto init_mbox_info_err;
1009 : : }
1010 : : }
1011 : :
1012 : : return 0;
1013 : :
1014 : : init_mbox_info_err:
1015 [ # # ]: 0 : for (i = 0; i < func_idx; i++)
1016 : 0 : clean_mbox_info(&mbox_info[i]);
1017 : :
1018 : : return err;
1019 : : }
1020 : :
1021 : : static void
1022 : 0 : free_mbox_info(struct hinic3_recv_mbox *mbox_info)
1023 : : {
1024 : : uint16_t func_idx;
1025 : :
1026 [ # # ]: 0 : for (func_idx = 0; func_idx < HINIC3_MAX_FUNCTIONS + 1; func_idx++)
1027 : 0 : clean_mbox_info(&mbox_info[func_idx]);
1028 : 0 : }
1029 : :
1030 : : static void
1031 : : prepare_send_mbox(struct hinic3_mbox *func_to_func)
1032 : : {
1033 : : struct hinic3_send_mbox *send_mbox = &func_to_func->send_mbox;
1034 : :
1035 : 0 : send_mbox->data = MBOX_AREA(func_to_func->hwdev->hwif);
1036 : : }
1037 : :
1038 : : /**
1039 : : * Allocate memory for the write-back state of the mailbox and write to
1040 : : * register.
1041 : : *
1042 : : * @param[in] func_to_func
1043 : : * Context for inter-function communication.
1044 : : * @return
1045 : : * 0 on success, non-zero on failure.
1046 : : */
1047 : : static int
1048 : 0 : alloc_mbox_wb_status(struct hinic3_mbox *func_to_func)
1049 : : {
1050 : : struct hinic3_send_mbox *send_mbox = &func_to_func->send_mbox;
1051 : 0 : struct hinic3_hwdev *hwdev = func_to_func->hwdev;
1052 : : uint32_t addr_h, addr_l;
1053 : :
1054 : : /* Reserved DMA area. */
1055 : 0 : send_mbox->wb_mz = hinic3_dma_zone_reserve(hwdev->eth_dev,
1056 : : "wb_mz", 0, MBOX_WB_STATUS_LEN,
1057 : : RTE_CACHE_LINE_SIZE, SOCKET_ID_ANY);
1058 [ # # ]: 0 : if (!send_mbox->wb_mz)
1059 : : return -ENOMEM;
1060 : :
1061 : 0 : send_mbox->wb_vaddr = send_mbox->wb_mz->addr;
1062 : 0 : send_mbox->wb_paddr = send_mbox->wb_mz->iova;
1063 : 0 : send_mbox->wb_status = send_mbox->wb_vaddr;
1064 : :
1065 : 0 : addr_h = upper_32_bits(send_mbox->wb_paddr);
1066 : 0 : addr_l = lower_32_bits(send_mbox->wb_paddr);
1067 : :
1068 : : /* Write info to the register. */
1069 : 0 : hinic3_hwif_write_reg(hwdev->hwif, HINIC3_FUNC_CSR_MAILBOX_RESULT_H_OFF, addr_h);
1070 : 0 : hinic3_hwif_write_reg(hwdev->hwif, HINIC3_FUNC_CSR_MAILBOX_RESULT_L_OFF, addr_l);
1071 : :
1072 : 0 : return 0;
1073 : : }
1074 : :
1075 : : static void
1076 : 0 : free_mbox_wb_status(struct hinic3_mbox *func_to_func)
1077 : : {
1078 : : struct hinic3_send_mbox *send_mbox = &func_to_func->send_mbox;
1079 : 0 : struct hinic3_hwdev *hwdev = func_to_func->hwdev;
1080 : :
1081 : 0 : hinic3_hwif_write_reg(hwdev->hwif, HINIC3_FUNC_CSR_MAILBOX_RESULT_H_OFF, 0);
1082 : 0 : hinic3_hwif_write_reg(hwdev->hwif, HINIC3_FUNC_CSR_MAILBOX_RESULT_L_OFF, 0);
1083 : :
1084 : 0 : hinic3_memzone_free(send_mbox->wb_mz);
1085 : 0 : }
1086 : :
1087 : : static int
1088 : 0 : alloc_mbox_tlp_buffer(struct hinic3_mbox *func_to_func)
1089 : : {
1090 : : struct hinic3_send_mbox *send_mbox = &func_to_func->send_mbox;
1091 : 0 : struct hinic3_hwdev *hwdev = func_to_func->hwdev;
1092 : :
1093 : 0 : send_mbox->sbuff_mz = hinic3_dma_zone_reserve(hwdev->eth_dev, "sbuff_mz",
1094 : : 0, MBOX_MAX_BUF_SZ, MBOX_MAX_BUF_SZ, SOCKET_ID_ANY);
1095 [ # # ]: 0 : if (!send_mbox->sbuff_mz)
1096 : : return -ENOMEM;
1097 : :
1098 : 0 : send_mbox->sbuff_vaddr = send_mbox->sbuff_mz->addr;
1099 : 0 : send_mbox->sbuff_paddr = send_mbox->sbuff_mz->iova;
1100 : :
1101 : 0 : return 0;
1102 : : }
1103 : :
1104 : : static void
1105 : : free_mbox_tlp_buffer(struct hinic3_mbox *func_to_func)
1106 : : {
1107 : : struct hinic3_send_mbox *send_mbox = &func_to_func->send_mbox;
1108 : :
1109 : 0 : hinic3_memzone_free(send_mbox->sbuff_mz);
1110 : 0 : }
1111 : :
1112 : : /**
1113 : : * Initialize function to function communication.
1114 : : *
1115 : : * @param[in] hwdev
1116 : : * Pointer to hardware device structure.
1117 : : * @return
1118 : : * 0 on success, non-zero on failure.
1119 : : */
1120 : : int
1121 : 0 : hinic3_func_to_func_init(struct hinic3_hwdev *hwdev)
1122 : : {
1123 : : struct hinic3_mbox *func_to_func;
1124 : : int err;
1125 : :
1126 : 0 : func_to_func = rte_zmalloc("func_to_func", sizeof(*func_to_func), 1);
1127 [ # # ]: 0 : if (!func_to_func)
1128 : : return -ENOMEM;
1129 : :
1130 : 0 : hwdev->func_to_func = func_to_func;
1131 : 0 : func_to_func->hwdev = hwdev;
1132 : : rte_spinlock_init(&func_to_func->mbox_lock);
1133 : :
1134 : : /* Alloc the memory required by the mailbox. */
1135 : 0 : err = alloc_mbox_info(func_to_func->mbox_send, MBOX_MAX_BUF_SZ);
1136 [ # # ]: 0 : if (err) {
1137 : 0 : PMD_DRV_LOG(ERR, "Alloc mem for mbox_active failed");
1138 : 0 : goto alloc_mbox_for_send_err;
1139 : : }
1140 : :
1141 : 0 : err = alloc_mbox_info(func_to_func->mbox_resp, MBOX_MAX_BUF_SZ);
1142 [ # # ]: 0 : if (err) {
1143 : 0 : PMD_DRV_LOG(ERR, "Alloc mem for mbox_passive failed");
1144 : 0 : goto alloc_mbox_for_resp_err;
1145 : : }
1146 : :
1147 : 0 : err = alloc_mbox_tlp_buffer(func_to_func);
1148 [ # # ]: 0 : if (err) {
1149 : 0 : PMD_DRV_LOG(ERR, "Alloc mbox send buffer failed");
1150 : 0 : goto alloc_tlp_buffer_err;
1151 : : }
1152 : :
1153 : 0 : err = alloc_mbox_wb_status(func_to_func);
1154 [ # # ]: 0 : if (err) {
1155 : 0 : PMD_DRV_LOG(ERR, "Alloc mbox write back status failed");
1156 : 0 : goto alloc_wb_status_err;
1157 : : }
1158 : :
1159 : : prepare_send_mbox(func_to_func);
1160 : :
1161 : 0 : return 0;
1162 : :
1163 : : alloc_wb_status_err:
1164 : : free_mbox_tlp_buffer(func_to_func);
1165 : :
1166 : 0 : alloc_tlp_buffer_err:
1167 : 0 : free_mbox_info(func_to_func->mbox_resp);
1168 : :
1169 : 0 : alloc_mbox_for_resp_err:
1170 : 0 : free_mbox_info(func_to_func->mbox_send);
1171 : :
1172 : 0 : alloc_mbox_for_send_err:
1173 : 0 : rte_free(func_to_func);
1174 : :
1175 : 0 : return err;
1176 : : }
1177 : :
1178 : : void
1179 : 0 : hinic3_func_to_func_free(struct hinic3_hwdev *hwdev)
1180 : : {
1181 : 0 : struct hinic3_mbox *func_to_func = hwdev->func_to_func;
1182 : :
1183 : 0 : free_mbox_wb_status(func_to_func);
1184 : : free_mbox_tlp_buffer(func_to_func);
1185 : 0 : free_mbox_info(func_to_func->mbox_resp);
1186 : 0 : free_mbox_info(func_to_func->mbox_send);
1187 : 0 : rte_free(func_to_func);
1188 : 0 : }
|