xref: /linux/drivers/net/ethernet/huawei/hinic/hinic_hw_mbox.c (revision 4f2c0a4acffbec01079c28f839422e64ddeff004)
1a425b6e1SLuo bin // SPDX-License-Identifier: GPL-2.0-only
2a425b6e1SLuo bin /* Huawei HiNIC PCI Express Linux driver
3a425b6e1SLuo bin  * Copyright(c) 2017 Huawei Technologies Co., Ltd
4a425b6e1SLuo bin  */
5a425b6e1SLuo bin #include <linux/pci.h>
6a425b6e1SLuo bin #include <linux/delay.h>
7a425b6e1SLuo bin #include <linux/types.h>
8a425b6e1SLuo bin #include <linux/completion.h>
9a425b6e1SLuo bin #include <linux/semaphore.h>
10a425b6e1SLuo bin #include <linux/spinlock.h>
11a425b6e1SLuo bin #include <linux/workqueue.h>
12a425b6e1SLuo bin 
13a425b6e1SLuo bin #include "hinic_hw_if.h"
14a425b6e1SLuo bin #include "hinic_hw_mgmt.h"
15a425b6e1SLuo bin #include "hinic_hw_csr.h"
16a425b6e1SLuo bin #include "hinic_hw_dev.h"
17a425b6e1SLuo bin #include "hinic_hw_mbox.h"
18a425b6e1SLuo bin 
19a425b6e1SLuo bin #define HINIC_MBOX_INT_DST_FUNC_SHIFT				0
20a425b6e1SLuo bin #define HINIC_MBOX_INT_DST_AEQN_SHIFT				10
21a425b6e1SLuo bin #define HINIC_MBOX_INT_SRC_RESP_AEQN_SHIFT			12
22a425b6e1SLuo bin #define HINIC_MBOX_INT_STAT_DMA_SHIFT				14
23a425b6e1SLuo bin /* The size of data to be sended (unit of 4 bytes) */
24a425b6e1SLuo bin #define HINIC_MBOX_INT_TX_SIZE_SHIFT				20
25a425b6e1SLuo bin /* SO_RO(strong order, relax order) */
26a425b6e1SLuo bin #define HINIC_MBOX_INT_STAT_DMA_SO_RO_SHIFT			25
27a425b6e1SLuo bin #define HINIC_MBOX_INT_WB_EN_SHIFT				28
28a425b6e1SLuo bin 
29a425b6e1SLuo bin #define HINIC_MBOX_INT_DST_FUNC_MASK				0x3FF
30a425b6e1SLuo bin #define HINIC_MBOX_INT_DST_AEQN_MASK				0x3
31a425b6e1SLuo bin #define HINIC_MBOX_INT_SRC_RESP_AEQN_MASK			0x3
32a425b6e1SLuo bin #define HINIC_MBOX_INT_STAT_DMA_MASK				0x3F
33a425b6e1SLuo bin #define HINIC_MBOX_INT_TX_SIZE_MASK				0x1F
34a425b6e1SLuo bin #define HINIC_MBOX_INT_STAT_DMA_SO_RO_MASK			0x3
35a425b6e1SLuo bin #define HINIC_MBOX_INT_WB_EN_MASK				0x1
36a425b6e1SLuo bin 
37a425b6e1SLuo bin #define HINIC_MBOX_INT_SET(val, field)	\
38a425b6e1SLuo bin 			(((val) & HINIC_MBOX_INT_##field##_MASK) << \
39a425b6e1SLuo bin 			HINIC_MBOX_INT_##field##_SHIFT)
40a425b6e1SLuo bin 
41a425b6e1SLuo bin enum hinic_mbox_tx_status {
42a425b6e1SLuo bin 	TX_NOT_DONE = 1,
43a425b6e1SLuo bin };
44a425b6e1SLuo bin 
45a425b6e1SLuo bin #define HINIC_MBOX_CTRL_TRIGGER_AEQE_SHIFT			0
46a425b6e1SLuo bin 
47a425b6e1SLuo bin /* specifies the issue request for the message data.
48a425b6e1SLuo bin  * 0 - Tx request is done;
49a425b6e1SLuo bin  * 1 - Tx request is in process.
50a425b6e1SLuo bin  */
51a425b6e1SLuo bin #define HINIC_MBOX_CTRL_TX_STATUS_SHIFT				1
52a425b6e1SLuo bin 
53a425b6e1SLuo bin #define HINIC_MBOX_CTRL_TRIGGER_AEQE_MASK			0x1
54a425b6e1SLuo bin #define HINIC_MBOX_CTRL_TX_STATUS_MASK				0x1
55a425b6e1SLuo bin 
56a425b6e1SLuo bin #define HINIC_MBOX_CTRL_SET(val, field)	\
57a425b6e1SLuo bin 			(((val) & HINIC_MBOX_CTRL_##field##_MASK) << \
58a425b6e1SLuo bin 			HINIC_MBOX_CTRL_##field##_SHIFT)
59a425b6e1SLuo bin 
60a425b6e1SLuo bin #define HINIC_MBOX_HEADER_MSG_LEN_SHIFT				0
61a425b6e1SLuo bin #define HINIC_MBOX_HEADER_MODULE_SHIFT				11
62a425b6e1SLuo bin #define HINIC_MBOX_HEADER_SEG_LEN_SHIFT				16
63a425b6e1SLuo bin #define HINIC_MBOX_HEADER_NO_ACK_SHIFT				22
64a425b6e1SLuo bin #define HINIC_MBOX_HEADER_SEQID_SHIFT				24
65a425b6e1SLuo bin #define HINIC_MBOX_HEADER_LAST_SHIFT				30
66a425b6e1SLuo bin 
67a425b6e1SLuo bin /* specifies the mailbox message direction
68a425b6e1SLuo bin  * 0 - send
69a425b6e1SLuo bin  * 1 - receive
70a425b6e1SLuo bin  */
71a425b6e1SLuo bin #define HINIC_MBOX_HEADER_DIRECTION_SHIFT			31
72a425b6e1SLuo bin #define HINIC_MBOX_HEADER_CMD_SHIFT				32
73a425b6e1SLuo bin #define HINIC_MBOX_HEADER_MSG_ID_SHIFT				40
74a425b6e1SLuo bin #define HINIC_MBOX_HEADER_STATUS_SHIFT				48
75a425b6e1SLuo bin #define HINIC_MBOX_HEADER_SRC_GLB_FUNC_IDX_SHIFT		54
76a425b6e1SLuo bin 
77a425b6e1SLuo bin #define HINIC_MBOX_HEADER_MSG_LEN_MASK				0x7FF
78a425b6e1SLuo bin #define HINIC_MBOX_HEADER_MODULE_MASK				0x1F
79a425b6e1SLuo bin #define HINIC_MBOX_HEADER_SEG_LEN_MASK				0x3F
80a425b6e1SLuo bin #define HINIC_MBOX_HEADER_NO_ACK_MASK				0x1
81a425b6e1SLuo bin #define HINIC_MBOX_HEADER_SEQID_MASK				0x3F
82a425b6e1SLuo bin #define HINIC_MBOX_HEADER_LAST_MASK				0x1
83a425b6e1SLuo bin #define HINIC_MBOX_HEADER_DIRECTION_MASK			0x1
84a425b6e1SLuo bin #define HINIC_MBOX_HEADER_CMD_MASK				0xFF
85a425b6e1SLuo bin #define HINIC_MBOX_HEADER_MSG_ID_MASK				0xFF
86a425b6e1SLuo bin #define HINIC_MBOX_HEADER_STATUS_MASK				0x3F
87a425b6e1SLuo bin #define HINIC_MBOX_HEADER_SRC_GLB_FUNC_IDX_MASK			0x3FF
88a425b6e1SLuo bin 
89a425b6e1SLuo bin #define HINIC_MBOX_HEADER_GET(val, field)	\
90a425b6e1SLuo bin 			(((val) >> HINIC_MBOX_HEADER_##field##_SHIFT) & \
91a425b6e1SLuo bin 			HINIC_MBOX_HEADER_##field##_MASK)
92a425b6e1SLuo bin #define HINIC_MBOX_HEADER_SET(val, field)	\
93a425b6e1SLuo bin 			((u64)((val) & HINIC_MBOX_HEADER_##field##_MASK) << \
94a425b6e1SLuo bin 			HINIC_MBOX_HEADER_##field##_SHIFT)
95a425b6e1SLuo bin 
96a425b6e1SLuo bin #define MBOX_SEGLEN_MASK			\
97a425b6e1SLuo bin 		HINIC_MBOX_HEADER_SET(HINIC_MBOX_HEADER_SEG_LEN_MASK, SEG_LEN)
98a425b6e1SLuo bin 
99a425b6e1SLuo bin #define HINIC_MBOX_SEG_LEN			48
100a425b6e1SLuo bin #define HINIC_MBOX_COMP_TIME			8000U
101a425b6e1SLuo bin #define MBOX_MSG_POLLING_TIMEOUT		8000
102a425b6e1SLuo bin 
103a425b6e1SLuo bin #define HINIC_MBOX_DATA_SIZE			2040
104a425b6e1SLuo bin 
105a425b6e1SLuo bin #define MBOX_MAX_BUF_SZ				2048UL
106a425b6e1SLuo bin #define MBOX_HEADER_SZ				8
107a425b6e1SLuo bin 
108a425b6e1SLuo bin #define MBOX_INFO_SZ				4
109a425b6e1SLuo bin 
110a425b6e1SLuo bin /* MBOX size is 64B, 8B for mbox_header, 4B reserved */
111a425b6e1SLuo bin #define MBOX_SEG_LEN				48
112a425b6e1SLuo bin #define MBOX_SEG_LEN_ALIGN			4
113a425b6e1SLuo bin #define MBOX_WB_STATUS_LEN			16UL
114a425b6e1SLuo bin 
115a425b6e1SLuo bin /* mbox write back status is 16B, only first 4B is used */
116a425b6e1SLuo bin #define MBOX_WB_STATUS_ERRCODE_MASK		0xFFFF
117a425b6e1SLuo bin #define MBOX_WB_STATUS_MASK			0xFF
118a425b6e1SLuo bin #define MBOX_WB_ERROR_CODE_MASK			0xFF00
119a425b6e1SLuo bin #define MBOX_WB_STATUS_FINISHED_SUCCESS		0xFF
120a425b6e1SLuo bin #define MBOX_WB_STATUS_NOT_FINISHED		0x00
121a425b6e1SLuo bin 
122a425b6e1SLuo bin #define MBOX_STATUS_FINISHED(wb)	\
123a425b6e1SLuo bin 	(((wb) & MBOX_WB_STATUS_MASK) != MBOX_WB_STATUS_NOT_FINISHED)
124a425b6e1SLuo bin #define MBOX_STATUS_SUCCESS(wb)		\
125a425b6e1SLuo bin 	(((wb) & MBOX_WB_STATUS_MASK) == MBOX_WB_STATUS_FINISHED_SUCCESS)
126a425b6e1SLuo bin #define MBOX_STATUS_ERRCODE(wb)		\
127a425b6e1SLuo bin 	((wb) & MBOX_WB_ERROR_CODE_MASK)
128a425b6e1SLuo bin 
129a425b6e1SLuo bin #define SEQ_ID_START_VAL			0
130a425b6e1SLuo bin #define SEQ_ID_MAX_VAL				42
131a425b6e1SLuo bin 
132a425b6e1SLuo bin #define NO_DMA_ATTRIBUTE_VAL			0
133a425b6e1SLuo bin 
134a425b6e1SLuo bin #define HINIC_MBOX_RSP_AEQN			2
135a425b6e1SLuo bin #define HINIC_MBOX_RECV_AEQN			0
136a425b6e1SLuo bin 
137a425b6e1SLuo bin #define MBOX_MSG_NO_DATA_LEN			1
138a425b6e1SLuo bin 
139a425b6e1SLuo bin #define MBOX_BODY_FROM_HDR(header)	((u8 *)(header) + MBOX_HEADER_SZ)
140a425b6e1SLuo bin #define MBOX_AREA(hwif)			\
141a425b6e1SLuo bin 	((hwif)->cfg_regs_bar + HINIC_FUNC_CSR_MAILBOX_DATA_OFF)
142a425b6e1SLuo bin 
143a425b6e1SLuo bin #define IS_PF_OR_PPF_SRC(src_func_idx)	((src_func_idx) < HINIC_MAX_PF_FUNCS)
144a425b6e1SLuo bin 
145a425b6e1SLuo bin #define MBOX_MSG_ID_MASK		0xFF
146a425b6e1SLuo bin #define MBOX_MSG_ID(func_to_func)	((func_to_func)->send_msg_id)
147a425b6e1SLuo bin #define MBOX_MSG_ID_INC(func_to_func_mbox) (MBOX_MSG_ID(func_to_func_mbox) = \
148a425b6e1SLuo bin 			(MBOX_MSG_ID(func_to_func_mbox) + 1) & MBOX_MSG_ID_MASK)
149a425b6e1SLuo bin 
150a425b6e1SLuo bin #define FUNC_ID_OFF_SET_8B		8
151a425b6e1SLuo bin 
152a425b6e1SLuo bin /* max message counter wait to process for one function */
153a425b6e1SLuo bin #define HINIC_MAX_MSG_CNT_TO_PROCESS	10
154a425b6e1SLuo bin 
155a425b6e1SLuo bin #define HINIC_QUEUE_MIN_DEPTH		6
156a425b6e1SLuo bin #define HINIC_QUEUE_MAX_DEPTH		12
157a425b6e1SLuo bin #define HINIC_MAX_RX_BUFFER_SIZE		15
158a425b6e1SLuo bin 
159a425b6e1SLuo bin enum hinic_hwif_direction_type {
160a425b6e1SLuo bin 	HINIC_HWIF_DIRECT_SEND	= 0,
161a425b6e1SLuo bin 	HINIC_HWIF_RESPONSE	= 1,
162a425b6e1SLuo bin };
163a425b6e1SLuo bin 
164a425b6e1SLuo bin enum mbox_send_mod {
165a425b6e1SLuo bin 	MBOX_SEND_MSG_INT,
166a425b6e1SLuo bin };
167a425b6e1SLuo bin 
168a425b6e1SLuo bin enum mbox_seg_type {
169a425b6e1SLuo bin 	NOT_LAST_SEG,
170a425b6e1SLuo bin 	LAST_SEG,
171a425b6e1SLuo bin };
172a425b6e1SLuo bin 
173a425b6e1SLuo bin enum mbox_ordering_type {
174a425b6e1SLuo bin 	STRONG_ORDER,
175a425b6e1SLuo bin };
176a425b6e1SLuo bin 
177a425b6e1SLuo bin enum mbox_write_back_type {
178a425b6e1SLuo bin 	WRITE_BACK = 1,
179a425b6e1SLuo bin };
180a425b6e1SLuo bin 
181a425b6e1SLuo bin enum mbox_aeq_trig_type {
182a425b6e1SLuo bin 	NOT_TRIGGER,
183a425b6e1SLuo bin 	TRIGGER,
184a425b6e1SLuo bin };
185a425b6e1SLuo bin 
check_func_id(struct hinic_hwdev * hwdev,u16 src_func_idx,const void * buf_in,u16 in_size,u16 offset)186c8c29ec3SLuo bin static bool check_func_id(struct hinic_hwdev *hwdev, u16 src_func_idx,
187c8c29ec3SLuo bin 			  const void *buf_in, u16 in_size, u16 offset)
188c8c29ec3SLuo bin {
189c8c29ec3SLuo bin 	u16 func_idx;
190c8c29ec3SLuo bin 
191c8c29ec3SLuo bin 	if (in_size < offset + sizeof(func_idx)) {
192c8c29ec3SLuo bin 		dev_warn(&hwdev->hwif->pdev->dev,
193c8c29ec3SLuo bin 			 "Receive mailbox msg len: %d less than %d Bytes is invalid\n",
194c8c29ec3SLuo bin 			 in_size, offset);
195c8c29ec3SLuo bin 		return false;
196c8c29ec3SLuo bin 	}
197c8c29ec3SLuo bin 
198c8c29ec3SLuo bin 	func_idx = *((u16 *)((u8 *)buf_in + offset));
199c8c29ec3SLuo bin 
200c8c29ec3SLuo bin 	if (src_func_idx != func_idx) {
201c8c29ec3SLuo bin 		dev_warn(&hwdev->hwif->pdev->dev,
202c8c29ec3SLuo bin 			 "Receive mailbox function id: 0x%x not equal to msg function id: 0x%x\n",
203c8c29ec3SLuo bin 			 src_func_idx, func_idx);
204c8c29ec3SLuo bin 		return false;
205c8c29ec3SLuo bin 	}
206c8c29ec3SLuo bin 
207c8c29ec3SLuo bin 	return true;
208c8c29ec3SLuo bin }
209c8c29ec3SLuo bin 
hinic_mbox_check_func_id_8B(struct hinic_hwdev * hwdev,u16 func_idx,void * buf_in,u16 in_size)210c8c29ec3SLuo bin bool hinic_mbox_check_func_id_8B(struct hinic_hwdev *hwdev, u16 func_idx,
211c8c29ec3SLuo bin 				 void *buf_in, u16 in_size)
212c8c29ec3SLuo bin {
213c8c29ec3SLuo bin 	return check_func_id(hwdev, func_idx, buf_in, in_size,
214c8c29ec3SLuo bin 			     FUNC_ID_OFF_SET_8B);
215c8c29ec3SLuo bin }
216c8c29ec3SLuo bin 
217a425b6e1SLuo bin /**
218a425b6e1SLuo bin  * hinic_register_pf_mbox_cb - register mbox callback for pf
219a425b6e1SLuo bin  * @hwdev: the pointer to hw device
220a425b6e1SLuo bin  * @mod:	specific mod that the callback will handle
221a425b6e1SLuo bin  * @callback:	callback function
222a425b6e1SLuo bin  * Return: 0 - success, negative - failure
223a425b6e1SLuo bin  */
hinic_register_pf_mbox_cb(struct hinic_hwdev * hwdev,enum hinic_mod_type mod,hinic_pf_mbox_cb callback)224a425b6e1SLuo bin int hinic_register_pf_mbox_cb(struct hinic_hwdev *hwdev,
225a425b6e1SLuo bin 			      enum hinic_mod_type mod,
226a425b6e1SLuo bin 			      hinic_pf_mbox_cb callback)
227a425b6e1SLuo bin {
228a425b6e1SLuo bin 	struct hinic_mbox_func_to_func *func_to_func = hwdev->func_to_func;
229a425b6e1SLuo bin 
230a425b6e1SLuo bin 	if (mod >= HINIC_MOD_MAX)
231a425b6e1SLuo bin 		return -EFAULT;
232a425b6e1SLuo bin 
233a425b6e1SLuo bin 	func_to_func->pf_mbox_cb[mod] = callback;
234a425b6e1SLuo bin 
235a425b6e1SLuo bin 	set_bit(HINIC_PF_MBOX_CB_REG, &func_to_func->pf_mbox_cb_state[mod]);
236a425b6e1SLuo bin 
237a425b6e1SLuo bin 	return 0;
238a425b6e1SLuo bin }
239a425b6e1SLuo bin 
240a425b6e1SLuo bin /**
241a425b6e1SLuo bin  * hinic_register_vf_mbox_cb - register mbox callback for vf
242a425b6e1SLuo bin  * @hwdev: the pointer to hw device
243a425b6e1SLuo bin  * @mod:	specific mod that the callback will handle
244a425b6e1SLuo bin  * @callback:	callback function
245a425b6e1SLuo bin  * Return: 0 - success, negative - failure
246a425b6e1SLuo bin  */
hinic_register_vf_mbox_cb(struct hinic_hwdev * hwdev,enum hinic_mod_type mod,hinic_vf_mbox_cb callback)247a425b6e1SLuo bin int hinic_register_vf_mbox_cb(struct hinic_hwdev *hwdev,
248a425b6e1SLuo bin 			      enum hinic_mod_type mod,
249a425b6e1SLuo bin 			      hinic_vf_mbox_cb callback)
250a425b6e1SLuo bin {
251a425b6e1SLuo bin 	struct hinic_mbox_func_to_func *func_to_func = hwdev->func_to_func;
252a425b6e1SLuo bin 
253a425b6e1SLuo bin 	if (mod >= HINIC_MOD_MAX)
254a425b6e1SLuo bin 		return -EFAULT;
255a425b6e1SLuo bin 
256a425b6e1SLuo bin 	func_to_func->vf_mbox_cb[mod] = callback;
257a425b6e1SLuo bin 
258a425b6e1SLuo bin 	set_bit(HINIC_VF_MBOX_CB_REG, &func_to_func->vf_mbox_cb_state[mod]);
259a425b6e1SLuo bin 
260a425b6e1SLuo bin 	return 0;
261a425b6e1SLuo bin }
262a425b6e1SLuo bin 
263a425b6e1SLuo bin /**
264a425b6e1SLuo bin  * hinic_unregister_pf_mbox_cb - unregister the mbox callback for pf
265a425b6e1SLuo bin  * @hwdev:	the pointer to hw device
266a425b6e1SLuo bin  * @mod:	specific mod that the callback will handle
267a425b6e1SLuo bin  */
hinic_unregister_pf_mbox_cb(struct hinic_hwdev * hwdev,enum hinic_mod_type mod)268a425b6e1SLuo bin void hinic_unregister_pf_mbox_cb(struct hinic_hwdev *hwdev,
269a425b6e1SLuo bin 				 enum hinic_mod_type mod)
270a425b6e1SLuo bin {
271a425b6e1SLuo bin 	struct hinic_mbox_func_to_func *func_to_func = hwdev->func_to_func;
272a425b6e1SLuo bin 
273a425b6e1SLuo bin 	clear_bit(HINIC_PF_MBOX_CB_REG, &func_to_func->pf_mbox_cb_state[mod]);
274a425b6e1SLuo bin 
275a425b6e1SLuo bin 	while (test_bit(HINIC_PF_MBOX_CB_RUNNING,
276a425b6e1SLuo bin 			&func_to_func->pf_mbox_cb_state[mod]))
277a425b6e1SLuo bin 		usleep_range(900, 1000);
278a425b6e1SLuo bin 
279a425b6e1SLuo bin 	func_to_func->pf_mbox_cb[mod] = NULL;
280a425b6e1SLuo bin }
281a425b6e1SLuo bin 
282a425b6e1SLuo bin /**
283a425b6e1SLuo bin  * hinic_unregister_vf_mbox_cb - unregister the mbox callback for vf
284a425b6e1SLuo bin  * @hwdev:	the pointer to hw device
285a425b6e1SLuo bin  * @mod:	specific mod that the callback will handle
286a425b6e1SLuo bin  */
hinic_unregister_vf_mbox_cb(struct hinic_hwdev * hwdev,enum hinic_mod_type mod)287a425b6e1SLuo bin void hinic_unregister_vf_mbox_cb(struct hinic_hwdev *hwdev,
288a425b6e1SLuo bin 				 enum hinic_mod_type mod)
289a425b6e1SLuo bin {
290a425b6e1SLuo bin 	struct hinic_mbox_func_to_func *func_to_func = hwdev->func_to_func;
291a425b6e1SLuo bin 
292a425b6e1SLuo bin 	clear_bit(HINIC_VF_MBOX_CB_REG, &func_to_func->vf_mbox_cb_state[mod]);
293a425b6e1SLuo bin 
294a425b6e1SLuo bin 	while (test_bit(HINIC_VF_MBOX_CB_RUNNING,
295a425b6e1SLuo bin 			&func_to_func->vf_mbox_cb_state[mod]))
296a425b6e1SLuo bin 		usleep_range(900, 1000);
297a425b6e1SLuo bin 
298a425b6e1SLuo bin 	func_to_func->vf_mbox_cb[mod] = NULL;
299a425b6e1SLuo bin }
300a425b6e1SLuo bin 
recv_vf_mbox_handler(struct hinic_mbox_func_to_func * func_to_func,struct hinic_recv_mbox * recv_mbox,void * buf_out,u16 * out_size)301a425b6e1SLuo bin static int recv_vf_mbox_handler(struct hinic_mbox_func_to_func *func_to_func,
302a425b6e1SLuo bin 				struct hinic_recv_mbox *recv_mbox,
303a425b6e1SLuo bin 				void *buf_out, u16 *out_size)
304a425b6e1SLuo bin {
305a425b6e1SLuo bin 	hinic_vf_mbox_cb cb;
306a425b6e1SLuo bin 	int ret = 0;
307a425b6e1SLuo bin 
308a425b6e1SLuo bin 	if (recv_mbox->mod >= HINIC_MOD_MAX) {
309a425b6e1SLuo bin 		dev_err(&func_to_func->hwif->pdev->dev, "Receive illegal mbox message, mod = %d\n",
310a425b6e1SLuo bin 			recv_mbox->mod);
311a425b6e1SLuo bin 		return -EINVAL;
312a425b6e1SLuo bin 	}
313a425b6e1SLuo bin 
314a425b6e1SLuo bin 	set_bit(HINIC_VF_MBOX_CB_RUNNING,
315a425b6e1SLuo bin 		&func_to_func->vf_mbox_cb_state[recv_mbox->mod]);
316a425b6e1SLuo bin 
317a425b6e1SLuo bin 	cb = func_to_func->vf_mbox_cb[recv_mbox->mod];
318a425b6e1SLuo bin 	if (cb && test_bit(HINIC_VF_MBOX_CB_REG,
319a425b6e1SLuo bin 			   &func_to_func->vf_mbox_cb_state[recv_mbox->mod])) {
320a425b6e1SLuo bin 		cb(func_to_func->hwdev, recv_mbox->cmd, recv_mbox->mbox,
321a425b6e1SLuo bin 		   recv_mbox->mbox_len, buf_out, out_size);
322a425b6e1SLuo bin 	} else {
323a425b6e1SLuo bin 		dev_err(&func_to_func->hwif->pdev->dev, "VF mbox cb is not registered\n");
324a425b6e1SLuo bin 		ret = -EINVAL;
325a425b6e1SLuo bin 	}
326a425b6e1SLuo bin 
327a425b6e1SLuo bin 	clear_bit(HINIC_VF_MBOX_CB_RUNNING,
328a425b6e1SLuo bin 		  &func_to_func->vf_mbox_cb_state[recv_mbox->mod]);
329a425b6e1SLuo bin 
330a425b6e1SLuo bin 	return ret;
331a425b6e1SLuo bin }
332a425b6e1SLuo bin 
333a425b6e1SLuo bin static int
recv_pf_from_vf_mbox_handler(struct hinic_mbox_func_to_func * func_to_func,struct hinic_recv_mbox * recv_mbox,u16 src_func_idx,void * buf_out,u16 * out_size)334a425b6e1SLuo bin recv_pf_from_vf_mbox_handler(struct hinic_mbox_func_to_func *func_to_func,
335a425b6e1SLuo bin 			     struct hinic_recv_mbox *recv_mbox,
336a425b6e1SLuo bin 			     u16 src_func_idx, void *buf_out,
337a425b6e1SLuo bin 			     u16 *out_size)
338a425b6e1SLuo bin {
339a425b6e1SLuo bin 	hinic_pf_mbox_cb cb;
340a425b6e1SLuo bin 	u16 vf_id = 0;
341a425b6e1SLuo bin 	int ret;
342a425b6e1SLuo bin 
343a425b6e1SLuo bin 	if (recv_mbox->mod >= HINIC_MOD_MAX) {
344a425b6e1SLuo bin 		dev_err(&func_to_func->hwif->pdev->dev, "Receive illegal mbox message, mod = %d\n",
345a425b6e1SLuo bin 			recv_mbox->mod);
346a425b6e1SLuo bin 		return -EINVAL;
347a425b6e1SLuo bin 	}
348a425b6e1SLuo bin 
349a425b6e1SLuo bin 	set_bit(HINIC_PF_MBOX_CB_RUNNING,
350a425b6e1SLuo bin 		&func_to_func->pf_mbox_cb_state[recv_mbox->mod]);
351a425b6e1SLuo bin 
352a425b6e1SLuo bin 	cb = func_to_func->pf_mbox_cb[recv_mbox->mod];
353a425b6e1SLuo bin 	if (cb && test_bit(HINIC_PF_MBOX_CB_REG,
354a425b6e1SLuo bin 			   &func_to_func->pf_mbox_cb_state[recv_mbox->mod])) {
355a425b6e1SLuo bin 		vf_id = src_func_idx -
356a425b6e1SLuo bin 			hinic_glb_pf_vf_offset(func_to_func->hwif);
357a425b6e1SLuo bin 		ret = cb(func_to_func->hwdev, vf_id, recv_mbox->cmd,
358a425b6e1SLuo bin 			 recv_mbox->mbox, recv_mbox->mbox_len,
359a425b6e1SLuo bin 			 buf_out, out_size);
360a425b6e1SLuo bin 	} else {
361a425b6e1SLuo bin 		dev_err(&func_to_func->hwif->pdev->dev, "PF mbox mod(0x%x) cb is not registered\n",
362a425b6e1SLuo bin 			recv_mbox->mod);
363a425b6e1SLuo bin 		ret = -EINVAL;
364a425b6e1SLuo bin 	}
365a425b6e1SLuo bin 
366a425b6e1SLuo bin 	clear_bit(HINIC_PF_MBOX_CB_RUNNING,
367a425b6e1SLuo bin 		  &func_to_func->pf_mbox_cb_state[recv_mbox->mod]);
368a425b6e1SLuo bin 
369a425b6e1SLuo bin 	return ret;
370a425b6e1SLuo bin }
371a425b6e1SLuo bin 
check_mbox_seq_id_and_seg_len(struct hinic_recv_mbox * recv_mbox,u8 seq_id,u8 seg_len)372a425b6e1SLuo bin static bool check_mbox_seq_id_and_seg_len(struct hinic_recv_mbox *recv_mbox,
373a425b6e1SLuo bin 					  u8 seq_id, u8 seg_len)
374a425b6e1SLuo bin {
375a425b6e1SLuo bin 	if (seq_id > SEQ_ID_MAX_VAL || seg_len > MBOX_SEG_LEN)
376a425b6e1SLuo bin 		return false;
377a425b6e1SLuo bin 
378a425b6e1SLuo bin 	if (seq_id == 0) {
379a425b6e1SLuo bin 		recv_mbox->seq_id = seq_id;
380a425b6e1SLuo bin 	} else {
381a425b6e1SLuo bin 		if (seq_id != recv_mbox->seq_id + 1)
382a425b6e1SLuo bin 			return false;
383a425b6e1SLuo bin 
384a425b6e1SLuo bin 		recv_mbox->seq_id = seq_id;
385a425b6e1SLuo bin 	}
386a425b6e1SLuo bin 
387a425b6e1SLuo bin 	return true;
388a425b6e1SLuo bin }
389a425b6e1SLuo bin 
resp_mbox_handler(struct hinic_mbox_func_to_func * func_to_func,struct hinic_recv_mbox * recv_mbox)390a425b6e1SLuo bin static void resp_mbox_handler(struct hinic_mbox_func_to_func *func_to_func,
391a425b6e1SLuo bin 			      struct hinic_recv_mbox *recv_mbox)
392a425b6e1SLuo bin {
393a425b6e1SLuo bin 	spin_lock(&func_to_func->mbox_lock);
394a425b6e1SLuo bin 	if (recv_mbox->msg_info.msg_id == func_to_func->send_msg_id &&
395a425b6e1SLuo bin 	    func_to_func->event_flag == EVENT_START)
396a425b6e1SLuo bin 		complete(&recv_mbox->recv_done);
397a425b6e1SLuo bin 	else
398a425b6e1SLuo bin 		dev_err(&func_to_func->hwif->pdev->dev,
399a425b6e1SLuo bin 			"Mbox response timeout, current send msg id(0x%x), recv msg id(0x%x), status(0x%x)\n",
400a425b6e1SLuo bin 			func_to_func->send_msg_id, recv_mbox->msg_info.msg_id,
401a425b6e1SLuo bin 			recv_mbox->msg_info.status);
402a425b6e1SLuo bin 	spin_unlock(&func_to_func->mbox_lock);
403a425b6e1SLuo bin }
404a425b6e1SLuo bin 
405a425b6e1SLuo bin static void recv_func_mbox_handler(struct hinic_mbox_func_to_func *func_to_func,
406a425b6e1SLuo bin 				   struct hinic_recv_mbox *recv_mbox,
407a425b6e1SLuo bin 				   u16 src_func_idx);
408a425b6e1SLuo bin 
recv_func_mbox_work_handler(struct work_struct * work)409a425b6e1SLuo bin static void recv_func_mbox_work_handler(struct work_struct *work)
410a425b6e1SLuo bin {
411a425b6e1SLuo bin 	struct hinic_mbox_work *mbox_work =
412a425b6e1SLuo bin 			container_of(work, struct hinic_mbox_work, work);
413a425b6e1SLuo bin 	struct hinic_recv_mbox *recv_mbox;
414a425b6e1SLuo bin 
415a425b6e1SLuo bin 	recv_func_mbox_handler(mbox_work->func_to_func, mbox_work->recv_mbox,
416a425b6e1SLuo bin 			       mbox_work->src_func_idx);
417a425b6e1SLuo bin 
418a425b6e1SLuo bin 	recv_mbox =
419a425b6e1SLuo bin 		&mbox_work->func_to_func->mbox_send[mbox_work->src_func_idx];
420a425b6e1SLuo bin 
421a425b6e1SLuo bin 	atomic_dec(&recv_mbox->msg_cnt);
422a425b6e1SLuo bin 
423a425b6e1SLuo bin 	kfree(mbox_work);
424a425b6e1SLuo bin }
425a425b6e1SLuo bin 
recv_mbox_handler(struct hinic_mbox_func_to_func * func_to_func,void * header,struct hinic_recv_mbox * recv_mbox)426a425b6e1SLuo bin static void recv_mbox_handler(struct hinic_mbox_func_to_func *func_to_func,
427a425b6e1SLuo bin 			      void *header, struct hinic_recv_mbox *recv_mbox)
428a425b6e1SLuo bin {
429a425b6e1SLuo bin 	void *mbox_body = MBOX_BODY_FROM_HDR(header);
430a425b6e1SLuo bin 	struct hinic_recv_mbox *rcv_mbox_temp = NULL;
431a425b6e1SLuo bin 	u64 mbox_header = *((u64 *)header);
432a425b6e1SLuo bin 	struct hinic_mbox_work *mbox_work;
433a425b6e1SLuo bin 	u8 seq_id, seg_len;
434a425b6e1SLuo bin 	u16 src_func_idx;
435a425b6e1SLuo bin 	int pos;
436a425b6e1SLuo bin 
437a425b6e1SLuo bin 	seq_id = HINIC_MBOX_HEADER_GET(mbox_header, SEQID);
438a425b6e1SLuo bin 	seg_len = HINIC_MBOX_HEADER_GET(mbox_header, SEG_LEN);
439a425b6e1SLuo bin 	src_func_idx = HINIC_MBOX_HEADER_GET(mbox_header, SRC_GLB_FUNC_IDX);
440a425b6e1SLuo bin 
441a425b6e1SLuo bin 	if (!check_mbox_seq_id_and_seg_len(recv_mbox, seq_id, seg_len)) {
442a425b6e1SLuo bin 		dev_err(&func_to_func->hwif->pdev->dev,
443a425b6e1SLuo bin 			"Mailbox sequence and segment check fail, src func id: 0x%x, front id: 0x%x, current id: 0x%x, seg len: 0x%x\n",
444a425b6e1SLuo bin 			src_func_idx, recv_mbox->seq_id, seq_id, seg_len);
445a425b6e1SLuo bin 		recv_mbox->seq_id = SEQ_ID_MAX_VAL;
446a425b6e1SLuo bin 		return;
447a425b6e1SLuo bin 	}
448a425b6e1SLuo bin 
449a425b6e1SLuo bin 	pos = seq_id * MBOX_SEG_LEN;
450a425b6e1SLuo bin 	memcpy((u8 *)recv_mbox->mbox + pos, mbox_body,
451a425b6e1SLuo bin 	       HINIC_MBOX_HEADER_GET(mbox_header, SEG_LEN));
452a425b6e1SLuo bin 
453a425b6e1SLuo bin 	if (!HINIC_MBOX_HEADER_GET(mbox_header, LAST))
454a425b6e1SLuo bin 		return;
455a425b6e1SLuo bin 
456a425b6e1SLuo bin 	recv_mbox->cmd = HINIC_MBOX_HEADER_GET(mbox_header, CMD);
457a425b6e1SLuo bin 	recv_mbox->mod = HINIC_MBOX_HEADER_GET(mbox_header, MODULE);
458a425b6e1SLuo bin 	recv_mbox->mbox_len = HINIC_MBOX_HEADER_GET(mbox_header, MSG_LEN);
459a425b6e1SLuo bin 	recv_mbox->ack_type = HINIC_MBOX_HEADER_GET(mbox_header, NO_ACK);
460a425b6e1SLuo bin 	recv_mbox->msg_info.msg_id = HINIC_MBOX_HEADER_GET(mbox_header, MSG_ID);
461a425b6e1SLuo bin 	recv_mbox->msg_info.status = HINIC_MBOX_HEADER_GET(mbox_header, STATUS);
462a425b6e1SLuo bin 	recv_mbox->seq_id = SEQ_ID_MAX_VAL;
463a425b6e1SLuo bin 
464a425b6e1SLuo bin 	if (HINIC_MBOX_HEADER_GET(mbox_header, DIRECTION) ==
465a425b6e1SLuo bin 	    HINIC_HWIF_RESPONSE) {
466a425b6e1SLuo bin 		resp_mbox_handler(func_to_func, recv_mbox);
467a425b6e1SLuo bin 		return;
468a425b6e1SLuo bin 	}
469a425b6e1SLuo bin 
470a425b6e1SLuo bin 	if (atomic_read(&recv_mbox->msg_cnt) > HINIC_MAX_MSG_CNT_TO_PROCESS) {
471a425b6e1SLuo bin 		dev_warn(&func_to_func->hwif->pdev->dev,
472a425b6e1SLuo bin 			 "This function(%u) have %d message wait to process,can't add to work queue\n",
473a425b6e1SLuo bin 			 src_func_idx, atomic_read(&recv_mbox->msg_cnt));
474a425b6e1SLuo bin 		return;
475a425b6e1SLuo bin 	}
476a425b6e1SLuo bin 
47737ecb5b8SZou Wei 	rcv_mbox_temp = kmemdup(recv_mbox, sizeof(*rcv_mbox_temp), GFP_KERNEL);
478a425b6e1SLuo bin 	if (!rcv_mbox_temp)
479a425b6e1SLuo bin 		return;
480a425b6e1SLuo bin 
48137ecb5b8SZou Wei 	rcv_mbox_temp->mbox = kmemdup(recv_mbox->mbox, MBOX_MAX_BUF_SZ,
48237ecb5b8SZou Wei 				      GFP_KERNEL);
483a425b6e1SLuo bin 	if (!rcv_mbox_temp->mbox)
484a425b6e1SLuo bin 		goto err_alloc_rcv_mbox_msg;
485a425b6e1SLuo bin 
486a425b6e1SLuo bin 	rcv_mbox_temp->buf_out = kzalloc(MBOX_MAX_BUF_SZ, GFP_KERNEL);
487a425b6e1SLuo bin 	if (!rcv_mbox_temp->buf_out)
488a425b6e1SLuo bin 		goto err_alloc_rcv_mbox_buf;
489a425b6e1SLuo bin 
490a425b6e1SLuo bin 	mbox_work = kzalloc(sizeof(*mbox_work), GFP_KERNEL);
491a425b6e1SLuo bin 	if (!mbox_work)
492a425b6e1SLuo bin 		goto err_alloc_mbox_work;
493a425b6e1SLuo bin 
494a425b6e1SLuo bin 	mbox_work->func_to_func = func_to_func;
495a425b6e1SLuo bin 	mbox_work->recv_mbox = rcv_mbox_temp;
496a425b6e1SLuo bin 	mbox_work->src_func_idx = src_func_idx;
497a425b6e1SLuo bin 
498a425b6e1SLuo bin 	atomic_inc(&recv_mbox->msg_cnt);
499a425b6e1SLuo bin 	INIT_WORK(&mbox_work->work, recv_func_mbox_work_handler);
500a425b6e1SLuo bin 	queue_work(func_to_func->workq, &mbox_work->work);
501a425b6e1SLuo bin 
502a425b6e1SLuo bin 	return;
503a425b6e1SLuo bin 
504a425b6e1SLuo bin err_alloc_mbox_work:
505a425b6e1SLuo bin 	kfree(rcv_mbox_temp->buf_out);
506a425b6e1SLuo bin 
507a425b6e1SLuo bin err_alloc_rcv_mbox_buf:
508a425b6e1SLuo bin 	kfree(rcv_mbox_temp->mbox);
509a425b6e1SLuo bin 
510a425b6e1SLuo bin err_alloc_rcv_mbox_msg:
511a425b6e1SLuo bin 	kfree(rcv_mbox_temp);
512a425b6e1SLuo bin }
513a425b6e1SLuo bin 
set_vf_mbox_random_id(struct hinic_hwdev * hwdev,u16 func_id)514088c5f0dSLuo bin static int set_vf_mbox_random_id(struct hinic_hwdev *hwdev, u16 func_id)
515088c5f0dSLuo bin {
516088c5f0dSLuo bin 	struct hinic_mbox_func_to_func *func_to_func = hwdev->func_to_func;
517088c5f0dSLuo bin 	struct hinic_set_random_id rand_info = {0};
518088c5f0dSLuo bin 	u16 out_size = sizeof(rand_info);
519088c5f0dSLuo bin 	struct hinic_pfhwdev *pfhwdev;
520088c5f0dSLuo bin 	int ret;
521088c5f0dSLuo bin 
522088c5f0dSLuo bin 	pfhwdev = container_of(hwdev, struct hinic_pfhwdev, hwdev);
523088c5f0dSLuo bin 
524088c5f0dSLuo bin 	rand_info.version = HINIC_CMD_VER_FUNC_ID;
525088c5f0dSLuo bin 	rand_info.func_idx = func_id;
526088c5f0dSLuo bin 	rand_info.vf_in_pf = func_id - hinic_glb_pf_vf_offset(hwdev->hwif);
527088c5f0dSLuo bin 	rand_info.random_id = get_random_u32();
528088c5f0dSLuo bin 
529088c5f0dSLuo bin 	func_to_func->vf_mbx_rand_id[func_id] = rand_info.random_id;
530088c5f0dSLuo bin 
531088c5f0dSLuo bin 	ret = hinic_msg_to_mgmt(&pfhwdev->pf_to_mgmt, HINIC_MOD_COMM,
532088c5f0dSLuo bin 				HINIC_MGMT_CMD_SET_VF_RANDOM_ID,
533088c5f0dSLuo bin 				&rand_info, sizeof(rand_info),
534088c5f0dSLuo bin 				&rand_info, &out_size, HINIC_MGMT_MSG_SYNC);
535088c5f0dSLuo bin 	if ((rand_info.status != HINIC_MGMT_CMD_UNSUPPORTED &&
536088c5f0dSLuo bin 	     rand_info.status) || !out_size || ret) {
537088c5f0dSLuo bin 		dev_err(&hwdev->hwif->pdev->dev, "Set VF random id failed, err: %d, status: 0x%x, out size: 0x%x\n",
538088c5f0dSLuo bin 			ret, rand_info.status, out_size);
539088c5f0dSLuo bin 		return -EIO;
540088c5f0dSLuo bin 	}
541088c5f0dSLuo bin 
542088c5f0dSLuo bin 	if (rand_info.status == HINIC_MGMT_CMD_UNSUPPORTED)
543088c5f0dSLuo bin 		return rand_info.status;
544088c5f0dSLuo bin 
545088c5f0dSLuo bin 	func_to_func->vf_mbx_old_rand_id[func_id] =
546088c5f0dSLuo bin 				func_to_func->vf_mbx_rand_id[func_id];
547088c5f0dSLuo bin 
548088c5f0dSLuo bin 	return 0;
549088c5f0dSLuo bin }
550088c5f0dSLuo bin 
update_random_id_work_handler(struct work_struct * work)551088c5f0dSLuo bin static void update_random_id_work_handler(struct work_struct *work)
552088c5f0dSLuo bin {
553088c5f0dSLuo bin 	struct hinic_mbox_work *mbox_work =
554088c5f0dSLuo bin 			container_of(work, struct hinic_mbox_work, work);
555088c5f0dSLuo bin 	struct hinic_mbox_func_to_func *func_to_func;
556088c5f0dSLuo bin 	u16 src = mbox_work->src_func_idx;
557088c5f0dSLuo bin 
558088c5f0dSLuo bin 	func_to_func = mbox_work->func_to_func;
559088c5f0dSLuo bin 
560088c5f0dSLuo bin 	if (set_vf_mbox_random_id(func_to_func->hwdev, src))
561088c5f0dSLuo bin 		dev_warn(&func_to_func->hwdev->hwif->pdev->dev, "Update VF id: 0x%x random id failed\n",
562088c5f0dSLuo bin 			 mbox_work->src_func_idx);
563088c5f0dSLuo bin 
564088c5f0dSLuo bin 	kfree(mbox_work);
565088c5f0dSLuo bin }
566088c5f0dSLuo bin 
check_vf_mbox_random_id(struct hinic_mbox_func_to_func * func_to_func,u8 * header)567088c5f0dSLuo bin static bool check_vf_mbox_random_id(struct hinic_mbox_func_to_func *func_to_func,
568088c5f0dSLuo bin 				    u8 *header)
569088c5f0dSLuo bin {
570088c5f0dSLuo bin 	struct hinic_hwdev *hwdev = func_to_func->hwdev;
571088c5f0dSLuo bin 	struct hinic_mbox_work *mbox_work = NULL;
572088c5f0dSLuo bin 	u64 mbox_header = *((u64 *)header);
573088c5f0dSLuo bin 	u16 offset, src;
574088c5f0dSLuo bin 	u32 random_id;
575088c5f0dSLuo bin 	int vf_in_pf;
576088c5f0dSLuo bin 
577088c5f0dSLuo bin 	src = HINIC_MBOX_HEADER_GET(mbox_header, SRC_GLB_FUNC_IDX);
578088c5f0dSLuo bin 
579088c5f0dSLuo bin 	if (IS_PF_OR_PPF_SRC(src) || !func_to_func->support_vf_random)
580088c5f0dSLuo bin 		return true;
581088c5f0dSLuo bin 
582088c5f0dSLuo bin 	if (!HINIC_IS_PPF(hwdev->hwif)) {
583088c5f0dSLuo bin 		offset = hinic_glb_pf_vf_offset(hwdev->hwif);
584088c5f0dSLuo bin 		vf_in_pf = src - offset;
585088c5f0dSLuo bin 
586088c5f0dSLuo bin 		if (vf_in_pf < 1 || vf_in_pf > hwdev->nic_cap.max_vf) {
587088c5f0dSLuo bin 			dev_warn(&hwdev->hwif->pdev->dev,
588088c5f0dSLuo bin 				 "Receive vf id(0x%x) is invalid, vf id should be from 0x%x to 0x%x\n",
589088c5f0dSLuo bin 				 src, offset + 1,
590088c5f0dSLuo bin 				 hwdev->nic_cap.max_vf + offset);
591088c5f0dSLuo bin 			return false;
592088c5f0dSLuo bin 		}
593088c5f0dSLuo bin 	}
594088c5f0dSLuo bin 
595088c5f0dSLuo bin 	random_id = be32_to_cpu(*(u32 *)(header + MBOX_SEG_LEN +
596088c5f0dSLuo bin 					 MBOX_HEADER_SZ));
597088c5f0dSLuo bin 
598088c5f0dSLuo bin 	if (random_id == func_to_func->vf_mbx_rand_id[src] ||
599088c5f0dSLuo bin 	    random_id == func_to_func->vf_mbx_old_rand_id[src])
600088c5f0dSLuo bin 		return true;
601088c5f0dSLuo bin 
602088c5f0dSLuo bin 	dev_warn(&hwdev->hwif->pdev->dev,
603088c5f0dSLuo bin 		 "The mailbox random id(0x%x) of func_id(0x%x) doesn't match with pf reservation(0x%x)\n",
604088c5f0dSLuo bin 		 random_id, src, func_to_func->vf_mbx_rand_id[src]);
605088c5f0dSLuo bin 
606088c5f0dSLuo bin 	mbox_work = kzalloc(sizeof(*mbox_work), GFP_KERNEL);
607088c5f0dSLuo bin 	if (!mbox_work)
608088c5f0dSLuo bin 		return false;
609088c5f0dSLuo bin 
610088c5f0dSLuo bin 	mbox_work->func_to_func = func_to_func;
611088c5f0dSLuo bin 	mbox_work->src_func_idx = src;
612088c5f0dSLuo bin 
613088c5f0dSLuo bin 	INIT_WORK(&mbox_work->work, update_random_id_work_handler);
614088c5f0dSLuo bin 	queue_work(func_to_func->workq, &mbox_work->work);
615088c5f0dSLuo bin 
616088c5f0dSLuo bin 	return false;
617088c5f0dSLuo bin }
618088c5f0dSLuo bin 
hinic_mbox_func_aeqe_handler(void * handle,void * header,u8 size)619*73f25f16SZhengchao Shao static void hinic_mbox_func_aeqe_handler(void *handle, void *header, u8 size)
620a425b6e1SLuo bin {
621a425b6e1SLuo bin 	struct hinic_mbox_func_to_func *func_to_func;
622a425b6e1SLuo bin 	u64 mbox_header = *((u64 *)header);
623a425b6e1SLuo bin 	struct hinic_recv_mbox *recv_mbox;
624a425b6e1SLuo bin 	u64 src, dir;
625a425b6e1SLuo bin 
626a425b6e1SLuo bin 	func_to_func = ((struct hinic_hwdev *)handle)->func_to_func;
627a425b6e1SLuo bin 
628a425b6e1SLuo bin 	dir = HINIC_MBOX_HEADER_GET(mbox_header, DIRECTION);
629a425b6e1SLuo bin 	src = HINIC_MBOX_HEADER_GET(mbox_header, SRC_GLB_FUNC_IDX);
630a425b6e1SLuo bin 
631a425b6e1SLuo bin 	if (src >= HINIC_MAX_FUNCTIONS) {
632a425b6e1SLuo bin 		dev_err(&func_to_func->hwif->pdev->dev,
633a425b6e1SLuo bin 			"Mailbox source function id:%u is invalid\n", (u32)src);
634a425b6e1SLuo bin 		return;
635a425b6e1SLuo bin 	}
636a425b6e1SLuo bin 
637088c5f0dSLuo bin 	if (!check_vf_mbox_random_id(func_to_func, header))
638088c5f0dSLuo bin 		return;
639088c5f0dSLuo bin 
640a425b6e1SLuo bin 	recv_mbox = (dir == HINIC_HWIF_DIRECT_SEND) ?
641a425b6e1SLuo bin 		    &func_to_func->mbox_send[src] :
642a425b6e1SLuo bin 		    &func_to_func->mbox_resp[src];
643a425b6e1SLuo bin 
644a425b6e1SLuo bin 	recv_mbox_handler(func_to_func, (u64 *)header, recv_mbox);
645a425b6e1SLuo bin }
646a425b6e1SLuo bin 
hinic_mbox_self_aeqe_handler(void * handle,void * header,u8 size)647*73f25f16SZhengchao Shao static void hinic_mbox_self_aeqe_handler(void *handle, void *header, u8 size)
648a425b6e1SLuo bin {
649a425b6e1SLuo bin 	struct hinic_mbox_func_to_func *func_to_func;
650a425b6e1SLuo bin 	struct hinic_send_mbox *send_mbox;
651a425b6e1SLuo bin 
652a425b6e1SLuo bin 	func_to_func = ((struct hinic_hwdev *)handle)->func_to_func;
653a425b6e1SLuo bin 	send_mbox = &func_to_func->send_mbox;
654a425b6e1SLuo bin 
655a425b6e1SLuo bin 	complete(&send_mbox->send_done);
656a425b6e1SLuo bin }
657a425b6e1SLuo bin 
clear_mbox_status(struct hinic_send_mbox * mbox)658a425b6e1SLuo bin static void clear_mbox_status(struct hinic_send_mbox *mbox)
659a425b6e1SLuo bin {
660a425b6e1SLuo bin 	*mbox->wb_status = 0;
661a425b6e1SLuo bin 
662a425b6e1SLuo bin 	/* clear mailbox write back status */
663a425b6e1SLuo bin 	wmb();
664a425b6e1SLuo bin }
665a425b6e1SLuo bin 
mbox_copy_header(struct hinic_hwdev * hwdev,struct hinic_send_mbox * mbox,u64 * header)666a425b6e1SLuo bin static void mbox_copy_header(struct hinic_hwdev *hwdev,
667a425b6e1SLuo bin 			     struct hinic_send_mbox *mbox, u64 *header)
668a425b6e1SLuo bin {
669a425b6e1SLuo bin 	u32 i, idx_max = MBOX_HEADER_SZ / sizeof(u32);
670a425b6e1SLuo bin 	u32 *data = (u32 *)header;
671a425b6e1SLuo bin 
672a425b6e1SLuo bin 	for (i = 0; i < idx_max; i++)
673a425b6e1SLuo bin 		__raw_writel(*(data + i), mbox->data + i * sizeof(u32));
674a425b6e1SLuo bin }
675a425b6e1SLuo bin 
mbox_copy_send_data(struct hinic_hwdev * hwdev,struct hinic_send_mbox * mbox,void * seg,u16 seg_len)676a425b6e1SLuo bin static void mbox_copy_send_data(struct hinic_hwdev *hwdev,
677a425b6e1SLuo bin 				struct hinic_send_mbox *mbox, void *seg,
678a425b6e1SLuo bin 				u16 seg_len)
679a425b6e1SLuo bin {
680a425b6e1SLuo bin 	u8 mbox_max_buf[MBOX_SEG_LEN] = {0};
681a425b6e1SLuo bin 	u32 data_len, chk_sz = sizeof(u32);
682a425b6e1SLuo bin 	u32 *data = seg;
683a425b6e1SLuo bin 	u32 i, idx_max;
684a425b6e1SLuo bin 
685a425b6e1SLuo bin 	/* The mbox message should be aligned in 4 bytes. */
686a425b6e1SLuo bin 	if (seg_len % chk_sz) {
687a425b6e1SLuo bin 		memcpy(mbox_max_buf, seg, seg_len);
688a425b6e1SLuo bin 		data = (u32 *)mbox_max_buf;
689a425b6e1SLuo bin 	}
690a425b6e1SLuo bin 
691a425b6e1SLuo bin 	data_len = seg_len;
692a425b6e1SLuo bin 	idx_max = ALIGN(data_len, chk_sz) / chk_sz;
693a425b6e1SLuo bin 
694a425b6e1SLuo bin 	for (i = 0; i < idx_max; i++)
695a425b6e1SLuo bin 		__raw_writel(*(data + i),
696a425b6e1SLuo bin 			     mbox->data + MBOX_HEADER_SZ + i * sizeof(u32));
697a425b6e1SLuo bin }
698a425b6e1SLuo bin 
write_mbox_msg_attr(struct hinic_mbox_func_to_func * func_to_func,u16 dst_func,u16 dst_aeqn,u16 seg_len,int poll)699a425b6e1SLuo bin static void write_mbox_msg_attr(struct hinic_mbox_func_to_func *func_to_func,
700a425b6e1SLuo bin 				u16 dst_func, u16 dst_aeqn, u16 seg_len,
701a425b6e1SLuo bin 				int poll)
702a425b6e1SLuo bin {
703a425b6e1SLuo bin 	u16 rsp_aeq = (dst_aeqn == 0) ? 0 : HINIC_MBOX_RSP_AEQN;
704a425b6e1SLuo bin 	u32 mbox_int, mbox_ctrl;
705a425b6e1SLuo bin 
706a425b6e1SLuo bin 	mbox_int = HINIC_MBOX_INT_SET(dst_func, DST_FUNC) |
707a425b6e1SLuo bin 		   HINIC_MBOX_INT_SET(dst_aeqn, DST_AEQN) |
708a425b6e1SLuo bin 		   HINIC_MBOX_INT_SET(rsp_aeq, SRC_RESP_AEQN) |
709a425b6e1SLuo bin 		   HINIC_MBOX_INT_SET(NO_DMA_ATTRIBUTE_VAL, STAT_DMA) |
710a425b6e1SLuo bin 		   HINIC_MBOX_INT_SET(ALIGN(MBOX_SEG_LEN + MBOX_HEADER_SZ +
711a425b6e1SLuo bin 				      MBOX_INFO_SZ, MBOX_SEG_LEN_ALIGN) >> 2,
712a425b6e1SLuo bin 				      TX_SIZE) |
713a425b6e1SLuo bin 		   HINIC_MBOX_INT_SET(STRONG_ORDER, STAT_DMA_SO_RO) |
714a425b6e1SLuo bin 		   HINIC_MBOX_INT_SET(WRITE_BACK, WB_EN);
715a425b6e1SLuo bin 
716a425b6e1SLuo bin 	hinic_hwif_write_reg(func_to_func->hwif,
717a425b6e1SLuo bin 			     HINIC_FUNC_CSR_MAILBOX_INT_OFFSET_OFF, mbox_int);
718a425b6e1SLuo bin 
719a425b6e1SLuo bin 	wmb(); /* writing the mbox int attributes */
720a425b6e1SLuo bin 	mbox_ctrl = HINIC_MBOX_CTRL_SET(TX_NOT_DONE, TX_STATUS);
721a425b6e1SLuo bin 
722a425b6e1SLuo bin 	if (poll)
723a425b6e1SLuo bin 		mbox_ctrl |= HINIC_MBOX_CTRL_SET(NOT_TRIGGER, TRIGGER_AEQE);
724a425b6e1SLuo bin 	else
725a425b6e1SLuo bin 		mbox_ctrl |= HINIC_MBOX_CTRL_SET(TRIGGER, TRIGGER_AEQE);
726a425b6e1SLuo bin 
727a425b6e1SLuo bin 	hinic_hwif_write_reg(func_to_func->hwif,
728a425b6e1SLuo bin 			     HINIC_FUNC_CSR_MAILBOX_CONTROL_OFF, mbox_ctrl);
729a425b6e1SLuo bin }
730a425b6e1SLuo bin 
dump_mox_reg(struct hinic_hwdev * hwdev)73125979125SZheng Bin static void dump_mox_reg(struct hinic_hwdev *hwdev)
732a425b6e1SLuo bin {
733a425b6e1SLuo bin 	u32 val;
734a425b6e1SLuo bin 
735a425b6e1SLuo bin 	val = hinic_hwif_read_reg(hwdev->hwif,
736a425b6e1SLuo bin 				  HINIC_FUNC_CSR_MAILBOX_CONTROL_OFF);
737a425b6e1SLuo bin 	dev_err(&hwdev->hwif->pdev->dev, "Mailbox control reg: 0x%x\n", val);
738a425b6e1SLuo bin 
739a425b6e1SLuo bin 	val = hinic_hwif_read_reg(hwdev->hwif,
740a425b6e1SLuo bin 				  HINIC_FUNC_CSR_MAILBOX_INT_OFFSET_OFF);
741a425b6e1SLuo bin 	dev_err(&hwdev->hwif->pdev->dev, "Mailbox interrupt offset: 0x%x\n",
742a425b6e1SLuo bin 		val);
743a425b6e1SLuo bin }
744a425b6e1SLuo bin 
get_mbox_status(struct hinic_send_mbox * mbox)745a425b6e1SLuo bin static u16 get_mbox_status(struct hinic_send_mbox *mbox)
746a425b6e1SLuo bin {
747a425b6e1SLuo bin 	/* write back is 16B, but only use first 4B */
748a425b6e1SLuo bin 	u64 wb_val = be64_to_cpu(*mbox->wb_status);
749a425b6e1SLuo bin 
750a425b6e1SLuo bin 	rmb(); /* verify reading before check */
751a425b6e1SLuo bin 
752a425b6e1SLuo bin 	return (u16)(wb_val & MBOX_WB_STATUS_ERRCODE_MASK);
753a425b6e1SLuo bin }
754a425b6e1SLuo bin 
755a425b6e1SLuo bin static int
wait_for_mbox_seg_completion(struct hinic_mbox_func_to_func * func_to_func,int poll,u16 * wb_status)756a425b6e1SLuo bin wait_for_mbox_seg_completion(struct hinic_mbox_func_to_func *func_to_func,
757a425b6e1SLuo bin 			     int poll, u16 *wb_status)
758a425b6e1SLuo bin {
759a425b6e1SLuo bin 	struct hinic_send_mbox *send_mbox = &func_to_func->send_mbox;
760a425b6e1SLuo bin 	struct hinic_hwdev *hwdev = func_to_func->hwdev;
761a425b6e1SLuo bin 	struct completion *done = &send_mbox->send_done;
762a425b6e1SLuo bin 	u32 cnt = 0;
76372ef908bSLuo bin 	unsigned long jif;
764a425b6e1SLuo bin 
765a425b6e1SLuo bin 	if (poll) {
766a425b6e1SLuo bin 		while (cnt < MBOX_MSG_POLLING_TIMEOUT) {
767a425b6e1SLuo bin 			*wb_status = get_mbox_status(send_mbox);
768a425b6e1SLuo bin 			if (MBOX_STATUS_FINISHED(*wb_status))
769a425b6e1SLuo bin 				break;
770a425b6e1SLuo bin 
771a425b6e1SLuo bin 			usleep_range(900, 1000);
772a425b6e1SLuo bin 			cnt++;
773a425b6e1SLuo bin 		}
774a425b6e1SLuo bin 
775a425b6e1SLuo bin 		if (cnt == MBOX_MSG_POLLING_TIMEOUT) {
776a425b6e1SLuo bin 			dev_err(&hwdev->hwif->pdev->dev, "Send mailbox segment timeout, wb status: 0x%x\n",
777a425b6e1SLuo bin 				*wb_status);
778a425b6e1SLuo bin 			dump_mox_reg(hwdev);
779a425b6e1SLuo bin 			return -ETIMEDOUT;
780a425b6e1SLuo bin 		}
781a425b6e1SLuo bin 	} else {
782a425b6e1SLuo bin 		jif = msecs_to_jiffies(HINIC_MBOX_COMP_TIME);
783a425b6e1SLuo bin 		if (!wait_for_completion_timeout(done, jif)) {
784a425b6e1SLuo bin 			dev_err(&hwdev->hwif->pdev->dev, "Send mailbox segment timeout\n");
785a425b6e1SLuo bin 			dump_mox_reg(hwdev);
78690f86b8aSLuo bin 			hinic_dump_aeq_info(hwdev);
787a425b6e1SLuo bin 			return -ETIMEDOUT;
788a425b6e1SLuo bin 		}
789a425b6e1SLuo bin 
790a425b6e1SLuo bin 		*wb_status = get_mbox_status(send_mbox);
791a425b6e1SLuo bin 	}
792a425b6e1SLuo bin 
793a425b6e1SLuo bin 	return 0;
794a425b6e1SLuo bin }
795a425b6e1SLuo bin 
send_mbox_seg(struct hinic_mbox_func_to_func * func_to_func,u64 header,u16 dst_func,void * seg,u16 seg_len,int poll,void * msg_info)796a425b6e1SLuo bin static int send_mbox_seg(struct hinic_mbox_func_to_func *func_to_func,
797a425b6e1SLuo bin 			 u64 header, u16 dst_func, void *seg, u16 seg_len,
798a425b6e1SLuo bin 			 int poll, void *msg_info)
799a425b6e1SLuo bin {
800a425b6e1SLuo bin 	struct hinic_send_mbox *send_mbox = &func_to_func->send_mbox;
801a425b6e1SLuo bin 	u16 seq_dir = HINIC_MBOX_HEADER_GET(header, DIRECTION);
802a425b6e1SLuo bin 	struct hinic_hwdev *hwdev = func_to_func->hwdev;
803a425b6e1SLuo bin 	struct completion *done = &send_mbox->send_done;
804a425b6e1SLuo bin 	u8 num_aeqs = hwdev->hwif->attr.num_aeqs;
805a425b6e1SLuo bin 	u16 dst_aeqn, wb_status = 0, errcode;
806a425b6e1SLuo bin 
807a425b6e1SLuo bin 	if (num_aeqs >= 4)
808a425b6e1SLuo bin 		dst_aeqn = (seq_dir == HINIC_HWIF_DIRECT_SEND) ?
809a425b6e1SLuo bin 			   HINIC_MBOX_RECV_AEQN : HINIC_MBOX_RSP_AEQN;
810a425b6e1SLuo bin 	else
811a425b6e1SLuo bin 		dst_aeqn = 0;
812a425b6e1SLuo bin 
813a425b6e1SLuo bin 	if (!poll)
814a425b6e1SLuo bin 		init_completion(done);
815a425b6e1SLuo bin 
816a425b6e1SLuo bin 	clear_mbox_status(send_mbox);
817a425b6e1SLuo bin 
818a425b6e1SLuo bin 	mbox_copy_header(hwdev, send_mbox, &header);
819a425b6e1SLuo bin 
820a425b6e1SLuo bin 	mbox_copy_send_data(hwdev, send_mbox, seg, seg_len);
821a425b6e1SLuo bin 
822a425b6e1SLuo bin 	write_mbox_msg_attr(func_to_func, dst_func, dst_aeqn, seg_len, poll);
823a425b6e1SLuo bin 
824a425b6e1SLuo bin 	wmb(); /* writing the mbox msg attributes */
825a425b6e1SLuo bin 
826a425b6e1SLuo bin 	if (wait_for_mbox_seg_completion(func_to_func, poll, &wb_status))
827a425b6e1SLuo bin 		return -ETIMEDOUT;
828a425b6e1SLuo bin 
829a425b6e1SLuo bin 	if (!MBOX_STATUS_SUCCESS(wb_status)) {
830a425b6e1SLuo bin 		dev_err(&hwdev->hwif->pdev->dev, "Send mailbox segment to function %d error, wb status: 0x%x\n",
831a425b6e1SLuo bin 			dst_func, wb_status);
832a425b6e1SLuo bin 		errcode = MBOX_STATUS_ERRCODE(wb_status);
833a425b6e1SLuo bin 		return errcode ? errcode : -EFAULT;
834a425b6e1SLuo bin 	}
835a425b6e1SLuo bin 
836a425b6e1SLuo bin 	return 0;
837a425b6e1SLuo bin }
838a425b6e1SLuo bin 
send_mbox_to_func(struct hinic_mbox_func_to_func * func_to_func,enum hinic_mod_type mod,u16 cmd,void * msg,u16 msg_len,u16 dst_func,enum hinic_hwif_direction_type direction,enum hinic_mbox_ack_type ack_type,struct mbox_msg_info * msg_info)839a425b6e1SLuo bin static int send_mbox_to_func(struct hinic_mbox_func_to_func *func_to_func,
840a425b6e1SLuo bin 			     enum hinic_mod_type mod, u16 cmd, void *msg,
841a425b6e1SLuo bin 			     u16 msg_len, u16 dst_func,
842a425b6e1SLuo bin 			     enum hinic_hwif_direction_type direction,
843a425b6e1SLuo bin 			     enum hinic_mbox_ack_type ack_type,
844a425b6e1SLuo bin 			     struct mbox_msg_info *msg_info)
845a425b6e1SLuo bin {
846a425b6e1SLuo bin 	struct hinic_hwdev *hwdev = func_to_func->hwdev;
847a425b6e1SLuo bin 	u16 seg_len = MBOX_SEG_LEN;
848a425b6e1SLuo bin 	u8 *msg_seg = (u8 *)msg;
849a425b6e1SLuo bin 	u16 left = msg_len;
850a425b6e1SLuo bin 	u32 seq_id = 0;
851a425b6e1SLuo bin 	u64 header = 0;
852a425b6e1SLuo bin 	int err = 0;
853a425b6e1SLuo bin 
854a425b6e1SLuo bin 	down(&func_to_func->msg_send_sem);
855a425b6e1SLuo bin 
856a425b6e1SLuo bin 	header = HINIC_MBOX_HEADER_SET(msg_len, MSG_LEN) |
857a425b6e1SLuo bin 		 HINIC_MBOX_HEADER_SET(mod, MODULE) |
858a425b6e1SLuo bin 		 HINIC_MBOX_HEADER_SET(seg_len, SEG_LEN) |
859a425b6e1SLuo bin 		 HINIC_MBOX_HEADER_SET(ack_type, NO_ACK) |
860a425b6e1SLuo bin 		 HINIC_MBOX_HEADER_SET(SEQ_ID_START_VAL, SEQID) |
861a425b6e1SLuo bin 		 HINIC_MBOX_HEADER_SET(NOT_LAST_SEG, LAST) |
862a425b6e1SLuo bin 		 HINIC_MBOX_HEADER_SET(direction, DIRECTION) |
863a425b6e1SLuo bin 		 HINIC_MBOX_HEADER_SET(cmd, CMD) |
864a425b6e1SLuo bin 		 /* The vf's offset to it's associated pf */
865a425b6e1SLuo bin 		 HINIC_MBOX_HEADER_SET(msg_info->msg_id, MSG_ID) |
866a425b6e1SLuo bin 		 HINIC_MBOX_HEADER_SET(msg_info->status, STATUS) |
867a425b6e1SLuo bin 		 HINIC_MBOX_HEADER_SET(hinic_global_func_id_hw(hwdev->hwif),
868a425b6e1SLuo bin 				       SRC_GLB_FUNC_IDX);
869a425b6e1SLuo bin 
870a425b6e1SLuo bin 	while (!(HINIC_MBOX_HEADER_GET(header, LAST))) {
871a425b6e1SLuo bin 		if (left <= HINIC_MBOX_SEG_LEN) {
872a425b6e1SLuo bin 			header &= ~MBOX_SEGLEN_MASK;
873a425b6e1SLuo bin 			header |= HINIC_MBOX_HEADER_SET(left, SEG_LEN);
874a425b6e1SLuo bin 			header |= HINIC_MBOX_HEADER_SET(LAST_SEG, LAST);
875a425b6e1SLuo bin 
876a425b6e1SLuo bin 			seg_len = left;
877a425b6e1SLuo bin 		}
878a425b6e1SLuo bin 
879a425b6e1SLuo bin 		err = send_mbox_seg(func_to_func, header, dst_func, msg_seg,
880a425b6e1SLuo bin 				    seg_len, MBOX_SEND_MSG_INT, msg_info);
881a425b6e1SLuo bin 		if (err) {
882a425b6e1SLuo bin 			dev_err(&hwdev->hwif->pdev->dev, "Failed to send mbox seg, seq_id=0x%llx\n",
883a425b6e1SLuo bin 				HINIC_MBOX_HEADER_GET(header, SEQID));
884a425b6e1SLuo bin 			goto err_send_mbox_seg;
885a425b6e1SLuo bin 		}
886a425b6e1SLuo bin 
887a425b6e1SLuo bin 		left -= HINIC_MBOX_SEG_LEN;
888a425b6e1SLuo bin 		msg_seg += HINIC_MBOX_SEG_LEN;
889a425b6e1SLuo bin 
890a425b6e1SLuo bin 		seq_id++;
891a425b6e1SLuo bin 		header &= ~(HINIC_MBOX_HEADER_SET(HINIC_MBOX_HEADER_SEQID_MASK,
892a425b6e1SLuo bin 						  SEQID));
893a425b6e1SLuo bin 		header |= HINIC_MBOX_HEADER_SET(seq_id, SEQID);
894a425b6e1SLuo bin 	}
895a425b6e1SLuo bin 
896a425b6e1SLuo bin err_send_mbox_seg:
897a425b6e1SLuo bin 	up(&func_to_func->msg_send_sem);
898a425b6e1SLuo bin 
899a425b6e1SLuo bin 	return err;
900a425b6e1SLuo bin }
901a425b6e1SLuo bin 
902a425b6e1SLuo bin static void
response_for_recv_func_mbox(struct hinic_mbox_func_to_func * func_to_func,struct hinic_recv_mbox * recv_mbox,int err,u16 out_size,u16 src_func_idx)903a425b6e1SLuo bin response_for_recv_func_mbox(struct hinic_mbox_func_to_func *func_to_func,
904a425b6e1SLuo bin 			    struct hinic_recv_mbox *recv_mbox, int err,
905a425b6e1SLuo bin 			    u16 out_size, u16 src_func_idx)
906a425b6e1SLuo bin {
907a425b6e1SLuo bin 	struct mbox_msg_info msg_info = {0};
908a425b6e1SLuo bin 
909a425b6e1SLuo bin 	if (recv_mbox->ack_type == MBOX_ACK) {
910a425b6e1SLuo bin 		msg_info.msg_id = recv_mbox->msg_info.msg_id;
911a425b6e1SLuo bin 		if (err == HINIC_MBOX_PF_BUSY_ACTIVE_FW)
912a425b6e1SLuo bin 			msg_info.status = HINIC_MBOX_PF_BUSY_ACTIVE_FW;
913a425b6e1SLuo bin 		else if (err == HINIC_MBOX_VF_CMD_ERROR)
914a425b6e1SLuo bin 			msg_info.status = HINIC_MBOX_VF_CMD_ERROR;
915a425b6e1SLuo bin 		else if (err)
916a425b6e1SLuo bin 			msg_info.status = HINIC_MBOX_PF_SEND_ERR;
917a425b6e1SLuo bin 
918a425b6e1SLuo bin 		/* if no data needs to response, set out_size to 1 */
919a425b6e1SLuo bin 		if (!out_size || err)
920a425b6e1SLuo bin 			out_size = MBOX_MSG_NO_DATA_LEN;
921a425b6e1SLuo bin 
922a425b6e1SLuo bin 		send_mbox_to_func(func_to_func, recv_mbox->mod, recv_mbox->cmd,
923a425b6e1SLuo bin 				  recv_mbox->buf_out, out_size, src_func_idx,
924a425b6e1SLuo bin 				  HINIC_HWIF_RESPONSE, MBOX_ACK,
925a425b6e1SLuo bin 				  &msg_info);
926a425b6e1SLuo bin 	}
927a425b6e1SLuo bin }
928a425b6e1SLuo bin 
recv_func_mbox_handler(struct hinic_mbox_func_to_func * func_to_func,struct hinic_recv_mbox * recv_mbox,u16 src_func_idx)929a425b6e1SLuo bin static void recv_func_mbox_handler(struct hinic_mbox_func_to_func *func_to_func,
930a425b6e1SLuo bin 				   struct hinic_recv_mbox *recv_mbox,
931a425b6e1SLuo bin 				   u16 src_func_idx)
932a425b6e1SLuo bin {
933a425b6e1SLuo bin 	void *buf_out = recv_mbox->buf_out;
934a425b6e1SLuo bin 	u16 out_size = MBOX_MAX_BUF_SZ;
935a425b6e1SLuo bin 	int err = 0;
936a425b6e1SLuo bin 
937a425b6e1SLuo bin 	if (HINIC_IS_VF(func_to_func->hwif)) {
938a425b6e1SLuo bin 		err = recv_vf_mbox_handler(func_to_func, recv_mbox, buf_out,
939a425b6e1SLuo bin 					   &out_size);
940a425b6e1SLuo bin 	} else {
941a425b6e1SLuo bin 		if (IS_PF_OR_PPF_SRC(src_func_idx))
942a425b6e1SLuo bin 			dev_warn(&func_to_func->hwif->pdev->dev,
943a425b6e1SLuo bin 				 "Unsupported pf2pf mbox msg\n");
944a425b6e1SLuo bin 		else
945a425b6e1SLuo bin 			err = recv_pf_from_vf_mbox_handler(func_to_func,
946a425b6e1SLuo bin 							   recv_mbox,
947a425b6e1SLuo bin 							   src_func_idx,
948a425b6e1SLuo bin 							   buf_out, &out_size);
949a425b6e1SLuo bin 	}
950a425b6e1SLuo bin 
951a425b6e1SLuo bin 	response_for_recv_func_mbox(func_to_func, recv_mbox, err, out_size,
952a425b6e1SLuo bin 				    src_func_idx);
953a425b6e1SLuo bin 	kfree(recv_mbox->buf_out);
954a425b6e1SLuo bin 	kfree(recv_mbox->mbox);
955a425b6e1SLuo bin 	kfree(recv_mbox);
956a425b6e1SLuo bin }
957a425b6e1SLuo bin 
set_mbox_to_func_event(struct hinic_mbox_func_to_func * func_to_func,enum mbox_event_state event_flag)958a425b6e1SLuo bin static void set_mbox_to_func_event(struct hinic_mbox_func_to_func *func_to_func,
959a425b6e1SLuo bin 				   enum mbox_event_state event_flag)
960a425b6e1SLuo bin {
961a425b6e1SLuo bin 	spin_lock(&func_to_func->mbox_lock);
962a425b6e1SLuo bin 	func_to_func->event_flag = event_flag;
963a425b6e1SLuo bin 	spin_unlock(&func_to_func->mbox_lock);
964a425b6e1SLuo bin }
965a425b6e1SLuo bin 
mbox_resp_info_handler(struct hinic_mbox_func_to_func * func_to_func,struct hinic_recv_mbox * mbox_for_resp,enum hinic_mod_type mod,u16 cmd,void * buf_out,u16 * out_size)966a425b6e1SLuo bin static int mbox_resp_info_handler(struct hinic_mbox_func_to_func *func_to_func,
967a425b6e1SLuo bin 				  struct hinic_recv_mbox *mbox_for_resp,
968a425b6e1SLuo bin 				  enum hinic_mod_type mod, u16 cmd,
969a425b6e1SLuo bin 				  void *buf_out, u16 *out_size)
970a425b6e1SLuo bin {
971a425b6e1SLuo bin 	int err;
972a425b6e1SLuo bin 
973a425b6e1SLuo bin 	if (mbox_for_resp->msg_info.status) {
974a425b6e1SLuo bin 		err = mbox_for_resp->msg_info.status;
975a425b6e1SLuo bin 		if (err != HINIC_MBOX_PF_BUSY_ACTIVE_FW)
976a425b6e1SLuo bin 			dev_err(&func_to_func->hwif->pdev->dev, "Mbox response error(0x%x)\n",
977a425b6e1SLuo bin 				mbox_for_resp->msg_info.status);
978a425b6e1SLuo bin 		return err;
979a425b6e1SLuo bin 	}
980a425b6e1SLuo bin 
981a425b6e1SLuo bin 	if (buf_out && out_size) {
982a425b6e1SLuo bin 		if (*out_size < mbox_for_resp->mbox_len) {
983a425b6e1SLuo bin 			dev_err(&func_to_func->hwif->pdev->dev,
984a425b6e1SLuo bin 				"Invalid response mbox message length: %d for mod %d cmd %d, should less than: %d\n",
985a425b6e1SLuo bin 				mbox_for_resp->mbox_len, mod, cmd, *out_size);
986a425b6e1SLuo bin 			return -EFAULT;
987a425b6e1SLuo bin 		}
988a425b6e1SLuo bin 
989a425b6e1SLuo bin 		if (mbox_for_resp->mbox_len)
990a425b6e1SLuo bin 			memcpy(buf_out, mbox_for_resp->mbox,
991a425b6e1SLuo bin 			       mbox_for_resp->mbox_len);
992a425b6e1SLuo bin 
993a425b6e1SLuo bin 		*out_size = mbox_for_resp->mbox_len;
994a425b6e1SLuo bin 	}
995a425b6e1SLuo bin 
996a425b6e1SLuo bin 	return 0;
997a425b6e1SLuo bin }
998a425b6e1SLuo bin 
hinic_mbox_to_func(struct hinic_mbox_func_to_func * func_to_func,enum hinic_mod_type mod,u16 cmd,u16 dst_func,void * buf_in,u16 in_size,void * buf_out,u16 * out_size,u32 timeout)999a425b6e1SLuo bin int hinic_mbox_to_func(struct hinic_mbox_func_to_func *func_to_func,
1000a425b6e1SLuo bin 		       enum hinic_mod_type mod, u16 cmd, u16 dst_func,
1001a425b6e1SLuo bin 		       void *buf_in, u16 in_size, void *buf_out,
1002a425b6e1SLuo bin 		       u16 *out_size, u32 timeout)
1003a425b6e1SLuo bin {
1004a425b6e1SLuo bin 	struct hinic_recv_mbox *mbox_for_resp;
1005a425b6e1SLuo bin 	struct mbox_msg_info msg_info = {0};
100672ef908bSLuo bin 	unsigned long timeo;
1007a425b6e1SLuo bin 	int err;
1008a425b6e1SLuo bin 
1009a425b6e1SLuo bin 	mbox_for_resp = &func_to_func->mbox_resp[dst_func];
1010a425b6e1SLuo bin 
1011a425b6e1SLuo bin 	down(&func_to_func->mbox_send_sem);
1012a425b6e1SLuo bin 
1013a425b6e1SLuo bin 	init_completion(&mbox_for_resp->recv_done);
1014a425b6e1SLuo bin 
1015a425b6e1SLuo bin 	msg_info.msg_id = MBOX_MSG_ID_INC(func_to_func);
1016a425b6e1SLuo bin 
1017a425b6e1SLuo bin 	set_mbox_to_func_event(func_to_func, EVENT_START);
1018a425b6e1SLuo bin 
1019a425b6e1SLuo bin 	err = send_mbox_to_func(func_to_func, mod, cmd, buf_in, in_size,
1020a425b6e1SLuo bin 				dst_func, HINIC_HWIF_DIRECT_SEND, MBOX_ACK,
1021a425b6e1SLuo bin 				&msg_info);
1022a425b6e1SLuo bin 	if (err) {
1023a425b6e1SLuo bin 		dev_err(&func_to_func->hwif->pdev->dev, "Send mailbox failed, msg_id: %d\n",
1024a425b6e1SLuo bin 			msg_info.msg_id);
1025a425b6e1SLuo bin 		set_mbox_to_func_event(func_to_func, EVENT_FAIL);
1026a425b6e1SLuo bin 		goto err_send_mbox;
1027a425b6e1SLuo bin 	}
1028a425b6e1SLuo bin 
1029a425b6e1SLuo bin 	timeo = msecs_to_jiffies(timeout ? timeout : HINIC_MBOX_COMP_TIME);
1030a425b6e1SLuo bin 	if (!wait_for_completion_timeout(&mbox_for_resp->recv_done, timeo)) {
1031a425b6e1SLuo bin 		set_mbox_to_func_event(func_to_func, EVENT_TIMEOUT);
1032a425b6e1SLuo bin 		dev_err(&func_to_func->hwif->pdev->dev,
1033a425b6e1SLuo bin 			"Send mbox msg timeout, msg_id: %d\n", msg_info.msg_id);
103490f86b8aSLuo bin 		hinic_dump_aeq_info(func_to_func->hwdev);
1035a425b6e1SLuo bin 		err = -ETIMEDOUT;
1036a425b6e1SLuo bin 		goto err_send_mbox;
1037a425b6e1SLuo bin 	}
1038a425b6e1SLuo bin 
1039a425b6e1SLuo bin 	set_mbox_to_func_event(func_to_func, EVENT_END);
1040a425b6e1SLuo bin 
1041a425b6e1SLuo bin 	err = mbox_resp_info_handler(func_to_func, mbox_for_resp, mod, cmd,
1042a425b6e1SLuo bin 				     buf_out, out_size);
1043a425b6e1SLuo bin 
1044a425b6e1SLuo bin err_send_mbox:
1045a425b6e1SLuo bin 	up(&func_to_func->mbox_send_sem);
1046a425b6e1SLuo bin 
1047a425b6e1SLuo bin 	return err;
1048a425b6e1SLuo bin }
1049a425b6e1SLuo bin 
mbox_func_params_valid(struct hinic_mbox_func_to_func * func_to_func,void * buf_in,u16 in_size)1050a425b6e1SLuo bin static int mbox_func_params_valid(struct hinic_mbox_func_to_func *func_to_func,
1051a425b6e1SLuo bin 				  void *buf_in, u16 in_size)
1052a425b6e1SLuo bin {
1053a425b6e1SLuo bin 	if (in_size > HINIC_MBOX_DATA_SIZE) {
1054a425b6e1SLuo bin 		dev_err(&func_to_func->hwif->pdev->dev,
1055a425b6e1SLuo bin 			"Mbox msg len(%d) exceed limit(%d)\n",
1056a425b6e1SLuo bin 			in_size, HINIC_MBOX_DATA_SIZE);
1057a425b6e1SLuo bin 		return -EINVAL;
1058a425b6e1SLuo bin 	}
1059a425b6e1SLuo bin 
1060a425b6e1SLuo bin 	return 0;
1061a425b6e1SLuo bin }
1062a425b6e1SLuo bin 
hinic_mbox_to_pf(struct hinic_hwdev * hwdev,enum hinic_mod_type mod,u8 cmd,void * buf_in,u16 in_size,void * buf_out,u16 * out_size,u32 timeout)1063a425b6e1SLuo bin int hinic_mbox_to_pf(struct hinic_hwdev *hwdev,
1064a425b6e1SLuo bin 		     enum hinic_mod_type mod, u8 cmd, void *buf_in,
1065a425b6e1SLuo bin 		     u16 in_size, void *buf_out, u16 *out_size, u32 timeout)
1066a425b6e1SLuo bin {
1067a425b6e1SLuo bin 	struct hinic_mbox_func_to_func *func_to_func = hwdev->func_to_func;
1068a425b6e1SLuo bin 	int err = mbox_func_params_valid(func_to_func, buf_in, in_size);
1069a425b6e1SLuo bin 
1070a425b6e1SLuo bin 	if (err)
1071a425b6e1SLuo bin 		return err;
1072a425b6e1SLuo bin 
1073a425b6e1SLuo bin 	if (!HINIC_IS_VF(hwdev->hwif)) {
1074a425b6e1SLuo bin 		dev_err(&hwdev->hwif->pdev->dev, "Params error, func_type: %d\n",
1075a425b6e1SLuo bin 			HINIC_FUNC_TYPE(hwdev->hwif));
1076a425b6e1SLuo bin 		return -EINVAL;
1077a425b6e1SLuo bin 	}
1078a425b6e1SLuo bin 
1079a425b6e1SLuo bin 	return hinic_mbox_to_func(func_to_func, mod, cmd,
1080a425b6e1SLuo bin 				  hinic_pf_id_of_vf_hw(hwdev->hwif), buf_in,
1081a425b6e1SLuo bin 				  in_size, buf_out, out_size, timeout);
1082a425b6e1SLuo bin }
1083a425b6e1SLuo bin 
hinic_mbox_to_vf(struct hinic_hwdev * hwdev,enum hinic_mod_type mod,u16 vf_id,u8 cmd,void * buf_in,u16 in_size,void * buf_out,u16 * out_size,u32 timeout)1084a425b6e1SLuo bin int hinic_mbox_to_vf(struct hinic_hwdev *hwdev,
1085a425b6e1SLuo bin 		     enum hinic_mod_type mod, u16 vf_id, u8 cmd, void *buf_in,
1086a425b6e1SLuo bin 		     u16 in_size, void *buf_out, u16 *out_size, u32 timeout)
1087a425b6e1SLuo bin {
1088a425b6e1SLuo bin 	struct hinic_mbox_func_to_func *func_to_func;
1089a425b6e1SLuo bin 	u16 dst_func_idx;
1090a425b6e1SLuo bin 	int err;
1091a425b6e1SLuo bin 
1092a425b6e1SLuo bin 	if (!hwdev)
1093a425b6e1SLuo bin 		return -EINVAL;
1094a425b6e1SLuo bin 
1095a425b6e1SLuo bin 	func_to_func = hwdev->func_to_func;
1096a425b6e1SLuo bin 	err = mbox_func_params_valid(func_to_func, buf_in, in_size);
1097a425b6e1SLuo bin 	if (err)
1098a425b6e1SLuo bin 		return err;
1099a425b6e1SLuo bin 
1100a425b6e1SLuo bin 	if (HINIC_IS_VF(hwdev->hwif)) {
1101a425b6e1SLuo bin 		dev_err(&hwdev->hwif->pdev->dev, "Params error, func_type: %d\n",
1102a425b6e1SLuo bin 			HINIC_FUNC_TYPE(hwdev->hwif));
1103a425b6e1SLuo bin 		return -EINVAL;
1104a425b6e1SLuo bin 	}
1105a425b6e1SLuo bin 
1106a425b6e1SLuo bin 	if (!vf_id) {
1107a425b6e1SLuo bin 		dev_err(&hwdev->hwif->pdev->dev,
1108a425b6e1SLuo bin 			"VF id(%d) error!\n", vf_id);
1109a425b6e1SLuo bin 		return -EINVAL;
1110a425b6e1SLuo bin 	}
1111a425b6e1SLuo bin 
1112a425b6e1SLuo bin 	/* vf_offset_to_pf + vf_id is the vf's global function id of vf in
1113a425b6e1SLuo bin 	 * this pf
1114a425b6e1SLuo bin 	 */
1115a425b6e1SLuo bin 	dst_func_idx = hinic_glb_pf_vf_offset(hwdev->hwif) + vf_id;
1116a425b6e1SLuo bin 
1117a425b6e1SLuo bin 	return hinic_mbox_to_func(func_to_func, mod, cmd, dst_func_idx, buf_in,
1118a425b6e1SLuo bin 				  in_size, buf_out, out_size, timeout);
1119a425b6e1SLuo bin }
1120a425b6e1SLuo bin 
init_mbox_info(struct hinic_recv_mbox * mbox_info)1121a425b6e1SLuo bin static int init_mbox_info(struct hinic_recv_mbox *mbox_info)
1122a425b6e1SLuo bin {
1123a425b6e1SLuo bin 	int err;
1124a425b6e1SLuo bin 
1125a425b6e1SLuo bin 	mbox_info->seq_id = SEQ_ID_MAX_VAL;
1126a425b6e1SLuo bin 
1127a425b6e1SLuo bin 	mbox_info->mbox = kzalloc(MBOX_MAX_BUF_SZ, GFP_KERNEL);
1128a425b6e1SLuo bin 	if (!mbox_info->mbox)
1129a425b6e1SLuo bin 		return -ENOMEM;
1130a425b6e1SLuo bin 
1131a425b6e1SLuo bin 	mbox_info->buf_out = kzalloc(MBOX_MAX_BUF_SZ, GFP_KERNEL);
1132a425b6e1SLuo bin 	if (!mbox_info->buf_out) {
1133a425b6e1SLuo bin 		err = -ENOMEM;
1134a425b6e1SLuo bin 		goto err_alloc_buf_out;
1135a425b6e1SLuo bin 	}
1136a425b6e1SLuo bin 
1137a425b6e1SLuo bin 	atomic_set(&mbox_info->msg_cnt, 0);
1138a425b6e1SLuo bin 
1139a425b6e1SLuo bin 	return 0;
1140a425b6e1SLuo bin 
1141a425b6e1SLuo bin err_alloc_buf_out:
1142a425b6e1SLuo bin 	kfree(mbox_info->mbox);
1143a425b6e1SLuo bin 
1144a425b6e1SLuo bin 	return err;
1145a425b6e1SLuo bin }
1146a425b6e1SLuo bin 
clean_mbox_info(struct hinic_recv_mbox * mbox_info)1147a425b6e1SLuo bin static void clean_mbox_info(struct hinic_recv_mbox *mbox_info)
1148a425b6e1SLuo bin {
1149a425b6e1SLuo bin 	kfree(mbox_info->buf_out);
1150a425b6e1SLuo bin 	kfree(mbox_info->mbox);
1151a425b6e1SLuo bin }
1152a425b6e1SLuo bin 
alloc_mbox_info(struct hinic_hwdev * hwdev,struct hinic_recv_mbox * mbox_info)1153a425b6e1SLuo bin static int alloc_mbox_info(struct hinic_hwdev *hwdev,
1154a425b6e1SLuo bin 			   struct hinic_recv_mbox *mbox_info)
1155a425b6e1SLuo bin {
1156a425b6e1SLuo bin 	u16 func_idx, i;
1157a425b6e1SLuo bin 	int err;
1158a425b6e1SLuo bin 
1159a425b6e1SLuo bin 	for (func_idx = 0; func_idx < HINIC_MAX_FUNCTIONS; func_idx++) {
1160a425b6e1SLuo bin 		err = init_mbox_info(&mbox_info[func_idx]);
1161a425b6e1SLuo bin 		if (err) {
1162a425b6e1SLuo bin 			dev_err(&hwdev->hwif->pdev->dev, "Failed to init function %d mbox info\n",
1163a425b6e1SLuo bin 				func_idx);
1164a425b6e1SLuo bin 			goto err_init_mbox_info;
1165a425b6e1SLuo bin 		}
1166a425b6e1SLuo bin 	}
1167a425b6e1SLuo bin 
1168a425b6e1SLuo bin 	return 0;
1169a425b6e1SLuo bin 
1170a425b6e1SLuo bin err_init_mbox_info:
1171a425b6e1SLuo bin 	for (i = 0; i < func_idx; i++)
1172a425b6e1SLuo bin 		clean_mbox_info(&mbox_info[i]);
1173a425b6e1SLuo bin 
1174a425b6e1SLuo bin 	return err;
1175a425b6e1SLuo bin }
1176a425b6e1SLuo bin 
free_mbox_info(struct hinic_recv_mbox * mbox_info)1177a425b6e1SLuo bin static void free_mbox_info(struct hinic_recv_mbox *mbox_info)
1178a425b6e1SLuo bin {
1179a425b6e1SLuo bin 	u16 func_idx;
1180a425b6e1SLuo bin 
1181a425b6e1SLuo bin 	for (func_idx = 0; func_idx < HINIC_MAX_FUNCTIONS; func_idx++)
1182a425b6e1SLuo bin 		clean_mbox_info(&mbox_info[func_idx]);
1183a425b6e1SLuo bin }
1184a425b6e1SLuo bin 
prepare_send_mbox(struct hinic_mbox_func_to_func * func_to_func)1185a425b6e1SLuo bin static void prepare_send_mbox(struct hinic_mbox_func_to_func *func_to_func)
1186a425b6e1SLuo bin {
1187a425b6e1SLuo bin 	struct hinic_send_mbox *send_mbox = &func_to_func->send_mbox;
1188a425b6e1SLuo bin 
1189a425b6e1SLuo bin 	send_mbox->data = MBOX_AREA(func_to_func->hwif);
1190a425b6e1SLuo bin }
1191a425b6e1SLuo bin 
alloc_mbox_wb_status(struct hinic_mbox_func_to_func * func_to_func)1192a425b6e1SLuo bin static int alloc_mbox_wb_status(struct hinic_mbox_func_to_func *func_to_func)
1193a425b6e1SLuo bin {
1194a425b6e1SLuo bin 	struct hinic_send_mbox *send_mbox = &func_to_func->send_mbox;
1195a425b6e1SLuo bin 	struct hinic_hwdev *hwdev = func_to_func->hwdev;
1196a425b6e1SLuo bin 	u32 addr_h, addr_l;
1197a425b6e1SLuo bin 
1198a425b6e1SLuo bin 	send_mbox->wb_vaddr = dma_alloc_coherent(&hwdev->hwif->pdev->dev,
1199a425b6e1SLuo bin 						 MBOX_WB_STATUS_LEN,
1200a425b6e1SLuo bin 						 &send_mbox->wb_paddr,
1201a425b6e1SLuo bin 						 GFP_KERNEL);
1202a425b6e1SLuo bin 	if (!send_mbox->wb_vaddr)
1203a425b6e1SLuo bin 		return -ENOMEM;
1204a425b6e1SLuo bin 
1205a425b6e1SLuo bin 	send_mbox->wb_status = send_mbox->wb_vaddr;
1206a425b6e1SLuo bin 
1207a425b6e1SLuo bin 	addr_h = upper_32_bits(send_mbox->wb_paddr);
1208a425b6e1SLuo bin 	addr_l = lower_32_bits(send_mbox->wb_paddr);
1209a425b6e1SLuo bin 
1210a425b6e1SLuo bin 	hinic_hwif_write_reg(hwdev->hwif, HINIC_FUNC_CSR_MAILBOX_RESULT_H_OFF,
1211a425b6e1SLuo bin 			     addr_h);
1212a425b6e1SLuo bin 	hinic_hwif_write_reg(hwdev->hwif, HINIC_FUNC_CSR_MAILBOX_RESULT_L_OFF,
1213a425b6e1SLuo bin 			     addr_l);
1214a425b6e1SLuo bin 
1215a425b6e1SLuo bin 	return 0;
1216a425b6e1SLuo bin }
1217a425b6e1SLuo bin 
free_mbox_wb_status(struct hinic_mbox_func_to_func * func_to_func)1218a425b6e1SLuo bin static void free_mbox_wb_status(struct hinic_mbox_func_to_func *func_to_func)
1219a425b6e1SLuo bin {
1220a425b6e1SLuo bin 	struct hinic_send_mbox *send_mbox = &func_to_func->send_mbox;
1221a425b6e1SLuo bin 	struct hinic_hwdev *hwdev = func_to_func->hwdev;
1222a425b6e1SLuo bin 
1223a425b6e1SLuo bin 	hinic_hwif_write_reg(hwdev->hwif, HINIC_FUNC_CSR_MAILBOX_RESULT_H_OFF,
1224a425b6e1SLuo bin 			     0);
1225a425b6e1SLuo bin 	hinic_hwif_write_reg(hwdev->hwif, HINIC_FUNC_CSR_MAILBOX_RESULT_L_OFF,
1226a425b6e1SLuo bin 			     0);
1227a425b6e1SLuo bin 
1228a425b6e1SLuo bin 	dma_free_coherent(&hwdev->hwif->pdev->dev, MBOX_WB_STATUS_LEN,
1229a425b6e1SLuo bin 			  send_mbox->wb_vaddr,
1230a425b6e1SLuo bin 			  send_mbox->wb_paddr);
1231a425b6e1SLuo bin }
1232a425b6e1SLuo bin 
hinic_mbox_check_cmd_valid(struct hinic_hwdev * hwdev,struct vf_cmd_check_handle * cmd_handle,u16 vf_id,u8 cmd,void * buf_in,u16 in_size,u8 size)1233c8c29ec3SLuo bin bool hinic_mbox_check_cmd_valid(struct hinic_hwdev *hwdev,
1234c8c29ec3SLuo bin 				struct vf_cmd_check_handle *cmd_handle,
1235c8c29ec3SLuo bin 				u16 vf_id, u8 cmd, void *buf_in,
1236c8c29ec3SLuo bin 				u16 in_size, u8 size)
1237c8c29ec3SLuo bin {
1238c8c29ec3SLuo bin 	u16 src_idx = vf_id + hinic_glb_pf_vf_offset(hwdev->hwif);
1239c8c29ec3SLuo bin 	int i;
1240c8c29ec3SLuo bin 
1241c8c29ec3SLuo bin 	for (i = 0; i < size; i++) {
1242c8c29ec3SLuo bin 		if (cmd == cmd_handle[i].cmd) {
1243c8c29ec3SLuo bin 			if (cmd_handle[i].check_cmd)
1244c8c29ec3SLuo bin 				return cmd_handle[i].check_cmd(hwdev, src_idx,
1245c8c29ec3SLuo bin 							       buf_in, in_size);
1246c8c29ec3SLuo bin 			else
1247c8c29ec3SLuo bin 				return true;
1248c8c29ec3SLuo bin 		}
1249c8c29ec3SLuo bin 	}
1250c8c29ec3SLuo bin 
1251c8c29ec3SLuo bin 	dev_err(&hwdev->hwif->pdev->dev,
1252c8c29ec3SLuo bin 		"PF Receive VF(%d) unsupported cmd(0x%x)\n",
1253c8c29ec3SLuo bin 		vf_id + hinic_glb_pf_vf_offset(hwdev->hwif), cmd);
1254c8c29ec3SLuo bin 
1255c8c29ec3SLuo bin 	return false;
1256c8c29ec3SLuo bin }
1257c8c29ec3SLuo bin 
hinic_cmdq_check_vf_ctxt(struct hinic_hwdev * hwdev,struct hinic_cmdq_ctxt * cmdq_ctxt)1258c8c29ec3SLuo bin static bool hinic_cmdq_check_vf_ctxt(struct hinic_hwdev *hwdev,
1259c8c29ec3SLuo bin 				     struct hinic_cmdq_ctxt *cmdq_ctxt)
1260c8c29ec3SLuo bin {
1261c8c29ec3SLuo bin 	struct hinic_cmdq_ctxt_info *ctxt_info = &cmdq_ctxt->ctxt_info;
1262c8c29ec3SLuo bin 	u64 curr_pg_pfn, wq_block_pfn;
1263c8c29ec3SLuo bin 
1264c8c29ec3SLuo bin 	if (cmdq_ctxt->ppf_idx != HINIC_HWIF_PPF_IDX(hwdev->hwif) ||
1265c8c29ec3SLuo bin 	    cmdq_ctxt->cmdq_type > HINIC_MAX_CMDQ_TYPES)
1266c8c29ec3SLuo bin 		return false;
1267c8c29ec3SLuo bin 
1268c8c29ec3SLuo bin 	curr_pg_pfn = HINIC_CMDQ_CTXT_PAGE_INFO_GET
1269c8c29ec3SLuo bin 		(ctxt_info->curr_wqe_page_pfn, CURR_WQE_PAGE_PFN);
1270c8c29ec3SLuo bin 	wq_block_pfn = HINIC_CMDQ_CTXT_BLOCK_INFO_GET
1271c8c29ec3SLuo bin 		(ctxt_info->wq_block_pfn, WQ_BLOCK_PFN);
1272c8c29ec3SLuo bin 	/* VF must use 0-level CLA */
1273c8c29ec3SLuo bin 	if (curr_pg_pfn != wq_block_pfn)
1274c8c29ec3SLuo bin 		return false;
1275c8c29ec3SLuo bin 
1276c8c29ec3SLuo bin 	return true;
1277c8c29ec3SLuo bin }
1278c8c29ec3SLuo bin 
check_cmdq_ctxt(struct hinic_hwdev * hwdev,u16 func_idx,void * buf_in,u16 in_size)1279c8c29ec3SLuo bin static bool check_cmdq_ctxt(struct hinic_hwdev *hwdev, u16 func_idx,
1280c8c29ec3SLuo bin 			    void *buf_in, u16 in_size)
1281c8c29ec3SLuo bin {
1282c8c29ec3SLuo bin 	if (!hinic_mbox_check_func_id_8B(hwdev, func_idx, buf_in, in_size))
1283c8c29ec3SLuo bin 		return false;
1284c8c29ec3SLuo bin 
1285c8c29ec3SLuo bin 	return hinic_cmdq_check_vf_ctxt(hwdev, buf_in);
1286c8c29ec3SLuo bin }
1287c8c29ec3SLuo bin 
1288c8c29ec3SLuo bin #define HW_CTX_QPS_VALID(hw_ctxt)   \
1289c8c29ec3SLuo bin 		((hw_ctxt)->rq_depth >= HINIC_QUEUE_MIN_DEPTH &&	\
1290c8c29ec3SLuo bin 		(hw_ctxt)->rq_depth <= HINIC_QUEUE_MAX_DEPTH &&	\
1291c8c29ec3SLuo bin 		(hw_ctxt)->sq_depth >= HINIC_QUEUE_MIN_DEPTH &&	\
1292c8c29ec3SLuo bin 		(hw_ctxt)->sq_depth <= HINIC_QUEUE_MAX_DEPTH &&	\
1293c8c29ec3SLuo bin 		(hw_ctxt)->rx_buf_sz_idx <= HINIC_MAX_RX_BUFFER_SIZE)
1294c8c29ec3SLuo bin 
hw_ctxt_qps_param_valid(struct hinic_cmd_hw_ioctxt * hw_ctxt)1295c8c29ec3SLuo bin static bool hw_ctxt_qps_param_valid(struct hinic_cmd_hw_ioctxt *hw_ctxt)
1296c8c29ec3SLuo bin {
1297c8c29ec3SLuo bin 	if (HW_CTX_QPS_VALID(hw_ctxt))
1298c8c29ec3SLuo bin 		return true;
1299c8c29ec3SLuo bin 
1300c8c29ec3SLuo bin 	if (!hw_ctxt->rq_depth && !hw_ctxt->sq_depth &&
1301c8c29ec3SLuo bin 	    !hw_ctxt->rx_buf_sz_idx)
1302c8c29ec3SLuo bin 		return true;
1303c8c29ec3SLuo bin 
1304c8c29ec3SLuo bin 	return false;
1305c8c29ec3SLuo bin }
1306c8c29ec3SLuo bin 
check_hwctxt(struct hinic_hwdev * hwdev,u16 func_idx,void * buf_in,u16 in_size)1307c8c29ec3SLuo bin static bool check_hwctxt(struct hinic_hwdev *hwdev, u16 func_idx,
1308c8c29ec3SLuo bin 			 void *buf_in, u16 in_size)
1309c8c29ec3SLuo bin {
1310c8c29ec3SLuo bin 	struct hinic_cmd_hw_ioctxt *hw_ctxt = buf_in;
1311c8c29ec3SLuo bin 
1312c8c29ec3SLuo bin 	if (!hinic_mbox_check_func_id_8B(hwdev, func_idx, buf_in, in_size))
1313c8c29ec3SLuo bin 		return false;
1314c8c29ec3SLuo bin 
1315c8c29ec3SLuo bin 	if (hw_ctxt->ppf_idx != HINIC_HWIF_PPF_IDX(hwdev->hwif))
1316c8c29ec3SLuo bin 		return false;
1317c8c29ec3SLuo bin 
1318c8c29ec3SLuo bin 	if (hw_ctxt->set_cmdq_depth) {
1319c8c29ec3SLuo bin 		if (hw_ctxt->cmdq_depth >= HINIC_QUEUE_MIN_DEPTH &&
1320c8c29ec3SLuo bin 		    hw_ctxt->cmdq_depth <= HINIC_QUEUE_MAX_DEPTH)
1321c8c29ec3SLuo bin 			return true;
1322c8c29ec3SLuo bin 
1323c8c29ec3SLuo bin 		return false;
1324c8c29ec3SLuo bin 	}
1325c8c29ec3SLuo bin 
1326c8c29ec3SLuo bin 	return hw_ctxt_qps_param_valid(hw_ctxt);
1327c8c29ec3SLuo bin }
1328c8c29ec3SLuo bin 
check_set_wq_page_size(struct hinic_hwdev * hwdev,u16 func_idx,void * buf_in,u16 in_size)1329c8c29ec3SLuo bin static bool check_set_wq_page_size(struct hinic_hwdev *hwdev, u16 func_idx,
1330c8c29ec3SLuo bin 				   void *buf_in, u16 in_size)
1331c8c29ec3SLuo bin {
1332c8c29ec3SLuo bin 	struct hinic_wq_page_size *page_size_info = buf_in;
1333c8c29ec3SLuo bin 
1334c8c29ec3SLuo bin 	if (!hinic_mbox_check_func_id_8B(hwdev, func_idx, buf_in, in_size))
1335c8c29ec3SLuo bin 		return false;
1336c8c29ec3SLuo bin 
1337c8c29ec3SLuo bin 	if (page_size_info->ppf_idx != HINIC_HWIF_PPF_IDX(hwdev->hwif))
1338c8c29ec3SLuo bin 		return false;
1339c8c29ec3SLuo bin 
1340c8c29ec3SLuo bin 	if (((1U << page_size_info->page_size) * SZ_4K) !=
1341c8c29ec3SLuo bin 	    HINIC_DEFAULT_WQ_PAGE_SIZE)
1342c8c29ec3SLuo bin 		return false;
1343c8c29ec3SLuo bin 
1344c8c29ec3SLuo bin 	return true;
1345c8c29ec3SLuo bin }
1346c8c29ec3SLuo bin 
1347c8c29ec3SLuo bin static struct vf_cmd_check_handle hw_cmd_support_vf[] = {
1348c8c29ec3SLuo bin 	{HINIC_COMM_CMD_START_FLR, hinic_mbox_check_func_id_8B},
1349c8c29ec3SLuo bin 	{HINIC_COMM_CMD_DMA_ATTR_SET, hinic_mbox_check_func_id_8B},
1350c8c29ec3SLuo bin 	{HINIC_COMM_CMD_CMDQ_CTXT_SET, check_cmdq_ctxt},
1351c8c29ec3SLuo bin 	{HINIC_COMM_CMD_CMDQ_CTXT_GET, check_cmdq_ctxt},
1352c8c29ec3SLuo bin 	{HINIC_COMM_CMD_HWCTXT_SET, check_hwctxt},
1353c8c29ec3SLuo bin 	{HINIC_COMM_CMD_HWCTXT_GET, check_hwctxt},
1354c8c29ec3SLuo bin 	{HINIC_COMM_CMD_SQ_HI_CI_SET, hinic_mbox_check_func_id_8B},
1355c8c29ec3SLuo bin 	{HINIC_COMM_CMD_RES_STATE_SET, hinic_mbox_check_func_id_8B},
1356c8c29ec3SLuo bin 	{HINIC_COMM_CMD_IO_RES_CLEAR, hinic_mbox_check_func_id_8B},
1357c8c29ec3SLuo bin 	{HINIC_COMM_CMD_CEQ_CTRL_REG_WR_BY_UP, hinic_mbox_check_func_id_8B},
1358c8c29ec3SLuo bin 	{HINIC_COMM_CMD_MSI_CTRL_REG_WR_BY_UP, hinic_mbox_check_func_id_8B},
1359c8c29ec3SLuo bin 	{HINIC_COMM_CMD_MSI_CTRL_REG_RD_BY_UP, hinic_mbox_check_func_id_8B},
1360c8c29ec3SLuo bin 	{HINIC_COMM_CMD_L2NIC_RESET, hinic_mbox_check_func_id_8B},
1361c8c29ec3SLuo bin 	{HINIC_COMM_CMD_PAGESIZE_SET, check_set_wq_page_size},
1362c8c29ec3SLuo bin };
1363c8c29ec3SLuo bin 
comm_pf_mbox_handler(void * handle,u16 vf_id,u8 cmd,void * buf_in,u16 in_size,void * buf_out,u16 * out_size)1364a425b6e1SLuo bin static int comm_pf_mbox_handler(void *handle, u16 vf_id, u8 cmd, void *buf_in,
1365a425b6e1SLuo bin 				u16 in_size, void *buf_out, u16 *out_size)
1366a425b6e1SLuo bin {
1367c8c29ec3SLuo bin 	u8 size = ARRAY_SIZE(hw_cmd_support_vf);
1368a425b6e1SLuo bin 	struct hinic_hwdev *hwdev = handle;
1369a425b6e1SLuo bin 	struct hinic_pfhwdev *pfhwdev;
1370a425b6e1SLuo bin 	int err = 0;
1371a425b6e1SLuo bin 
1372a425b6e1SLuo bin 	pfhwdev = container_of(hwdev, struct hinic_pfhwdev, hwdev);
1373a425b6e1SLuo bin 
1374c8c29ec3SLuo bin 	if (!hinic_mbox_check_cmd_valid(handle, hw_cmd_support_vf, vf_id, cmd,
1375c8c29ec3SLuo bin 					buf_in, in_size, size)) {
1376c8c29ec3SLuo bin 		dev_err(&hwdev->hwif->pdev->dev,
1377c8c29ec3SLuo bin 			"PF Receive VF: %d common cmd: 0x%x or mbox len: 0x%x is invalid\n",
1378c8c29ec3SLuo bin 			vf_id + hinic_glb_pf_vf_offset(hwdev->hwif), cmd,
1379c8c29ec3SLuo bin 			in_size);
1380c8c29ec3SLuo bin 		return HINIC_MBOX_VF_CMD_ERROR;
1381c8c29ec3SLuo bin 	}
1382c8c29ec3SLuo bin 
1383a425b6e1SLuo bin 	if (cmd == HINIC_COMM_CMD_START_FLR) {
1384a425b6e1SLuo bin 		*out_size = 0;
1385a425b6e1SLuo bin 	} else {
1386a425b6e1SLuo bin 		err = hinic_msg_to_mgmt(&pfhwdev->pf_to_mgmt, HINIC_MOD_COMM,
1387a425b6e1SLuo bin 					cmd, buf_in, in_size, buf_out, out_size,
1388a425b6e1SLuo bin 					HINIC_MGMT_MSG_SYNC);
1389a425b6e1SLuo bin 		if (err && err != HINIC_MBOX_PF_BUSY_ACTIVE_FW)
1390a425b6e1SLuo bin 			dev_err(&hwdev->hwif->pdev->dev,
1391a425b6e1SLuo bin 				"PF mbox common callback handler err: %d\n",
1392a425b6e1SLuo bin 				err);
1393a425b6e1SLuo bin 	}
1394a425b6e1SLuo bin 
1395a425b6e1SLuo bin 	return err;
1396a425b6e1SLuo bin }
1397a425b6e1SLuo bin 
hinic_func_to_func_init(struct hinic_hwdev * hwdev)1398a425b6e1SLuo bin int hinic_func_to_func_init(struct hinic_hwdev *hwdev)
1399a425b6e1SLuo bin {
1400a425b6e1SLuo bin 	struct hinic_mbox_func_to_func *func_to_func;
1401a425b6e1SLuo bin 	struct hinic_pfhwdev *pfhwdev;
1402a425b6e1SLuo bin 	int err;
1403a425b6e1SLuo bin 
1404a425b6e1SLuo bin 	pfhwdev =  container_of(hwdev, struct hinic_pfhwdev, hwdev);
1405a425b6e1SLuo bin 	func_to_func = kzalloc(sizeof(*func_to_func), GFP_KERNEL);
1406a425b6e1SLuo bin 	if (!func_to_func)
1407a425b6e1SLuo bin 		return -ENOMEM;
1408a425b6e1SLuo bin 
1409a425b6e1SLuo bin 	hwdev->func_to_func = func_to_func;
1410a425b6e1SLuo bin 	func_to_func->hwdev = hwdev;
1411a425b6e1SLuo bin 	func_to_func->hwif = hwdev->hwif;
1412a425b6e1SLuo bin 	sema_init(&func_to_func->mbox_send_sem, 1);
1413a425b6e1SLuo bin 	sema_init(&func_to_func->msg_send_sem, 1);
1414a425b6e1SLuo bin 	spin_lock_init(&func_to_func->mbox_lock);
1415a425b6e1SLuo bin 	func_to_func->workq = create_singlethread_workqueue(HINIC_MBOX_WQ_NAME);
1416a425b6e1SLuo bin 	if (!func_to_func->workq) {
1417a425b6e1SLuo bin 		dev_err(&hwdev->hwif->pdev->dev, "Failed to initialize MBOX workqueue\n");
1418a425b6e1SLuo bin 		err = -ENOMEM;
1419a425b6e1SLuo bin 		goto err_create_mbox_workq;
1420a425b6e1SLuo bin 	}
1421a425b6e1SLuo bin 
1422a425b6e1SLuo bin 	err = alloc_mbox_info(hwdev, func_to_func->mbox_send);
1423a425b6e1SLuo bin 	if (err) {
1424a425b6e1SLuo bin 		dev_err(&hwdev->hwif->pdev->dev, "Failed to alloc mem for mbox_active\n");
1425a425b6e1SLuo bin 		goto err_alloc_mbox_for_send;
1426a425b6e1SLuo bin 	}
1427a425b6e1SLuo bin 
1428a425b6e1SLuo bin 	err = alloc_mbox_info(hwdev, func_to_func->mbox_resp);
1429a425b6e1SLuo bin 	if (err) {
1430a425b6e1SLuo bin 		dev_err(&hwdev->hwif->pdev->dev, "Failed to alloc mem for mbox_passive\n");
1431a425b6e1SLuo bin 		goto err_alloc_mbox_for_resp;
1432a425b6e1SLuo bin 	}
1433a425b6e1SLuo bin 
1434a425b6e1SLuo bin 	err = alloc_mbox_wb_status(func_to_func);
1435a425b6e1SLuo bin 	if (err) {
1436a425b6e1SLuo bin 		dev_err(&hwdev->hwif->pdev->dev, "Failed to alloc mbox write back status\n");
1437a425b6e1SLuo bin 		goto err_alloc_wb_status;
1438a425b6e1SLuo bin 	}
1439a425b6e1SLuo bin 
1440a425b6e1SLuo bin 	prepare_send_mbox(func_to_func);
1441a425b6e1SLuo bin 
1442a425b6e1SLuo bin 	hinic_aeq_register_hw_cb(&hwdev->aeqs, HINIC_MBX_FROM_FUNC,
1443a425b6e1SLuo bin 				 &pfhwdev->hwdev, hinic_mbox_func_aeqe_handler);
1444a425b6e1SLuo bin 	hinic_aeq_register_hw_cb(&hwdev->aeqs, HINIC_MBX_SEND_RSLT,
1445a425b6e1SLuo bin 				 &pfhwdev->hwdev, hinic_mbox_self_aeqe_handler);
1446a425b6e1SLuo bin 
1447a425b6e1SLuo bin 	if (!HINIC_IS_VF(hwdev->hwif))
1448a425b6e1SLuo bin 		hinic_register_pf_mbox_cb(hwdev, HINIC_MOD_COMM,
1449a425b6e1SLuo bin 					  comm_pf_mbox_handler);
1450a425b6e1SLuo bin 
1451a425b6e1SLuo bin 	return 0;
1452a425b6e1SLuo bin 
1453a425b6e1SLuo bin err_alloc_wb_status:
1454a425b6e1SLuo bin 	free_mbox_info(func_to_func->mbox_resp);
1455a425b6e1SLuo bin 
1456a425b6e1SLuo bin err_alloc_mbox_for_resp:
1457a425b6e1SLuo bin 	free_mbox_info(func_to_func->mbox_send);
1458a425b6e1SLuo bin 
1459a425b6e1SLuo bin err_alloc_mbox_for_send:
1460a425b6e1SLuo bin 	destroy_workqueue(func_to_func->workq);
1461a425b6e1SLuo bin 
1462a425b6e1SLuo bin err_create_mbox_workq:
1463a425b6e1SLuo bin 	kfree(func_to_func);
1464a425b6e1SLuo bin 
1465a425b6e1SLuo bin 	return err;
1466a425b6e1SLuo bin }
1467a425b6e1SLuo bin 
hinic_func_to_func_free(struct hinic_hwdev * hwdev)1468a425b6e1SLuo bin void hinic_func_to_func_free(struct hinic_hwdev *hwdev)
1469a425b6e1SLuo bin {
1470a425b6e1SLuo bin 	struct hinic_mbox_func_to_func *func_to_func = hwdev->func_to_func;
1471a425b6e1SLuo bin 
1472a425b6e1SLuo bin 	hinic_aeq_unregister_hw_cb(&hwdev->aeqs, HINIC_MBX_FROM_FUNC);
1473a425b6e1SLuo bin 	hinic_aeq_unregister_hw_cb(&hwdev->aeqs, HINIC_MBX_SEND_RSLT);
1474a425b6e1SLuo bin 
1475a425b6e1SLuo bin 	hinic_unregister_pf_mbox_cb(hwdev, HINIC_MOD_COMM);
1476a425b6e1SLuo bin 	/* destroy workqueue before free related mbox resources in case of
1477a425b6e1SLuo bin 	 * illegal resource access
1478a425b6e1SLuo bin 	 */
1479a425b6e1SLuo bin 	destroy_workqueue(func_to_func->workq);
1480a425b6e1SLuo bin 
1481a425b6e1SLuo bin 	free_mbox_wb_status(func_to_func);
1482a425b6e1SLuo bin 	free_mbox_info(func_to_func->mbox_resp);
1483a425b6e1SLuo bin 	free_mbox_info(func_to_func->mbox_send);
1484a425b6e1SLuo bin 
1485a425b6e1SLuo bin 	kfree(func_to_func);
1486a425b6e1SLuo bin }
1487088c5f0dSLuo bin 
hinic_vf_mbox_random_id_init(struct hinic_hwdev * hwdev)1488088c5f0dSLuo bin int hinic_vf_mbox_random_id_init(struct hinic_hwdev *hwdev)
1489088c5f0dSLuo bin {
1490088c5f0dSLuo bin 	u16 vf_offset;
1491088c5f0dSLuo bin 	u8 vf_in_pf;
1492088c5f0dSLuo bin 	int err = 0;
1493088c5f0dSLuo bin 
1494088c5f0dSLuo bin 	if (HINIC_IS_VF(hwdev->hwif))
1495088c5f0dSLuo bin 		return 0;
1496088c5f0dSLuo bin 
1497088c5f0dSLuo bin 	vf_offset = hinic_glb_pf_vf_offset(hwdev->hwif);
1498088c5f0dSLuo bin 
1499088c5f0dSLuo bin 	for (vf_in_pf = 1; vf_in_pf <= hwdev->nic_cap.max_vf; vf_in_pf++) {
1500088c5f0dSLuo bin 		err = set_vf_mbox_random_id(hwdev, vf_offset + vf_in_pf);
1501088c5f0dSLuo bin 		if (err)
1502088c5f0dSLuo bin 			break;
1503088c5f0dSLuo bin 	}
1504088c5f0dSLuo bin 
1505088c5f0dSLuo bin 	if (err == HINIC_MGMT_CMD_UNSUPPORTED) {
1506088c5f0dSLuo bin 		hwdev->func_to_func->support_vf_random = false;
1507088c5f0dSLuo bin 		err = 0;
1508088c5f0dSLuo bin 		dev_warn(&hwdev->hwif->pdev->dev, "Mgmt is unsupported to set VF%d random id\n",
1509088c5f0dSLuo bin 			 vf_in_pf - 1);
1510088c5f0dSLuo bin 	} else if (!err) {
1511088c5f0dSLuo bin 		hwdev->func_to_func->support_vf_random = true;
1512088c5f0dSLuo bin 	}
1513088c5f0dSLuo bin 
1514088c5f0dSLuo bin 	return err;
1515088c5f0dSLuo bin }
1516