xref: /dpdk/drivers/net/hinic/base/hinic_pmd_mbox.c (revision 68a03efeed657e6e05f281479b33b51102797e15)
1 /* SPDX-License-Identifier: BSD-3-Clause
2  * Copyright(c) 2017 Huawei Technologies Co., Ltd
3  */
4 
5 #include "hinic_compat.h"
6 #include "hinic_csr.h"
7 #include "hinic_pmd_hwdev.h"
8 #include "hinic_pmd_hwif.h"
9 #include "hinic_pmd_eqs.h"
10 #include "hinic_pmd_mgmt.h"
11 #include "hinic_pmd_mbox.h"
12 
13 #define HINIC_MBOX_INT_DST_FUNC_SHIFT				0
14 #define HINIC_MBOX_INT_DST_AEQN_SHIFT				10
15 #define HINIC_MBOX_INT_SRC_RESP_AEQN_SHIFT			12
16 #define HINIC_MBOX_INT_STAT_DMA_SHIFT				14
17 /* The size of data to be send (unit of 4 bytes) */
18 #define HINIC_MBOX_INT_TX_SIZE_SHIFT				20
19 /* SO_RO(strong order, relax order)  */
20 #define HINIC_MBOX_INT_STAT_DMA_SO_RO_SHIFT			25
21 #define HINIC_MBOX_INT_WB_EN_SHIFT				28
22 
23 
24 #define HINIC_MBOX_INT_DST_FUNC_MASK				0x3FF
25 #define HINIC_MBOX_INT_DST_AEQN_MASK				0x3
26 #define HINIC_MBOX_INT_SRC_RESP_AEQN_MASK			0x3
27 #define HINIC_MBOX_INT_STAT_DMA_MASK				0x3F
28 #define HINIC_MBOX_INT_TX_SIZE_MASK				0x1F
29 #define HINIC_MBOX_INT_STAT_DMA_SO_RO_MASK			0x3
30 #define HINIC_MBOX_INT_WB_EN_MASK				0x1
31 
32 #define HINIC_MBOX_INT_SET(val, field)	\
33 			(((val) & HINIC_MBOX_INT_##field##_MASK) << \
34 			HINIC_MBOX_INT_##field##_SHIFT)
35 
36 enum hinic_mbox_tx_status {
37 	TX_DONE = 0,
38 	TX_IN_PROGRESS,
39 };
40 
41 #define HINIC_MBOX_CTRL_TRIGGER_AEQE_SHIFT			0
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 HINIC_MBOX_CTRL_TX_STATUS_SHIFT				1
47 
48 #define HINIC_MBOX_CTRL_TRIGGER_AEQE_MASK			0x1
49 #define HINIC_MBOX_CTRL_TX_STATUS_MASK				0x1
50 
51 #define HINIC_MBOX_CTRL_SET(val, field)	\
52 			(((val) & HINIC_MBOX_CTRL_##field##_MASK) << \
53 			HINIC_MBOX_CTRL_##field##_SHIFT)
54 
55 #define HINIC_MBOX_HEADER_MSG_LEN_SHIFT				0
56 #define HINIC_MBOX_HEADER_MODULE_SHIFT				11
57 #define HINIC_MBOX_HEADER_SEG_LEN_SHIFT				16
58 #define HINIC_MBOX_HEADER_NO_ACK_SHIFT				22
59 #define HINIC_MBOX_HEADER_SEQID_SHIFT				24
60 #define HINIC_MBOX_HEADER_LAST_SHIFT				30
61 
62 #define HINIC_MBOX_HEADER_DIRECTION_SHIFT			31
63 #define HINIC_MBOX_HEADER_CMD_SHIFT				32
64 #define HINIC_MBOX_HEADER_MSG_ID_SHIFT				40
65 #define HINIC_MBOX_HEADER_STATUS_SHIFT				48
66 #define HINIC_MBOX_HEADER_SRC_GLB_FUNC_IDX_SHIFT		54
67 
68 #define HINIC_MBOX_HEADER_MSG_LEN_MASK				0x7FF
69 #define HINIC_MBOX_HEADER_MODULE_MASK				0x1F
70 #define HINIC_MBOX_HEADER_SEG_LEN_MASK				0x3F
71 #define HINIC_MBOX_HEADER_NO_ACK_MASK				0x1
72 #define HINIC_MBOX_HEADER_SEQID_MASK				0x3F
73 #define HINIC_MBOX_HEADER_LAST_MASK				0x1
74 #define HINIC_MBOX_HEADER_DIRECTION_MASK			0x1
75 #define HINIC_MBOX_HEADER_CMD_MASK				0xFF
76 #define HINIC_MBOX_HEADER_MSG_ID_MASK				0xFF
77 #define HINIC_MBOX_HEADER_STATUS_MASK				0x3F
78 #define HINIC_MBOX_HEADER_SRC_GLB_FUNC_IDX_MASK			0x3FF
79 
80 #define HINIC_MBOX_HEADER_GET(val, field)	\
81 			(((val) >> HINIC_MBOX_HEADER_##field##_SHIFT) & \
82 			HINIC_MBOX_HEADER_##field##_MASK)
83 #define HINIC_MBOX_HEADER_SET(val, field)	\
84 			((u64)((val) & HINIC_MBOX_HEADER_##field##_MASK) << \
85 			HINIC_MBOX_HEADER_##field##_SHIFT)
86 
87 #define HINIC_MBOX_COMP_TIME_MS			8000U
88 #define MBOX_MSG_POLLING_TIMEOUT_MS		5000
89 
90 /* The size unit is Bytes */
91 #define HINIC_MBOX_DATA_SIZE			2040
92 #define MBOX_MAX_BUF_SZ				2048UL
93 #define MBOX_HEADER_SZ				8
94 
95 /* MBOX size is 64B, 8B for mbox_header, 4B reserved */
96 #define MBOX_SEG_LEN				48
97 #define MBOX_SEG_LEN_ALIGN			4
98 #define MBOX_WB_STATUS_LEN			16UL
99 #define MBOX_SIZE				64
100 
101 /* mbox write back status is 16B, only first 4B is used */
102 #define MBOX_WB_STATUS_ERRCODE_MASK		0xFFFF
103 #define MBOX_WB_STATUS_MASK			0xFF
104 #define MBOX_WB_ERROR_CODE_MASK			0xFF00
105 #define MBOX_WB_STATUS_FINISHED_SUCCESS		0xFF
106 #define MBOX_WB_STATUS_FINISHED_WITH_ERR	0xFE
107 #define MBOX_WB_STATUS_NOT_FINISHED		0x00
108 
109 #define MBOX_STATUS_FINISHED(wb)	\
110 	(((wb) & MBOX_WB_STATUS_MASK) != MBOX_WB_STATUS_NOT_FINISHED)
111 #define MBOX_STATUS_SUCCESS(wb)		\
112 	(((wb) & MBOX_WB_STATUS_MASK) == MBOX_WB_STATUS_FINISHED_SUCCESS)
113 #define MBOX_STATUS_ERRCODE(wb)		\
114 	((wb) & MBOX_WB_ERROR_CODE_MASK)
115 
116 #define SEQ_ID_START_VAL			0
117 
118 #define DST_AEQ_IDX_DEFAULT_VAL			0
119 #define SRC_AEQ_IDX_DEFAULT_VAL			0
120 #define NO_DMA_ATTRIBUTE_VAL			0
121 
122 #define MBOX_MSG_NO_DATA_LEN			1
123 
124 #define FUNC_ID_OFF_SET_8B		8
125 #define FUNC_ID_OFF_SET_10B		10
126 
127 #define MBOX_BODY_FROM_HDR(header)	((u8 *)(header) + MBOX_HEADER_SZ)
128 #define MBOX_AREA(hwif)			\
129 		((hwif)->cfg_regs_base + HINIC_FUNC_CSR_MAILBOX_DATA_OFF)
130 
131 #define MBOX_RESPONSE_ERROR		0x1
132 #define MBOX_MSG_ID_MASK		0xFF
133 #define MBOX_MSG_ID(func_to_func)	((func_to_func)->send_msg_id)
134 
135 enum hinic_hwif_direction_type {
136 	/* driver send msg to up or up send msg to driver*/
137 	HINIC_HWIF_DIRECT_SEND = 0,
138 	/* after driver/up send msg to each other, then up/driver ack the msg */
139 	HINIC_HWIF_RESPONSE,
140 };
141 
142 enum mbox_send_mod {
143 	MBOX_SEND_MSG_POLL = 1
144 };
145 
146 enum mbox_seg_type {
147 	NOT_LAST_SEG,
148 	LAST_SEG,
149 };
150 
151 enum mbox_ordering_type {
152 	STRONG_ORDER,
153 	RELAX_ORDER,
154 };
155 
156 enum mbox_write_back_type {
157 	NOT_WRITE_BACK = 0,
158 	WRITE_BACK,
159 };
160 
161 enum mbox_aeq_trig_type {
162 	NOT_TRIGGER,
163 	TRIGGER,
164 };
165 
166 static int send_mbox_to_func(struct hinic_mbox_func_to_func *func_to_func,
167 				enum hinic_mod_type mod, u16 cmd, void *msg,
168 				u16 msg_len, u16 dst_func,
169 				enum hinic_hwif_direction_type direction,
170 				enum hinic_mbox_ack_type ack_type,
171 				struct mbox_msg_info *msg_info);
172 
173 static int recv_vf_mbox_handler(struct hinic_mbox_func_to_func *func_to_func,
174 				struct hinic_recv_mbox *recv_mbox,
175 				void *buf_out, u16 *out_size, void *param)
176 {
177 	int rc = 0;
178 	*out_size = 0;
179 
180 	switch (recv_mbox->mod) {
181 	case HINIC_MOD_COMM:
182 		hinic_comm_async_event_handle(func_to_func->hwdev,
183 						recv_mbox->cmd, recv_mbox->mbox,
184 						recv_mbox->mbox_len,
185 						buf_out, out_size);
186 		break;
187 	case HINIC_MOD_L2NIC:
188 		hinic_l2nic_async_event_handle(func_to_func->hwdev, param,
189 						recv_mbox->cmd, recv_mbox->mbox,
190 						recv_mbox->mbox_len,
191 						buf_out, out_size);
192 		break;
193 	default:
194 		PMD_DRV_LOG(ERR, "No handler, mod: %d", recv_mbox->mod);
195 		rc = HINIC_MBOX_VF_CMD_ERROR;
196 		break;
197 	}
198 
199 	return rc;
200 }
201 
202 static void set_mbx_msg_status(struct mbox_msg_info *msg_info, int status)
203 {
204 	if (status == HINIC_DEV_BUSY_ACTIVE_FW)
205 		msg_info->status = HINIC_MBOX_PF_BUSY_ACTIVE_FW;
206 	else if (status == HINIC_MBOX_VF_CMD_ERROR)
207 		msg_info->status = HINIC_MBOX_VF_CMD_ERROR;
208 	else if (status)
209 		msg_info->status = HINIC_MBOX_PF_SEND_ERR;
210 }
211 
212 static void recv_func_mbox_handler(struct hinic_mbox_func_to_func *func_to_func,
213 				struct hinic_recv_mbox *recv_mbox,
214 				u16 src_func_idx, void *param)
215 {
216 	struct hinic_hwdev *dev = func_to_func->hwdev;
217 	struct mbox_msg_info msg_info = { 0 };
218 	u16 out_size = MBOX_MAX_BUF_SZ;
219 	void *buf_out = recv_mbox->buf_out;
220 	int err = 0;
221 
222 	if (HINIC_IS_VF(dev)) {
223 		err = recv_vf_mbox_handler(func_to_func, recv_mbox, buf_out,
224 						&out_size, param);
225 	} else {
226 		err = -EINVAL;
227 		PMD_DRV_LOG(ERR, "PMD doesn't support non-VF handle mailbox message");
228 	}
229 
230 	if (!out_size || err)
231 		out_size = MBOX_MSG_NO_DATA_LEN;
232 
233 	if (recv_mbox->ack_type == MBOX_ACK) {
234 		msg_info.msg_id = recv_mbox->msg_info.msg_id;
235 		set_mbx_msg_status(&msg_info, err);
236 		send_mbox_to_func(func_to_func, recv_mbox->mod, recv_mbox->cmd,
237 				buf_out, out_size, src_func_idx,
238 				HINIC_HWIF_RESPONSE, MBOX_ACK, &msg_info);
239 	}
240 }
241 
242 static bool check_mbox_seq_id_and_seg_len(struct hinic_recv_mbox *recv_mbox,
243 					  u8 seq_id, u8 seg_len, u8 msg_id)
244 {
245 	if (seq_id > HINIC_SEQ_ID_MAX_VAL || seg_len > HINIC_MSG_SEG_LEN)
246 		return false;
247 
248 	if (seq_id == 0) {
249 		recv_mbox->seq_id = seq_id;
250 		recv_mbox->msg_info.msg_id = msg_id;
251 	} else {
252 		if ((seq_id != recv_mbox->seq_id + 1) ||
253 			msg_id != recv_mbox->msg_info.msg_id) {
254 			recv_mbox->seq_id = 0;
255 			return false;
256 		}
257 
258 		recv_mbox->seq_id = seq_id;
259 	}
260 
261 	return true;
262 }
263 
264 static void clear_mbox_status(struct hinic_send_mbox *mbox)
265 {
266 	/* clear mailbox write back status */
267 	*mbox->wb_status = 0;
268 	rte_wmb();
269 }
270 
271 static void mbox_copy_header(struct hinic_send_mbox *mbox, u64 *header)
272 {
273 	u32 *data = (u32 *)header;
274 	u32 i, idx_max = MBOX_HEADER_SZ / sizeof(u32);
275 
276 	for (i = 0; i < idx_max; i++)
277 		__raw_writel(*(data + i), mbox->data + i * sizeof(u32));
278 }
279 
280 static void
281 mbox_copy_send_data(struct hinic_send_mbox *mbox, void *seg, u16 seg_len)
282 {
283 	u32 *data = (u32 *)seg;
284 	u32 data_len, chk_sz = sizeof(u32);
285 	u32 i, idx_max;
286 	u8 mbox_max_buf[MBOX_SEG_LEN] = {0};
287 
288 	/* The mbox message should be aligned in 4 bytes. */
289 	if (seg_len % chk_sz) {
290 		memcpy(mbox_max_buf, seg, seg_len);
291 		data = (u32 *)mbox_max_buf;
292 	}
293 
294 	data_len = seg_len;
295 	idx_max = ALIGN(data_len, chk_sz) / chk_sz;
296 
297 	for (i = 0; i < idx_max; i++)
298 		__raw_writel(*(data + i),
299 				mbox->data + MBOX_HEADER_SZ + i * sizeof(u32));
300 }
301 
302 static int mbox_msg_ack_aeqn(struct hinic_hwdev *hwdev)
303 {
304 	u16 aeq_num = HINIC_HWIF_NUM_AEQS(hwdev->hwif);
305 	int msg_ack_aeqn;
306 
307 	if (aeq_num >= HINIC_MAX_AEQS - 1) {
308 		msg_ack_aeqn = HINIC_AEQN_2;
309 	} else if (aeq_num == HINIC_MIN_AEQS) {
310 		/* This is used for ovs */
311 		msg_ack_aeqn = HINIC_AEQN_1;
312 	} else {
313 		PMD_DRV_LOG(ERR, "Warning: Invalid aeq num: %d\n", aeq_num);
314 		msg_ack_aeqn = -1;
315 	}
316 
317 	return msg_ack_aeqn;
318 }
319 
320 static u16 mbox_msg_dst_aeqn(struct hinic_hwdev *hwdev,
321 			enum hinic_hwif_direction_type seq_dir)
322 {
323 	u16 dst_aeqn;
324 
325 	if (seq_dir == HINIC_HWIF_DIRECT_SEND)
326 		dst_aeqn = HINIC_AEQN_0;
327 	else
328 		dst_aeqn = mbox_msg_ack_aeqn(hwdev);
329 
330 	return dst_aeqn;
331 }
332 
333 static int mbox_seg_ack_aeqn(struct hinic_hwdev *hwdev)
334 {
335 	return mbox_msg_ack_aeqn(hwdev);
336 }
337 
338 static void write_mbox_msg_attr(struct hinic_mbox_func_to_func *func_to_func,
339 			u16 dst_func, u16 dst_aeqn, u16 seg_ack_aeqn,
340 			__rte_unused u16 seg_len, int poll)
341 {
342 	u32 mbox_int, mbox_ctrl;
343 
344 	mbox_int = HINIC_MBOX_INT_SET(dst_func, DST_FUNC) |
345 		HINIC_MBOX_INT_SET(dst_aeqn, DST_AEQN) |
346 		/* N/A in polling mode */
347 		HINIC_MBOX_INT_SET(seg_ack_aeqn, SRC_RESP_AEQN) |
348 		HINIC_MBOX_INT_SET(NO_DMA_ATTRIBUTE_VAL, STAT_DMA) |
349 		HINIC_MBOX_INT_SET(ALIGN(MBOX_SIZE, MBOX_SEG_LEN_ALIGN) >> 2,
350 					TX_SIZE) |
351 		HINIC_MBOX_INT_SET(STRONG_ORDER, STAT_DMA_SO_RO) |
352 		HINIC_MBOX_INT_SET(WRITE_BACK, WB_EN);
353 
354 	hinic_hwif_write_reg(func_to_func->hwdev->hwif,
355 			HINIC_FUNC_CSR_MAILBOX_INT_OFFSET_OFF, mbox_int);
356 
357 	rte_wmb();
358 	mbox_ctrl = HINIC_MBOX_CTRL_SET(TX_IN_PROGRESS, TX_STATUS);
359 
360 	if (poll)
361 		mbox_ctrl |= HINIC_MBOX_CTRL_SET(NOT_TRIGGER, TRIGGER_AEQE);
362 	else
363 		mbox_ctrl |= HINIC_MBOX_CTRL_SET(TRIGGER, TRIGGER_AEQE);
364 
365 	hinic_hwif_write_reg(func_to_func->hwdev->hwif,
366 				HINIC_FUNC_CSR_MAILBOX_CONTROL_OFF, mbox_ctrl);
367 }
368 
369 static int init_mbox_info(struct hinic_recv_mbox *mbox_info)
370 {
371 	int err;
372 
373 	mbox_info->mbox = kzalloc(MBOX_MAX_BUF_SZ, GFP_KERNEL);
374 	if (!mbox_info->mbox) {
375 		PMD_DRV_LOG(ERR, "Alloc mbox buf_in mem failed\n");
376 		return -ENOMEM;
377 	}
378 
379 	mbox_info->buf_out = kzalloc(MBOX_MAX_BUF_SZ, GFP_KERNEL);
380 	if (!mbox_info->buf_out) {
381 		PMD_DRV_LOG(ERR, "Alloc mbox buf_out mem failed\n");
382 		err = -ENOMEM;
383 		goto alloc_buf_out_err;
384 	}
385 
386 	return 0;
387 
388 alloc_buf_out_err:
389 	kfree(mbox_info->mbox);
390 
391 	return err;
392 }
393 
394 static void clean_mbox_info(struct hinic_recv_mbox *mbox_info)
395 {
396 	kfree(mbox_info->buf_out);
397 	kfree(mbox_info->mbox);
398 }
399 
400 static int alloc_mbox_info(struct hinic_recv_mbox *mbox_info)
401 {
402 	u16 func_idx, i;
403 	int err;
404 
405 	for (func_idx = 0; func_idx < HINIC_MAX_FUNCTIONS; func_idx++) {
406 		err = init_mbox_info(&mbox_info[func_idx]);
407 		if (err) {
408 			PMD_DRV_LOG(ERR, "Initialize function[%d] mailbox information failed, err: %d",
409 				    func_idx, err);
410 			goto init_mbox_info_err;
411 		}
412 	}
413 
414 	return 0;
415 
416 init_mbox_info_err:
417 	for (i = 0; i < func_idx; i++)
418 		clean_mbox_info(&mbox_info[i]);
419 
420 	return err;
421 }
422 
423 static void free_mbox_info(struct hinic_recv_mbox *mbox_info)
424 {
425 	u16 func_idx;
426 
427 	for (func_idx = 0; func_idx < HINIC_MAX_FUNCTIONS; func_idx++)
428 		clean_mbox_info(&mbox_info[func_idx]);
429 }
430 
431 static void prepare_send_mbox(struct hinic_mbox_func_to_func *func_to_func)
432 {
433 	struct hinic_send_mbox *send_mbox = &func_to_func->send_mbox;
434 
435 	send_mbox->data = MBOX_AREA(func_to_func->hwdev->hwif);
436 }
437 
438 static int alloc_mbox_wb_status(struct hinic_mbox_func_to_func *func_to_func)
439 {
440 	struct hinic_send_mbox *send_mbox = &func_to_func->send_mbox;
441 	struct hinic_hwdev *hwdev = func_to_func->hwdev;
442 	struct hinic_hwif *hwif = hwdev->hwif;
443 	u32 addr_h, addr_l;
444 
445 	send_mbox->wb_vaddr = dma_zalloc_coherent(hwdev, MBOX_WB_STATUS_LEN,
446 					&send_mbox->wb_paddr, SOCKET_ID_ANY);
447 	if (!send_mbox->wb_vaddr) {
448 		PMD_DRV_LOG(ERR, "Allocating memory for mailbox wb status failed");
449 		return -ENOMEM;
450 	}
451 	send_mbox->wb_status = (volatile u64 *)send_mbox->wb_vaddr;
452 
453 	addr_h = upper_32_bits(send_mbox->wb_paddr);
454 	addr_l = lower_32_bits(send_mbox->wb_paddr);
455 	hinic_hwif_write_reg(hwif, HINIC_FUNC_CSR_MAILBOX_RESULT_H_OFF, addr_h);
456 	hinic_hwif_write_reg(hwif, HINIC_FUNC_CSR_MAILBOX_RESULT_L_OFF, addr_l);
457 
458 	return 0;
459 }
460 
461 static void free_mbox_wb_status(struct hinic_mbox_func_to_func *func_to_func)
462 {
463 	struct hinic_send_mbox *send_mbox = &func_to_func->send_mbox;
464 	struct hinic_hwdev *hwdev = func_to_func->hwdev;
465 	struct hinic_hwif *hwif = hwdev->hwif;
466 
467 	hinic_hwif_write_reg(hwif, HINIC_FUNC_CSR_MAILBOX_RESULT_H_OFF, 0);
468 	hinic_hwif_write_reg(hwif, HINIC_FUNC_CSR_MAILBOX_RESULT_L_OFF, 0);
469 
470 	dma_free_coherent(hwdev, MBOX_WB_STATUS_LEN,
471 				send_mbox->wb_vaddr, send_mbox->wb_paddr);
472 }
473 
474 static int recv_mbox_handler(struct hinic_mbox_func_to_func *func_to_func,
475 		void *header, struct hinic_recv_mbox *recv_mbox, void *param)
476 {
477 	u64 mbox_header = *((u64 *)header);
478 	void *mbox_body = MBOX_BODY_FROM_HDR(header);
479 	u16 src_func_idx;
480 	enum hinic_hwif_direction_type direction;
481 	u8 seq_id, seg_len;
482 	u8 msg_id;
483 	u8 front_id;
484 
485 	seq_id = HINIC_MBOX_HEADER_GET(mbox_header, SEQID);
486 	seg_len = HINIC_MBOX_HEADER_GET(mbox_header, SEG_LEN);
487 	direction = HINIC_MBOX_HEADER_GET(mbox_header, DIRECTION);
488 	src_func_idx = HINIC_MBOX_HEADER_GET(mbox_header, SRC_GLB_FUNC_IDX);
489 	msg_id = HINIC_MBOX_HEADER_GET(mbox_header, MSG_ID);
490 	front_id = recv_mbox->seq_id;
491 
492 	if (!check_mbox_seq_id_and_seg_len(recv_mbox, seq_id, seg_len,
493 		msg_id)) {
494 		PMD_DRV_LOG(ERR,
495 			"Mailbox sequence and segment check failed, src func id: 0x%x, "
496 			"front id: 0x%x, current id: 0x%x, seg len: 0x%x "
497 			"front msg_id: %d, cur msg_id: %d",
498 			src_func_idx, front_id, seq_id, seg_len,
499 			recv_mbox->msg_info.msg_id, msg_id);
500 		return HINIC_ERROR;
501 	}
502 
503 	memcpy((u8 *)recv_mbox->mbox + seq_id * HINIC_MSG_SEG_LEN,
504 		mbox_body, seg_len);
505 
506 	if (!HINIC_MBOX_HEADER_GET(mbox_header, LAST))
507 		return HINIC_ERROR;
508 
509 	recv_mbox->seq_id = 0;
510 	recv_mbox->cmd = HINIC_MBOX_HEADER_GET(mbox_header, CMD);
511 	recv_mbox->mod = HINIC_MBOX_HEADER_GET(mbox_header, MODULE);
512 	recv_mbox->mbox_len = HINIC_MBOX_HEADER_GET(mbox_header, MSG_LEN);
513 	recv_mbox->ack_type = HINIC_MBOX_HEADER_GET(mbox_header, NO_ACK);
514 	recv_mbox->msg_info.msg_id = HINIC_MBOX_HEADER_GET(mbox_header, MSG_ID);
515 	recv_mbox->msg_info.status = HINIC_MBOX_HEADER_GET(mbox_header, STATUS);
516 
517 	if (direction == HINIC_HWIF_RESPONSE) {
518 		if (recv_mbox->msg_info.msg_id == func_to_func->send_msg_id &&
519 			func_to_func->event_flag == EVENT_START) {
520 			return HINIC_OK;
521 		}
522 
523 		PMD_DRV_LOG(ERR, "Mbox response timeout, current send msg id(0x%x), recv msg id(0x%x), status(0x%x)",
524 			func_to_func->send_msg_id, recv_mbox->msg_info.msg_id,
525 			recv_mbox->msg_info.status);
526 		return HINIC_ERROR;
527 	}
528 
529 	recv_func_mbox_handler(func_to_func, recv_mbox, src_func_idx, param);
530 
531 	return HINIC_ERROR;
532 }
533 
534 /**
535  * hinic_mbox_func_aeqe_handler - Process mbox info from func which is
536  * sent by aeqe.
537  *
538  * @param handle
539  *   Pointer to hradware nic device.
540  * @param header
541  *   Mbox header info.
542  * @param size
543  *   The size of aeqe descriptor.
544  * @param param
545  *   customized parameter.
546  *
547  * @return
548  *   0 on success, negative error value otherwise.
549  */
550 int hinic_mbox_func_aeqe_handler(void *handle, u8 *header,
551 					__rte_unused u8 size, void *param)
552 {
553 	struct hinic_mbox_func_to_func *func_to_func =
554 				((struct hinic_hwdev *)handle)->func_to_func;
555 	struct hinic_recv_mbox *recv_mbox;
556 	u64 mbox_header = *((u64 *)header);
557 	u16 src = HINIC_MBOX_HEADER_GET(mbox_header, SRC_GLB_FUNC_IDX);
558 
559 	if (src >= HINIC_MAX_FUNCTIONS) {
560 		PMD_DRV_LOG(ERR, "Mailbox source function id: %d is invalid",
561 				src);
562 		return HINIC_ERROR;
563 	}
564 
565 	recv_mbox = (HINIC_MBOX_HEADER_GET(mbox_header, DIRECTION) ==
566 			HINIC_HWIF_DIRECT_SEND) ?
567 			&func_to_func->mbox_send[src] :
568 			&func_to_func->mbox_resp[src];
569 
570 	return recv_mbox_handler(func_to_func, (u64 *)header, recv_mbox, param);
571 }
572 
573 static u16 get_mbox_status(struct hinic_send_mbox *mbox)
574 {
575 	/* write back is 16B, but only use first 4B */
576 	u64 wb_val = be64_to_cpu(*mbox->wb_status);
577 
578 	rte_rmb(); /* verify reading before check */
579 
580 	return (u16)(wb_val & MBOX_WB_STATUS_ERRCODE_MASK);
581 }
582 
583 static void dump_mox_reg(struct hinic_hwdev *hwdev)
584 {
585 	u32 val;
586 
587 	val = hinic_hwif_read_reg(hwdev->hwif,
588 					HINIC_FUNC_CSR_MAILBOX_CONTROL_OFF);
589 	PMD_DRV_LOG(WARNING, "Mailbox control reg: 0x%x", val);
590 	val = hinic_hwif_read_reg(hwdev->hwif,
591 					HINIC_FUNC_CSR_MAILBOX_INT_OFFSET_OFF);
592 	PMD_DRV_LOG(WARNING, "Mailbox interrupt offset: 0x%x", val);
593 }
594 
595 static int send_mbox_seg(struct hinic_mbox_func_to_func *func_to_func,
596 			 u64 header, u16 dst_func, void *seg, u16 seg_len)
597 {
598 	struct hinic_send_mbox *send_mbox = &func_to_func->send_mbox;
599 	struct hinic_hwdev *hwdev = func_to_func->hwdev;
600 	u16 seq_dir = HINIC_MBOX_HEADER_GET(header, DIRECTION);
601 	u16 dst_aeqn, seg_ack_aeqn;
602 	u16 err_code, wb_status = 0;
603 	u32 cnt = 0;
604 
605 	dst_aeqn = mbox_msg_dst_aeqn(hwdev, seq_dir);
606 	seg_ack_aeqn = mbox_seg_ack_aeqn(hwdev);
607 
608 	clear_mbox_status(send_mbox);
609 
610 	mbox_copy_header(send_mbox, &header);
611 
612 	mbox_copy_send_data(send_mbox, seg, seg_len);
613 
614 	write_mbox_msg_attr(func_to_func, dst_func, dst_aeqn, seg_ack_aeqn,
615 				seg_len, MBOX_SEND_MSG_POLL);
616 
617 	rte_wmb();
618 
619 	while (cnt < MBOX_MSG_POLLING_TIMEOUT_MS) {
620 		wb_status = get_mbox_status(send_mbox);
621 		if (MBOX_STATUS_FINISHED(wb_status))
622 			break;
623 
624 		rte_delay_ms(1); /* loop every ms */
625 		cnt++;
626 	}
627 
628 	if (cnt == MBOX_MSG_POLLING_TIMEOUT_MS) {
629 		PMD_DRV_LOG(ERR, "Send mailbox segment timeout, wb status: 0x%x",
630 				wb_status);
631 		dump_mox_reg(hwdev);
632 		return -ETIMEDOUT;
633 	}
634 
635 	if (!MBOX_STATUS_SUCCESS(wb_status)) {
636 		PMD_DRV_LOG(ERR, "Send mailbox segment to function %d error, wb status: 0x%x",
637 				dst_func, wb_status);
638 		/*
639 		 * err_code: 0 responses no errors, other values can
640 		 * refer to FS doc.
641 		 */
642 		err_code = MBOX_STATUS_ERRCODE(wb_status);
643 		return err_code ? err_code : -EFAULT;
644 	}
645 
646 	return 0;
647 }
648 
649 static void set_mbox_to_func_event(struct hinic_mbox_func_to_func *func_to_func,
650 				   enum mbox_event_state event_flag)
651 {
652 	spin_lock(&func_to_func->mbox_lock);
653 	func_to_func->event_flag = event_flag;
654 	spin_unlock(&func_to_func->mbox_lock);
655 }
656 
657 static int send_mbox_to_func(struct hinic_mbox_func_to_func *func_to_func,
658 				enum hinic_mod_type mod, u16 cmd, void *msg,
659 				u16 msg_len, u16 dst_func,
660 				enum hinic_hwif_direction_type direction,
661 				enum hinic_mbox_ack_type ack_type,
662 				struct mbox_msg_info *msg_info)
663 {
664 	struct hinic_hwdev *hwdev = func_to_func->hwdev;
665 	int err = 0;
666 	u32 seq_id = 0;
667 	u16 seg_len = HINIC_MSG_SEG_LEN;
668 	u16 left = msg_len;
669 	u8 *msg_seg = (u8 *)msg;
670 	u64 header = 0;
671 
672 	err = hinic_mutex_lock(&func_to_func->msg_send_mutex);
673 	if (err)
674 		return err;
675 
676 	header = HINIC_MBOX_HEADER_SET(msg_len, MSG_LEN) |
677 		HINIC_MBOX_HEADER_SET(mod, MODULE) |
678 		HINIC_MBOX_HEADER_SET(seg_len, SEG_LEN) |
679 		HINIC_MBOX_HEADER_SET(ack_type, NO_ACK) |
680 		HINIC_MBOX_HEADER_SET(SEQ_ID_START_VAL, SEQID) |
681 		HINIC_MBOX_HEADER_SET(NOT_LAST_SEG, LAST) |
682 		HINIC_MBOX_HEADER_SET(direction, DIRECTION) |
683 		HINIC_MBOX_HEADER_SET(cmd, CMD) |
684 		HINIC_MBOX_HEADER_SET(msg_info->msg_id, MSG_ID) |
685 		HINIC_MBOX_HEADER_SET(msg_info->status, STATUS) |
686 		HINIC_MBOX_HEADER_SET(hinic_global_func_id(hwdev),
687 					SRC_GLB_FUNC_IDX);
688 
689 	while (!(HINIC_MBOX_HEADER_GET(header, LAST))) {
690 		if (left <= HINIC_MSG_SEG_LEN) {
691 			header &=
692 			~(HINIC_MBOX_HEADER_SET(HINIC_MBOX_HEADER_SEG_LEN_MASK,
693 						SEG_LEN));
694 			header |= HINIC_MBOX_HEADER_SET(left, SEG_LEN);
695 			header |= HINIC_MBOX_HEADER_SET(LAST_SEG, LAST);
696 
697 			seg_len = left;
698 		}
699 
700 		err = send_mbox_seg(func_to_func, header, dst_func, msg_seg,
701 				    seg_len);
702 		if (err) {
703 			PMD_DRV_LOG(ERR, "Fail to send mbox seg, err: %d", err);
704 			goto send_err;
705 		}
706 
707 		left -= HINIC_MSG_SEG_LEN;
708 		msg_seg += HINIC_MSG_SEG_LEN;
709 
710 		seq_id++;
711 		header &= ~(HINIC_MBOX_HEADER_SET(HINIC_MBOX_HEADER_SEQID_MASK,
712 							SEQID));
713 		header |= HINIC_MBOX_HEADER_SET(seq_id, SEQID);
714 	}
715 
716 send_err:
717 	(void)hinic_mutex_unlock(&func_to_func->msg_send_mutex);
718 
719 	return err;
720 }
721 
722 static int hinic_mbox_to_func(struct hinic_mbox_func_to_func *func_to_func,
723 			enum hinic_mod_type mod, u16 cmd, u16 dst_func,
724 			void *buf_in, u16 in_size, void *buf_out, u16 *out_size,
725 			u32 timeout)
726 {
727 	struct hinic_recv_mbox *mbox_for_resp =
728 					&func_to_func->mbox_resp[dst_func];
729 	struct mbox_msg_info msg_info = {0};
730 	u32 time;
731 	int err;
732 
733 	err = hinic_mutex_lock(&func_to_func->mbox_send_mutex);
734 	if (err)
735 		return err;
736 
737 	msg_info.msg_id = (MBOX_MSG_ID(func_to_func) + 1) & MBOX_MSG_ID_MASK;
738 	MBOX_MSG_ID(func_to_func) = msg_info.msg_id;
739 
740 	set_mbox_to_func_event(func_to_func, EVENT_START);
741 
742 	err = send_mbox_to_func(func_to_func, mod, cmd, buf_in, in_size,
743 				dst_func, HINIC_HWIF_DIRECT_SEND,
744 				MBOX_ACK, &msg_info);
745 	if (err)
746 		goto send_err;
747 
748 	time = msecs_to_jiffies(timeout ? timeout : HINIC_MBOX_COMP_TIME_MS);
749 	err = hinic_aeq_poll_msg(func_to_func->ack_aeq, time, NULL);
750 	if (err) {
751 		set_mbox_to_func_event(func_to_func, EVENT_TIMEOUT);
752 		PMD_DRV_LOG(ERR, "Send mailbox message time out");
753 		err = -ETIMEDOUT;
754 		goto send_err;
755 	}
756 
757 	set_mbox_to_func_event(func_to_func, EVENT_END);
758 
759 	if (mbox_for_resp->msg_info.status) {
760 		err = mbox_for_resp->msg_info.status;
761 		if (err != HINIC_MBOX_PF_BUSY_ACTIVE_FW)
762 			PMD_DRV_LOG(ERR, "Mailbox response error: 0x%x",
763 					mbox_for_resp->msg_info.status);
764 		else
765 			PMD_DRV_LOG(ERR, "Chip is in active, PF can't process VF message");
766 		goto send_err;
767 	}
768 
769 	rte_rmb();
770 
771 	if (mbox_for_resp->mbox_len && buf_out && out_size) {
772 		if (mbox_for_resp->mbox_len <= *out_size) {
773 			memcpy(buf_out, mbox_for_resp->mbox,
774 				mbox_for_resp->mbox_len);
775 			*out_size = mbox_for_resp->mbox_len;
776 		} else {
777 			PMD_DRV_LOG(ERR, "Mailbox response message len[%u] overflow",
778 					mbox_for_resp->mbox_len);
779 			err = -ERANGE;
780 		}
781 	}
782 
783 send_err:
784 	if (err && out_size)
785 		*out_size = 0;
786 	(void)hinic_mutex_unlock(&func_to_func->mbox_send_mutex);
787 
788 	return err;
789 }
790 
791 static int
792 mbox_func_params_valid(__rte_unused struct hinic_mbox_func_to_func *mbox_obj,
793 			void *buf_in, u16 in_size)
794 {
795 	if (!buf_in || !in_size)
796 		return -EINVAL;
797 
798 	if (in_size > HINIC_MBOX_DATA_SIZE) {
799 		PMD_DRV_LOG(ERR, "Mailbox message len(%d) exceed limit(%d)",
800 				in_size, HINIC_MBOX_DATA_SIZE);
801 		return -EINVAL;
802 	}
803 
804 	return 0;
805 }
806 
807 static u8 hinic_pf_id_of_vf(void *hwdev)
808 {
809 	struct hinic_hwif *hwif = ((struct hinic_hwdev *)hwdev)->hwif;
810 	return hwif->attr.port_to_port_idx;
811 }
812 
813 /**
814  * hinic_mbox_to_pf - Send mbox info to pf and need pf to response.
815  *
816  * @param hwdev
817  *   Pointer to hardware nic device.
818  * @param mod
819  *   Mode type of hardware.
820  * @param cmd
821  *   The command sent to pf.
822  * @param buf_in
823  *   Input parameter.
824  * @param in_size
825  *   Input parameter size.
826  * @param buf_out
827  *   Output parameter.
828  * @param out_size
829  *   Output parameter size.
830  * @param timeout
831  *   Timeout.
832  *
833  * @return
834  *   0 on success, negative error value otherwise.
835  */
836 int hinic_mbox_to_pf(struct hinic_hwdev *hwdev,
837 		      enum hinic_mod_type mod, u8 cmd, void *buf_in,
838 		      u16 in_size, void *buf_out, u16 *out_size, u32 timeout)
839 {
840 	struct hinic_mbox_func_to_func *func_to_func = hwdev->func_to_func;
841 	int err;
842 
843 	err = mbox_func_params_valid(func_to_func, buf_in, in_size);
844 	if (err) {
845 		PMD_DRV_LOG(ERR, "Mailbox parameters check failed: %d", err);
846 		return err;
847 	}
848 
849 	if (!HINIC_IS_VF(hwdev)) {
850 		PMD_DRV_LOG(ERR, "Input function type error, func_type: %d",
851 				hinic_func_type(hwdev));
852 		return -EINVAL;
853 	}
854 
855 	return hinic_mbox_to_func(func_to_func, mod, cmd,
856 				   hinic_pf_id_of_vf(hwdev), buf_in, in_size,
857 				   buf_out, out_size, timeout);
858 }
859 
860 /**
861  * hinic_mbox_to_pf_no_ack - Send mbox info to pf and do not need pf to response
862  *
863  * @param hwdev
864  *   Pointer to hardware nic device.
865  * @param mod
866  *   Mode type of hardware.
867  * @param cmd
868  *   The command sent to pf.
869  * @param buf_in
870  *   Input parameter.
871  * @param in_size
872  *   Input parameter size.
873  *
874  * @return
875  *   0 on success, negative error value otherwise.
876  */
877 int hinic_mbox_to_pf_no_ack(struct hinic_hwdev *hwdev, enum hinic_mod_type mod,
878 			u8 cmd, void *buf_in, u16 in_size)
879 {
880 	int err;
881 	struct mbox_msg_info msg_info = {0};
882 
883 	err = hinic_mutex_lock(&hwdev->func_to_func->mbox_send_mutex);
884 	if (err)
885 		return err;
886 
887 	err = send_mbox_to_func(hwdev->func_to_func, mod, cmd, buf_in, in_size,
888 			hinic_pf_id_of_vf(hwdev), HINIC_HWIF_DIRECT_SEND,
889 			MBOX_NO_ACK, &msg_info);
890 	if (err)
891 		PMD_DRV_LOG(ERR, "Send mailbox no ack failed, err: %d", err);
892 
893 	(void)hinic_mutex_unlock(&hwdev->func_to_func->mbox_send_mutex);
894 
895 	return err;
896 }
897 
898 static int hinic_func_to_func_init(struct hinic_hwdev *hwdev)
899 {
900 	struct hinic_mbox_func_to_func *func_to_func;
901 	int err;
902 
903 	func_to_func = kzalloc(sizeof(*func_to_func), GFP_KERNEL);
904 	if (!func_to_func) {
905 		PMD_DRV_LOG(ERR, "Allocating memory for func_to_func object failed");
906 		return -ENOMEM;
907 	}
908 	hwdev->func_to_func = func_to_func;
909 	func_to_func->hwdev = hwdev;
910 	(void)hinic_mutex_init(&func_to_func->mbox_send_mutex, NULL);
911 	(void)hinic_mutex_init(&func_to_func->msg_send_mutex, NULL);
912 
913 	err = alloc_mbox_info(func_to_func->mbox_send);
914 	if (err) {
915 		PMD_DRV_LOG(ERR, "Allocating memory for mailbox sending failed");
916 		goto alloc_mbox_for_send_err;
917 	}
918 
919 	err = alloc_mbox_info(func_to_func->mbox_resp);
920 	if (err) {
921 		PMD_DRV_LOG(ERR, "Allocating memory for mailbox responding failed");
922 		goto alloc_mbox_for_resp_err;
923 	}
924 
925 	err = alloc_mbox_wb_status(func_to_func);
926 	if (err)
927 		goto alloc_wb_status_err;
928 
929 	prepare_send_mbox(func_to_func);
930 
931 	return 0;
932 
933 alloc_wb_status_err:
934 	free_mbox_info(func_to_func->mbox_resp);
935 
936 alloc_mbox_for_resp_err:
937 	free_mbox_info(func_to_func->mbox_send);
938 
939 alloc_mbox_for_send_err:
940 	kfree(func_to_func);
941 
942 	return err;
943 }
944 
945 /**
946  * hinic_comm_func_to_func_free - Uninitialize func to func resource.
947  *
948  * @param hwdev
949  *   Pointer to hardware nic device.
950  */
951 void hinic_comm_func_to_func_free(struct hinic_hwdev *hwdev)
952 {
953 	struct hinic_mbox_func_to_func *func_to_func = hwdev->func_to_func;
954 
955 	free_mbox_wb_status(func_to_func);
956 	free_mbox_info(func_to_func->mbox_resp);
957 	free_mbox_info(func_to_func->mbox_send);
958 	(void)hinic_mutex_destroy(&func_to_func->mbox_send_mutex);
959 	(void)hinic_mutex_destroy(&func_to_func->msg_send_mutex);
960 	kfree(func_to_func);
961 }
962 
963 /**
964  * hinic_comm_func_to_func_init - Initialize func to func resource.
965  *
966  * @param hwdev
967  *   Pointer to hardware nic device.
968  */
969 int hinic_comm_func_to_func_init(struct hinic_hwdev *hwdev)
970 {
971 	int rc;
972 	u16 msg_ack_aeqn;
973 
974 	rc = hinic_func_to_func_init(hwdev);
975 	if (rc)
976 		return rc;
977 
978 	msg_ack_aeqn = mbox_msg_ack_aeqn(hwdev);
979 
980 	hwdev->func_to_func->ack_aeq = &hwdev->aeqs->aeq[msg_ack_aeqn];
981 	hwdev->func_to_func->recv_aeq = &hwdev->aeqs->aeq[HINIC_AEQN_0];
982 
983 	return 0;
984 }
985 
986