1a4957d87SZiyang Xuan /* SPDX-License-Identifier: BSD-3-Clause
2a4957d87SZiyang Xuan * Copyright(c) 2017 Huawei Technologies Co., Ltd
3a4957d87SZiyang Xuan */
4a4957d87SZiyang Xuan
5a4957d87SZiyang Xuan #include "hinic_compat.h"
6a4957d87SZiyang Xuan #include "hinic_csr.h"
7a4957d87SZiyang Xuan #include "hinic_pmd_hwdev.h"
8a4957d87SZiyang Xuan #include "hinic_pmd_hwif.h"
9a4957d87SZiyang Xuan #include "hinic_pmd_mgmt.h"
10b8582d05SXiaoyun Wang #include "hinic_pmd_mbox.h"
11a4957d87SZiyang Xuan
12a4957d87SZiyang Xuan #define BUF_OUT_DEFAULT_SIZE 1
13a4957d87SZiyang Xuan
14a4957d87SZiyang Xuan #define MAX_PF_MGMT_BUF_SIZE 2048UL
15a4957d87SZiyang Xuan
16a4957d87SZiyang Xuan #define MGMT_MSG_SIZE_MIN 20
17a4957d87SZiyang Xuan #define MGMT_MSG_SIZE_STEP 16
18a4957d87SZiyang Xuan #define MGMT_MSG_RSVD_FOR_DEV 8
19a4957d87SZiyang Xuan
20a4957d87SZiyang Xuan #define MGMT_MSG_TIMEOUT 5000 /* millisecond */
21a4957d87SZiyang Xuan
22a4957d87SZiyang Xuan #define SYNC_MSG_ID_MASK 0x1FF
23a4957d87SZiyang Xuan #define ASYNC_MSG_ID_MASK 0x1FF
24a4957d87SZiyang Xuan #define ASYNC_MSG_FLAG 0x200
25a4957d87SZiyang Xuan
26a4957d87SZiyang Xuan #define MSG_NO_RESP 0xFFFF
27a4957d87SZiyang Xuan
28a4957d87SZiyang Xuan #define MAX_MSG_SZ 2016
29a4957d87SZiyang Xuan
30a4957d87SZiyang Xuan #define MSG_SZ_IS_VALID(in_size) ((in_size) <= MAX_MSG_SZ)
31a4957d87SZiyang Xuan
32a4957d87SZiyang Xuan #define SYNC_MSG_ID(pf_to_mgmt) ((pf_to_mgmt)->sync_msg_id)
33a4957d87SZiyang Xuan
34a4957d87SZiyang Xuan #define SYNC_MSG_ID_INC(pf_to_mgmt) (SYNC_MSG_ID(pf_to_mgmt) = \
35a4957d87SZiyang Xuan (SYNC_MSG_ID(pf_to_mgmt) + 1) & SYNC_MSG_ID_MASK)
36a4957d87SZiyang Xuan
37a4957d87SZiyang Xuan #define ASYNC_MSG_ID(pf_to_mgmt) ((pf_to_mgmt)->async_msg_id)
38a4957d87SZiyang Xuan
39a4957d87SZiyang Xuan #define ASYNC_MSG_ID_INC(pf_to_mgmt) (ASYNC_MSG_ID(pf_to_mgmt) = \
40a4957d87SZiyang Xuan ((ASYNC_MSG_ID(pf_to_mgmt) + 1) & ASYNC_MSG_ID_MASK) \
41a4957d87SZiyang Xuan | ASYNC_MSG_FLAG)
42a4957d87SZiyang Xuan
43a4957d87SZiyang Xuan #define HINIC_SEQ_ID_MAX_VAL 42
44a4957d87SZiyang Xuan #define HINIC_MSG_SEG_LEN 48
45a4957d87SZiyang Xuan
46a4957d87SZiyang Xuan #define GET_CURR_AEQ_ELEM(eq) GET_AEQ_ELEM((eq), (eq)->cons_idx)
47a4957d87SZiyang Xuan
48a4957d87SZiyang Xuan #define EQ_ELEM_DESC_TYPE_SHIFT 0
49a4957d87SZiyang Xuan #define EQ_ELEM_DESC_SRC_SHIFT 7
50a4957d87SZiyang Xuan #define EQ_ELEM_DESC_SIZE_SHIFT 8
51a4957d87SZiyang Xuan #define EQ_ELEM_DESC_WRAPPED_SHIFT 31
52a4957d87SZiyang Xuan
53a4957d87SZiyang Xuan #define EQ_ELEM_DESC_TYPE_MASK 0x7FU
54a4957d87SZiyang Xuan #define EQ_ELEM_DESC_SRC_MASK 0x1U
55a4957d87SZiyang Xuan #define EQ_ELEM_DESC_SIZE_MASK 0xFFU
56a4957d87SZiyang Xuan #define EQ_ELEM_DESC_WRAPPED_MASK 0x1U
57a4957d87SZiyang Xuan
58a4957d87SZiyang Xuan #define EQ_MSIX_RESEND_TIMER_CLEAR 1
59a4957d87SZiyang Xuan
60a4957d87SZiyang Xuan #define EQ_ELEM_DESC_GET(val, member) \
61a4957d87SZiyang Xuan (((val) >> EQ_ELEM_DESC_##member##_SHIFT) & \
62a4957d87SZiyang Xuan EQ_ELEM_DESC_##member##_MASK)
63a4957d87SZiyang Xuan
64a4957d87SZiyang Xuan #define HINIC_MGMT_CHANNEL_STATUS_SHIFT 0x0
65a4957d87SZiyang Xuan #define HINIC_MGMT_CHANNEL_STATUS_MASK 0x1
66a4957d87SZiyang Xuan
67a4957d87SZiyang Xuan #define HINIC_GET_MGMT_CHANNEL_STATUS(val, member) \
68a4957d87SZiyang Xuan (((val) >> HINIC_##member##_SHIFT) & HINIC_##member##_MASK)
69a4957d87SZiyang Xuan
70a4957d87SZiyang Xuan #define HINIC_MSG_TO_MGMT_MAX_LEN 2016
71a4957d87SZiyang Xuan
72a4957d87SZiyang Xuan /**
73a4957d87SZiyang Xuan * mgmt_msg_len - calculate the total message length
74a4957d87SZiyang Xuan * @msg_data_len: the length of the message data
75a4957d87SZiyang Xuan * Return: the total message length
76b8582d05SXiaoyun Wang */
mgmt_msg_len(u16 msg_data_len)77a4957d87SZiyang Xuan static u16 mgmt_msg_len(u16 msg_data_len)
78a4957d87SZiyang Xuan {
79a4957d87SZiyang Xuan /* u64 - the size of the header */
80a4957d87SZiyang Xuan u16 msg_size = (u16)(MGMT_MSG_RSVD_FOR_DEV + sizeof(u64) +
81a4957d87SZiyang Xuan msg_data_len);
82a4957d87SZiyang Xuan
83a4957d87SZiyang Xuan if (msg_size > MGMT_MSG_SIZE_MIN)
84a4957d87SZiyang Xuan msg_size = MGMT_MSG_SIZE_MIN +
85a4957d87SZiyang Xuan ALIGN((msg_size - MGMT_MSG_SIZE_MIN),
86a4957d87SZiyang Xuan MGMT_MSG_SIZE_STEP);
87a4957d87SZiyang Xuan else
88a4957d87SZiyang Xuan msg_size = MGMT_MSG_SIZE_MIN;
89a4957d87SZiyang Xuan
90a4957d87SZiyang Xuan return msg_size;
91a4957d87SZiyang Xuan }
92a4957d87SZiyang Xuan
93a4957d87SZiyang Xuan /**
94a4957d87SZiyang Xuan * prepare_header - prepare the header of the message
95a4957d87SZiyang Xuan * @pf_to_mgmt: PF to MGMT channel
96a4957d87SZiyang Xuan * @header: pointer of the header to prepare
97a4957d87SZiyang Xuan * @msg_len: the length of the message
98a4957d87SZiyang Xuan * @mod: module in the chip that will get the message
99a4957d87SZiyang Xuan * @ack_type: the type to response
100a4957d87SZiyang Xuan * @direction: the direction of the original message
101a4957d87SZiyang Xuan * @cmd: the command to do
102a4957d87SZiyang Xuan * @msg_id: message id
103b8582d05SXiaoyun Wang */
prepare_header(struct hinic_msg_pf_to_mgmt * pf_to_mgmt,u64 * header,int msg_len,enum hinic_mod_type mod,enum hinic_msg_ack_type ack_type,enum hinic_msg_direction_type direction,u8 cmd,u32 msg_id)104a4957d87SZiyang Xuan static void prepare_header(struct hinic_msg_pf_to_mgmt *pf_to_mgmt,
105a4957d87SZiyang Xuan u64 *header, int msg_len, enum hinic_mod_type mod,
106a4957d87SZiyang Xuan enum hinic_msg_ack_type ack_type,
107a4957d87SZiyang Xuan enum hinic_msg_direction_type direction,
108a4957d87SZiyang Xuan u8 cmd, u32 msg_id)
109a4957d87SZiyang Xuan {
110a4957d87SZiyang Xuan struct hinic_hwif *hwif = pf_to_mgmt->hwdev->hwif;
111a4957d87SZiyang Xuan
112a4957d87SZiyang Xuan *header = HINIC_MSG_HEADER_SET(msg_len, MSG_LEN) |
113a4957d87SZiyang Xuan HINIC_MSG_HEADER_SET(mod, MODULE) |
114a4957d87SZiyang Xuan HINIC_MSG_HEADER_SET(msg_len, SEG_LEN) |
115a4957d87SZiyang Xuan HINIC_MSG_HEADER_SET(ack_type, NO_ACK) |
116a4957d87SZiyang Xuan HINIC_MSG_HEADER_SET(0, ASYNC_MGMT_TO_PF) |
117a4957d87SZiyang Xuan HINIC_MSG_HEADER_SET(0, SEQID) |
118a4957d87SZiyang Xuan HINIC_MSG_HEADER_SET(LAST_SEGMENT, LAST) |
119a4957d87SZiyang Xuan HINIC_MSG_HEADER_SET(direction, DIRECTION) |
120a4957d87SZiyang Xuan HINIC_MSG_HEADER_SET(cmd, CMD) |
121a4957d87SZiyang Xuan HINIC_MSG_HEADER_SET(HINIC_PCI_INTF_IDX(hwif), PCI_INTF_IDX) |
122a4957d87SZiyang Xuan HINIC_MSG_HEADER_SET(hwif->attr.port_to_port_idx, P2P_IDX) |
123a4957d87SZiyang Xuan HINIC_MSG_HEADER_SET(msg_id, MSG_ID);
124a4957d87SZiyang Xuan }
125a4957d87SZiyang Xuan
126a4957d87SZiyang Xuan /**
127a4957d87SZiyang Xuan * prepare_mgmt_cmd - prepare the mgmt command
128a4957d87SZiyang Xuan * @mgmt_cmd: pointer to the command to prepare
129a4957d87SZiyang Xuan * @header: pointer of the header to prepare
130a4957d87SZiyang Xuan * @msg: the data of the message
131a4957d87SZiyang Xuan * @msg_len: the length of the message
132b8582d05SXiaoyun Wang */
prepare_mgmt_cmd(u8 * mgmt_cmd,u64 * header,void * msg,int msg_len)133a4957d87SZiyang Xuan static void prepare_mgmt_cmd(u8 *mgmt_cmd, u64 *header, void *msg,
134a4957d87SZiyang Xuan int msg_len)
135a4957d87SZiyang Xuan {
136a4957d87SZiyang Xuan memset(mgmt_cmd, 0, MGMT_MSG_RSVD_FOR_DEV);
137a4957d87SZiyang Xuan
138a4957d87SZiyang Xuan mgmt_cmd += MGMT_MSG_RSVD_FOR_DEV;
139a4957d87SZiyang Xuan memcpy(mgmt_cmd, header, sizeof(*header));
140a4957d87SZiyang Xuan
141a4957d87SZiyang Xuan mgmt_cmd += sizeof(*header);
142a4957d87SZiyang Xuan memcpy(mgmt_cmd, msg, msg_len);
143a4957d87SZiyang Xuan }
144a4957d87SZiyang Xuan
145a4957d87SZiyang Xuan /**
146a4957d87SZiyang Xuan * alloc_recv_msg - allocate received message memory
147a4957d87SZiyang Xuan * @recv_msg: pointer that will hold the allocated data
148a4957d87SZiyang Xuan * Return: 0 - success, negative - failure
149b8582d05SXiaoyun Wang */
alloc_recv_msg(struct hinic_recv_msg * recv_msg)150a4957d87SZiyang Xuan static int alloc_recv_msg(struct hinic_recv_msg *recv_msg)
151a4957d87SZiyang Xuan {
152a4957d87SZiyang Xuan int err;
153a4957d87SZiyang Xuan
154a4957d87SZiyang Xuan recv_msg->msg = kzalloc(MAX_PF_MGMT_BUF_SIZE, GFP_KERNEL);
155a4957d87SZiyang Xuan if (!recv_msg->msg) {
156a4957d87SZiyang Xuan PMD_DRV_LOG(ERR, "Allocate recv msg buf failed");
157a4957d87SZiyang Xuan return -ENOMEM;
158a4957d87SZiyang Xuan }
159a4957d87SZiyang Xuan
160a4957d87SZiyang Xuan recv_msg->buf_out = kzalloc(MAX_PF_MGMT_BUF_SIZE, GFP_KERNEL);
161a4957d87SZiyang Xuan if (!recv_msg->buf_out) {
162a4957d87SZiyang Xuan PMD_DRV_LOG(ERR, "Allocate recv msg output buf failed");
163a4957d87SZiyang Xuan err = -ENOMEM;
164a4957d87SZiyang Xuan goto alloc_buf_out_err;
165a4957d87SZiyang Xuan }
166a4957d87SZiyang Xuan
167a4957d87SZiyang Xuan return 0;
168a4957d87SZiyang Xuan
169a4957d87SZiyang Xuan alloc_buf_out_err:
170a4957d87SZiyang Xuan kfree(recv_msg->msg);
171a4957d87SZiyang Xuan return err;
172a4957d87SZiyang Xuan }
173a4957d87SZiyang Xuan
174a4957d87SZiyang Xuan /**
175a4957d87SZiyang Xuan * free_recv_msg - free received message memory
176a4957d87SZiyang Xuan * @recv_msg: pointer that holds the allocated data
177b8582d05SXiaoyun Wang */
free_recv_msg(struct hinic_recv_msg * recv_msg)178a4957d87SZiyang Xuan static void free_recv_msg(struct hinic_recv_msg *recv_msg)
179a4957d87SZiyang Xuan {
180a4957d87SZiyang Xuan kfree(recv_msg->buf_out);
181a4957d87SZiyang Xuan kfree(recv_msg->msg);
182a4957d87SZiyang Xuan }
183a4957d87SZiyang Xuan
184a4957d87SZiyang Xuan /**
185a4957d87SZiyang Xuan * alloc_msg_buf - allocate all the message buffers of PF to MGMT channel
186a4957d87SZiyang Xuan * @pf_to_mgmt: PF to MGMT channel
187a4957d87SZiyang Xuan * Return: 0 - success, negative - failure
188b8582d05SXiaoyun Wang */
alloc_msg_buf(struct hinic_msg_pf_to_mgmt * pf_to_mgmt)189a4957d87SZiyang Xuan static int alloc_msg_buf(struct hinic_msg_pf_to_mgmt *pf_to_mgmt)
190a4957d87SZiyang Xuan {
191a4957d87SZiyang Xuan int err;
192a4957d87SZiyang Xuan
193a4957d87SZiyang Xuan err = alloc_recv_msg(&pf_to_mgmt->recv_msg_from_mgmt);
194a4957d87SZiyang Xuan if (err) {
195a4957d87SZiyang Xuan PMD_DRV_LOG(ERR, "Allocate recv msg failed");
196a4957d87SZiyang Xuan return err;
197a4957d87SZiyang Xuan }
198a4957d87SZiyang Xuan
199a4957d87SZiyang Xuan err = alloc_recv_msg(&pf_to_mgmt->recv_resp_msg_from_mgmt);
200a4957d87SZiyang Xuan if (err) {
201a4957d87SZiyang Xuan PMD_DRV_LOG(ERR, "Allocate resp recv msg failed");
202a4957d87SZiyang Xuan goto alloc_msg_for_resp_err;
203a4957d87SZiyang Xuan }
204a4957d87SZiyang Xuan
205a4957d87SZiyang Xuan pf_to_mgmt->async_msg_buf = kzalloc(MAX_PF_MGMT_BUF_SIZE, GFP_KERNEL);
206a4957d87SZiyang Xuan if (!pf_to_mgmt->async_msg_buf) {
207a4957d87SZiyang Xuan PMD_DRV_LOG(ERR, "Allocate async msg buf failed");
208a4957d87SZiyang Xuan err = -ENOMEM;
209a4957d87SZiyang Xuan goto async_msg_buf_err;
210a4957d87SZiyang Xuan }
211a4957d87SZiyang Xuan
212a4957d87SZiyang Xuan pf_to_mgmt->sync_msg_buf = kzalloc(MAX_PF_MGMT_BUF_SIZE, GFP_KERNEL);
213a4957d87SZiyang Xuan if (!pf_to_mgmt->sync_msg_buf) {
214a4957d87SZiyang Xuan PMD_DRV_LOG(ERR, "Allocate sync msg buf failed");
215a4957d87SZiyang Xuan err = -ENOMEM;
216a4957d87SZiyang Xuan goto sync_msg_buf_err;
217a4957d87SZiyang Xuan }
218a4957d87SZiyang Xuan
219a4957d87SZiyang Xuan return 0;
220a4957d87SZiyang Xuan
221a4957d87SZiyang Xuan sync_msg_buf_err:
222a4957d87SZiyang Xuan kfree(pf_to_mgmt->async_msg_buf);
223a4957d87SZiyang Xuan
224a4957d87SZiyang Xuan async_msg_buf_err:
225a4957d87SZiyang Xuan free_recv_msg(&pf_to_mgmt->recv_resp_msg_from_mgmt);
226a4957d87SZiyang Xuan
227a4957d87SZiyang Xuan alloc_msg_for_resp_err:
228a4957d87SZiyang Xuan free_recv_msg(&pf_to_mgmt->recv_msg_from_mgmt);
229a4957d87SZiyang Xuan
230a4957d87SZiyang Xuan return err;
231a4957d87SZiyang Xuan }
232a4957d87SZiyang Xuan
233a4957d87SZiyang Xuan /**
234a4957d87SZiyang Xuan * free_msg_buf - free all the message buffers of PF to MGMT channel
235a4957d87SZiyang Xuan * @pf_to_mgmt: PF to MGMT channel
236a4957d87SZiyang Xuan * Return: 0 - success, negative - failure
237b8582d05SXiaoyun Wang */
free_msg_buf(struct hinic_msg_pf_to_mgmt * pf_to_mgmt)238a4957d87SZiyang Xuan static void free_msg_buf(struct hinic_msg_pf_to_mgmt *pf_to_mgmt)
239a4957d87SZiyang Xuan {
240a4957d87SZiyang Xuan kfree(pf_to_mgmt->sync_msg_buf);
241a4957d87SZiyang Xuan kfree(pf_to_mgmt->async_msg_buf);
242a4957d87SZiyang Xuan
243a4957d87SZiyang Xuan free_recv_msg(&pf_to_mgmt->recv_resp_msg_from_mgmt);
244a4957d87SZiyang Xuan free_recv_msg(&pf_to_mgmt->recv_msg_from_mgmt);
245a4957d87SZiyang Xuan }
246a4957d87SZiyang Xuan
hinic_get_mgmt_channel_status(void * hwdev)247036b61d8SXiaoyun Wang static int hinic_get_mgmt_channel_status(void *hwdev)
248036b61d8SXiaoyun Wang {
249036b61d8SXiaoyun Wang struct hinic_hwif *hwif = ((struct hinic_hwdev *)hwdev)->hwif;
250036b61d8SXiaoyun Wang u32 val;
251036b61d8SXiaoyun Wang
252036b61d8SXiaoyun Wang if (hinic_func_type((struct hinic_hwdev *)hwdev) == TYPE_VF)
253036b61d8SXiaoyun Wang return false;
254036b61d8SXiaoyun Wang
255036b61d8SXiaoyun Wang val = hinic_hwif_read_reg(hwif, HINIC_ICPL_RESERVD_ADDR);
256036b61d8SXiaoyun Wang
257036b61d8SXiaoyun Wang return HINIC_GET_MGMT_CHANNEL_STATUS(val, MGMT_CHANNEL_STATUS);
258036b61d8SXiaoyun Wang }
259036b61d8SXiaoyun Wang
260a4957d87SZiyang Xuan /**
261a4957d87SZiyang Xuan * send_msg_to_mgmt_async - send async message
262a4957d87SZiyang Xuan * @pf_to_mgmt: PF to MGMT channel
263a4957d87SZiyang Xuan * @mod: module in the chip that will get the message
264a4957d87SZiyang Xuan * @cmd: command of the message
265a4957d87SZiyang Xuan * @msg: the data of the message
266a4957d87SZiyang Xuan * @msg_len: the length of the message
267a4957d87SZiyang Xuan * @direction: the direction of the original message
268a4957d87SZiyang Xuan * @resp_msg_id: message id of response
269a4957d87SZiyang Xuan * Return: 0 - success, negative - failure
270b8582d05SXiaoyun Wang */
send_msg_to_mgmt_async(struct hinic_msg_pf_to_mgmt * pf_to_mgmt,enum hinic_mod_type mod,u8 cmd,void * msg,u16 msg_len,enum hinic_msg_direction_type direction,u16 resp_msg_id)271a4957d87SZiyang Xuan static int send_msg_to_mgmt_async(struct hinic_msg_pf_to_mgmt *pf_to_mgmt,
272a4957d87SZiyang Xuan enum hinic_mod_type mod, u8 cmd,
273a4957d87SZiyang Xuan void *msg, u16 msg_len,
274a4957d87SZiyang Xuan enum hinic_msg_direction_type direction,
275a4957d87SZiyang Xuan u16 resp_msg_id)
276a4957d87SZiyang Xuan {
277a4957d87SZiyang Xuan void *mgmt_cmd = pf_to_mgmt->async_msg_buf;
278a4957d87SZiyang Xuan struct hinic_api_cmd_chain *chain;
279a4957d87SZiyang Xuan u64 header;
280a4957d87SZiyang Xuan u16 cmd_size = mgmt_msg_len(msg_len);
281a4957d87SZiyang Xuan
282a4957d87SZiyang Xuan if (direction == HINIC_MSG_RESPONSE)
283a4957d87SZiyang Xuan prepare_header(pf_to_mgmt, &header, msg_len, mod, HINIC_MSG_ACK,
284a4957d87SZiyang Xuan direction, cmd, resp_msg_id);
285a4957d87SZiyang Xuan else
286a4957d87SZiyang Xuan prepare_header(pf_to_mgmt, &header, msg_len, mod, HINIC_MSG_ACK,
287a4957d87SZiyang Xuan direction, cmd, ASYNC_MSG_ID(pf_to_mgmt));
288a4957d87SZiyang Xuan
289a4957d87SZiyang Xuan prepare_mgmt_cmd((u8 *)mgmt_cmd, &header, msg, msg_len);
290a4957d87SZiyang Xuan
291a4957d87SZiyang Xuan chain = pf_to_mgmt->cmd_chain[HINIC_API_CMD_WRITE_ASYNC_TO_MGMT_CPU];
292a4957d87SZiyang Xuan
293a4957d87SZiyang Xuan return hinic_api_cmd_write(chain, HINIC_NODE_ID_MGMT_HOST, mgmt_cmd,
294a4957d87SZiyang Xuan cmd_size);
295a4957d87SZiyang Xuan }
296a4957d87SZiyang Xuan
297a4957d87SZiyang Xuan /**
298a4957d87SZiyang Xuan * send_msg_to_mgmt_sync - send async message
299a4957d87SZiyang Xuan * @pf_to_mgmt: PF to MGMT channel
300a4957d87SZiyang Xuan * @mod: module in the chip that will get the message
301a4957d87SZiyang Xuan * @cmd: command of the message
302a4957d87SZiyang Xuan * @msg: the msg data
303a4957d87SZiyang Xuan * @msg_len: the msg data length
304a4957d87SZiyang Xuan * @ack_type: indicate mgmt command whether need ack or not
305a4957d87SZiyang Xuan * @direction: the direction of the original message
306a4957d87SZiyang Xuan * @resp_msg_id: msg id to response for
307a4957d87SZiyang Xuan * Return: 0 - success, negative - failure
308b8582d05SXiaoyun Wang */
send_msg_to_mgmt_sync(struct hinic_msg_pf_to_mgmt * pf_to_mgmt,enum hinic_mod_type mod,u8 cmd,void * msg,u16 msg_len,enum hinic_msg_ack_type ack_type,enum hinic_msg_direction_type direction,__rte_unused u16 resp_msg_id)309a4957d87SZiyang Xuan static int send_msg_to_mgmt_sync(struct hinic_msg_pf_to_mgmt *pf_to_mgmt,
310a4957d87SZiyang Xuan enum hinic_mod_type mod, u8 cmd,
311a4957d87SZiyang Xuan void *msg, u16 msg_len,
312a4957d87SZiyang Xuan enum hinic_msg_ack_type ack_type,
313a4957d87SZiyang Xuan enum hinic_msg_direction_type direction,
314a4957d87SZiyang Xuan __rte_unused u16 resp_msg_id)
315a4957d87SZiyang Xuan {
316a4957d87SZiyang Xuan void *mgmt_cmd = pf_to_mgmt->sync_msg_buf;
317a4957d87SZiyang Xuan struct hinic_api_cmd_chain *chain;
318a4957d87SZiyang Xuan u64 header;
319a4957d87SZiyang Xuan u16 cmd_size = mgmt_msg_len(msg_len);
320a4957d87SZiyang Xuan
321036b61d8SXiaoyun Wang /* If fw is hot active, return failed */
322036b61d8SXiaoyun Wang if (hinic_get_mgmt_channel_status(pf_to_mgmt->hwdev)) {
323036b61d8SXiaoyun Wang if (mod == HINIC_MOD_COMM || mod == HINIC_MOD_L2NIC)
324036b61d8SXiaoyun Wang return HINIC_DEV_BUSY_ACTIVE_FW;
325036b61d8SXiaoyun Wang else
326036b61d8SXiaoyun Wang return -EBUSY;
327036b61d8SXiaoyun Wang }
328036b61d8SXiaoyun Wang
329a4957d87SZiyang Xuan if (direction == HINIC_MSG_RESPONSE)
330a4957d87SZiyang Xuan prepare_header(pf_to_mgmt, &header, msg_len, mod, ack_type,
331a4957d87SZiyang Xuan direction, cmd, resp_msg_id);
332a4957d87SZiyang Xuan else
333a4957d87SZiyang Xuan prepare_header(pf_to_mgmt, &header, msg_len, mod, ack_type,
334a4957d87SZiyang Xuan direction, cmd, SYNC_MSG_ID(pf_to_mgmt));
335a4957d87SZiyang Xuan
336a4957d87SZiyang Xuan prepare_mgmt_cmd((u8 *)mgmt_cmd, &header, msg, msg_len);
337a4957d87SZiyang Xuan
338a4957d87SZiyang Xuan chain = pf_to_mgmt->cmd_chain[HINIC_API_CMD_PMD_WRITE_TO_MGMT];
339a4957d87SZiyang Xuan
340a4957d87SZiyang Xuan return hinic_api_cmd_write(chain, HINIC_NODE_ID_MGMT_HOST,
341a4957d87SZiyang Xuan mgmt_cmd, cmd_size);
342a4957d87SZiyang Xuan }
343a4957d87SZiyang Xuan
344a4957d87SZiyang Xuan /**
345a4957d87SZiyang Xuan * hinic_pf_to_mgmt_init - initialize PF to MGMT channel
346a4957d87SZiyang Xuan * @hwdev: the pointer to the private hardware device object
347a4957d87SZiyang Xuan * Return: 0 - success, negative - failure
348b8582d05SXiaoyun Wang */
hinic_pf_to_mgmt_init(struct hinic_hwdev * hwdev)349a4957d87SZiyang Xuan static int hinic_pf_to_mgmt_init(struct hinic_hwdev *hwdev)
350a4957d87SZiyang Xuan {
351a4957d87SZiyang Xuan struct hinic_msg_pf_to_mgmt *pf_to_mgmt;
352a4957d87SZiyang Xuan int err;
353a4957d87SZiyang Xuan
354a4957d87SZiyang Xuan pf_to_mgmt = kzalloc(sizeof(*pf_to_mgmt), GFP_KERNEL);
355a4957d87SZiyang Xuan if (!pf_to_mgmt) {
356a4957d87SZiyang Xuan PMD_DRV_LOG(ERR, "Allocate pf to mgmt mem failed");
357a4957d87SZiyang Xuan return -ENOMEM;
358a4957d87SZiyang Xuan }
359a4957d87SZiyang Xuan
360a4957d87SZiyang Xuan hwdev->pf_to_mgmt = pf_to_mgmt;
361a4957d87SZiyang Xuan pf_to_mgmt->hwdev = hwdev;
362a4957d87SZiyang Xuan
363b8582d05SXiaoyun Wang err = hinic_mutex_init(&pf_to_mgmt->sync_msg_mutex, NULL);
364ae865766SZiyang Xuan if (err)
365ae865766SZiyang Xuan goto mutex_init_err;
366a4957d87SZiyang Xuan
367a4957d87SZiyang Xuan err = alloc_msg_buf(pf_to_mgmt);
368a4957d87SZiyang Xuan if (err) {
369a4957d87SZiyang Xuan PMD_DRV_LOG(ERR, "Allocate msg buffers failed");
370a4957d87SZiyang Xuan goto alloc_msg_buf_err;
371a4957d87SZiyang Xuan }
372a4957d87SZiyang Xuan
373a4957d87SZiyang Xuan err = hinic_api_cmd_init(hwdev, pf_to_mgmt->cmd_chain);
374a4957d87SZiyang Xuan if (err) {
375a4957d87SZiyang Xuan PMD_DRV_LOG(ERR, "Init the api cmd chains failed");
376a4957d87SZiyang Xuan goto api_cmd_init_err;
377a4957d87SZiyang Xuan }
378a4957d87SZiyang Xuan
379a4957d87SZiyang Xuan return 0;
380a4957d87SZiyang Xuan
381a4957d87SZiyang Xuan api_cmd_init_err:
382a4957d87SZiyang Xuan free_msg_buf(pf_to_mgmt);
383a4957d87SZiyang Xuan
384a4957d87SZiyang Xuan alloc_msg_buf_err:
385b8582d05SXiaoyun Wang hinic_mutex_destroy(&pf_to_mgmt->sync_msg_mutex);
386ae865766SZiyang Xuan
387ae865766SZiyang Xuan mutex_init_err:
388a4957d87SZiyang Xuan kfree(pf_to_mgmt);
389a4957d87SZiyang Xuan
390a4957d87SZiyang Xuan return err;
391a4957d87SZiyang Xuan }
392a4957d87SZiyang Xuan
393a4957d87SZiyang Xuan /**
394a4957d87SZiyang Xuan * hinic_pf_to_mgmt_free - free PF to MGMT channel
395a4957d87SZiyang Xuan * @hwdev: the pointer to the private hardware device object
396b8582d05SXiaoyun Wang */
hinic_pf_to_mgmt_free(struct hinic_hwdev * hwdev)397a4957d87SZiyang Xuan static void hinic_pf_to_mgmt_free(struct hinic_hwdev *hwdev)
398a4957d87SZiyang Xuan {
399a4957d87SZiyang Xuan struct hinic_msg_pf_to_mgmt *pf_to_mgmt = hwdev->pf_to_mgmt;
400a4957d87SZiyang Xuan
401a4957d87SZiyang Xuan hinic_api_cmd_free(pf_to_mgmt->cmd_chain);
402a4957d87SZiyang Xuan free_msg_buf(pf_to_mgmt);
403b8582d05SXiaoyun Wang hinic_mutex_destroy(&pf_to_mgmt->sync_msg_mutex);
404a4957d87SZiyang Xuan kfree(pf_to_mgmt);
405a4957d87SZiyang Xuan }
406a4957d87SZiyang Xuan
407a4957d87SZiyang Xuan static int
hinic_pf_to_mgmt_sync(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)408a4957d87SZiyang Xuan hinic_pf_to_mgmt_sync(struct hinic_hwdev *hwdev,
409a4957d87SZiyang Xuan enum hinic_mod_type mod, u8 cmd, void *buf_in, u16 in_size,
410a4957d87SZiyang Xuan void *buf_out, u16 *out_size, u32 timeout)
411a4957d87SZiyang Xuan {
412a4957d87SZiyang Xuan struct hinic_msg_pf_to_mgmt *pf_to_mgmt = hwdev->pf_to_mgmt;
413a4957d87SZiyang Xuan struct hinic_recv_msg *recv_msg;
414a4957d87SZiyang Xuan u32 timeo;
415a4957d87SZiyang Xuan int err, i;
416a4957d87SZiyang Xuan
417b8582d05SXiaoyun Wang err = hinic_mutex_lock(&pf_to_mgmt->sync_msg_mutex);
418b8582d05SXiaoyun Wang if (err)
419b8582d05SXiaoyun Wang return err;
420a4957d87SZiyang Xuan
421a4957d87SZiyang Xuan SYNC_MSG_ID_INC(pf_to_mgmt);
422a4957d87SZiyang Xuan recv_msg = &pf_to_mgmt->recv_resp_msg_from_mgmt;
423a4957d87SZiyang Xuan
424a4957d87SZiyang Xuan err = send_msg_to_mgmt_sync(pf_to_mgmt, mod, cmd, buf_in, in_size,
425a4957d87SZiyang Xuan HINIC_MSG_ACK, HINIC_MSG_DIRECT_SEND,
426a4957d87SZiyang Xuan MSG_NO_RESP);
427a4957d87SZiyang Xuan if (err) {
428a4957d87SZiyang Xuan PMD_DRV_LOG(ERR, "Send msg to mgmt failed");
429a4957d87SZiyang Xuan goto unlock_sync_msg;
430a4957d87SZiyang Xuan }
431a4957d87SZiyang Xuan
432a4957d87SZiyang Xuan timeo = msecs_to_jiffies(timeout ? timeout : MGMT_MSG_TIMEOUT);
433a4957d87SZiyang Xuan for (i = 0; i < pf_to_mgmt->rx_aeq->poll_retry_nr; i++) {
434a4957d87SZiyang Xuan err = hinic_aeq_poll_msg(pf_to_mgmt->rx_aeq, timeo, NULL);
435a4957d87SZiyang Xuan if (err) {
436a4957d87SZiyang Xuan PMD_DRV_LOG(ERR, "Poll mgmt rsp timeout, mod=%d cmd=%d msg_id=%u rc=%d",
437a4957d87SZiyang Xuan mod, cmd, pf_to_mgmt->sync_msg_id, err);
438a4957d87SZiyang Xuan err = -ETIMEDOUT;
439a4957d87SZiyang Xuan hinic_dump_aeq_info(hwdev);
440a4957d87SZiyang Xuan goto unlock_sync_msg;
441a4957d87SZiyang Xuan } else {
442a4957d87SZiyang Xuan if (mod == recv_msg->mod && cmd == recv_msg->cmd &&
443a4957d87SZiyang Xuan recv_msg->msg_id == pf_to_mgmt->sync_msg_id) {
444a4957d87SZiyang Xuan /* the expected response polled */
445a4957d87SZiyang Xuan break;
446a4957d87SZiyang Xuan }
447a4957d87SZiyang Xuan PMD_DRV_LOG(ERR, "AEQ[%d] poll(mod=%d, cmd=%d, msg_id=%u) an "
448a4957d87SZiyang Xuan "unexpected(mod=%d, cmd=%d, msg_id=%u) response",
449a4957d87SZiyang Xuan pf_to_mgmt->rx_aeq->q_id, mod, cmd,
450a4957d87SZiyang Xuan pf_to_mgmt->sync_msg_id, recv_msg->mod,
451a4957d87SZiyang Xuan recv_msg->cmd, recv_msg->msg_id);
452a4957d87SZiyang Xuan }
453a4957d87SZiyang Xuan }
454a4957d87SZiyang Xuan
455a4957d87SZiyang Xuan if (i == pf_to_mgmt->rx_aeq->poll_retry_nr) {
456a4957d87SZiyang Xuan PMD_DRV_LOG(ERR, "Get %d unexpected mgmt rsp from AEQ[%d], poll mgmt rsp failed",
457a4957d87SZiyang Xuan i, pf_to_mgmt->rx_aeq->q_id);
458a4957d87SZiyang Xuan err = -EBADMSG;
459a4957d87SZiyang Xuan goto unlock_sync_msg;
460a4957d87SZiyang Xuan }
461a4957d87SZiyang Xuan
462a4957d87SZiyang Xuan rte_smp_rmb();
463a4957d87SZiyang Xuan if (recv_msg->msg_len && buf_out && out_size) {
464a4957d87SZiyang Xuan if (recv_msg->msg_len <= *out_size) {
465a4957d87SZiyang Xuan memcpy(buf_out, recv_msg->msg,
466a4957d87SZiyang Xuan recv_msg->msg_len);
467a4957d87SZiyang Xuan *out_size = recv_msg->msg_len;
468a4957d87SZiyang Xuan } else {
469a4957d87SZiyang Xuan PMD_DRV_LOG(ERR, "Mgmt rsp's msg len: %u overflow.",
470a4957d87SZiyang Xuan recv_msg->msg_len);
471a4957d87SZiyang Xuan err = -ERANGE;
472a4957d87SZiyang Xuan }
473a4957d87SZiyang Xuan }
474a4957d87SZiyang Xuan
475a4957d87SZiyang Xuan unlock_sync_msg:
476a4957d87SZiyang Xuan if (err && out_size)
477a4957d87SZiyang Xuan *out_size = 0;
478b8582d05SXiaoyun Wang (void)hinic_mutex_unlock(&pf_to_mgmt->sync_msg_mutex);
479a4957d87SZiyang Xuan return err;
480a4957d87SZiyang Xuan }
481a4957d87SZiyang Xuan
hinic_msg_to_mgmt_sync(void * hwdev,enum hinic_mod_type mod,u8 cmd,void * buf_in,u16 in_size,void * buf_out,u16 * out_size,u32 timeout)482a4957d87SZiyang Xuan int hinic_msg_to_mgmt_sync(void *hwdev, enum hinic_mod_type mod, u8 cmd,
483a4957d87SZiyang Xuan void *buf_in, u16 in_size,
484a4957d87SZiyang Xuan void *buf_out, u16 *out_size, u32 timeout)
485a4957d87SZiyang Xuan {
486a4957d87SZiyang Xuan int rc = HINIC_ERROR;
487a4957d87SZiyang Xuan
488a4957d87SZiyang Xuan if (!hwdev || in_size > HINIC_MSG_TO_MGMT_MAX_LEN)
489a4957d87SZiyang Xuan return -EINVAL;
490a4957d87SZiyang Xuan
491b8582d05SXiaoyun Wang if (hinic_func_type(hwdev) == TYPE_VF) {
492b8582d05SXiaoyun Wang rc = hinic_mbox_to_pf(hwdev, mod, cmd, buf_in, in_size,
493b8582d05SXiaoyun Wang buf_out, out_size, timeout);
494b8582d05SXiaoyun Wang } else {
495b8582d05SXiaoyun Wang rc = hinic_pf_to_mgmt_sync(hwdev, mod, cmd, buf_in, in_size,
496b8582d05SXiaoyun Wang buf_out, out_size, timeout);
497b8582d05SXiaoyun Wang }
498a4957d87SZiyang Xuan
499a4957d87SZiyang Xuan return rc;
500a4957d87SZiyang Xuan }
501a4957d87SZiyang Xuan
hinic_msg_to_mgmt_no_ack(void * hwdev,enum hinic_mod_type mod,u8 cmd,void * buf_in,u16 in_size)502a4957d87SZiyang Xuan int hinic_msg_to_mgmt_no_ack(void *hwdev, enum hinic_mod_type mod, u8 cmd,
503214164a6SXiaoyun Wang void *buf_in, u16 in_size)
504a4957d87SZiyang Xuan {
505a4957d87SZiyang Xuan struct hinic_msg_pf_to_mgmt *pf_to_mgmt =
506a4957d87SZiyang Xuan ((struct hinic_hwdev *)hwdev)->pf_to_mgmt;
507a4957d87SZiyang Xuan int err = -EINVAL;
508a4957d87SZiyang Xuan
509a4957d87SZiyang Xuan if (!MSG_SZ_IS_VALID(in_size)) {
510a4957d87SZiyang Xuan PMD_DRV_LOG(ERR, "Mgmt msg buffer size is invalid");
511a4957d87SZiyang Xuan return err;
512a4957d87SZiyang Xuan }
513a4957d87SZiyang Xuan
514b8582d05SXiaoyun Wang err = hinic_mutex_lock(&pf_to_mgmt->sync_msg_mutex);
515b8582d05SXiaoyun Wang if (err)
516b8582d05SXiaoyun Wang return err;
517a4957d87SZiyang Xuan
518a4957d87SZiyang Xuan err = send_msg_to_mgmt_sync(pf_to_mgmt, mod, cmd, buf_in, in_size,
519a4957d87SZiyang Xuan HINIC_MSG_NO_ACK, HINIC_MSG_DIRECT_SEND,
520a4957d87SZiyang Xuan MSG_NO_RESP);
521a4957d87SZiyang Xuan
522b8582d05SXiaoyun Wang (void)hinic_mutex_unlock(&pf_to_mgmt->sync_msg_mutex);
523a4957d87SZiyang Xuan
524a4957d87SZiyang Xuan return err;
525a4957d87SZiyang Xuan }
526a4957d87SZiyang Xuan
check_mgmt_seq_id_and_seg_len(struct hinic_recv_msg * recv_msg,u8 seq_id,u8 seg_len,u16 msg_id)527a4957d87SZiyang Xuan static bool check_mgmt_seq_id_and_seg_len(struct hinic_recv_msg *recv_msg,
528*cb99500dSGuoyang Zhou u8 seq_id, u8 seg_len, u16 msg_id)
529a4957d87SZiyang Xuan {
530a4957d87SZiyang Xuan if (seq_id > HINIC_SEQ_ID_MAX_VAL || seg_len > HINIC_MSG_SEG_LEN)
531a4957d87SZiyang Xuan return false;
532a4957d87SZiyang Xuan
533a4957d87SZiyang Xuan if (seq_id == 0) {
534*cb99500dSGuoyang Zhou recv_msg->seq_id = seq_id;
535*cb99500dSGuoyang Zhou recv_msg->msg_id = msg_id;
536a4957d87SZiyang Xuan } else {
537*cb99500dSGuoyang Zhou if ((seq_id != recv_msg->seq_id + 1) ||
538*cb99500dSGuoyang Zhou msg_id != recv_msg->msg_id) {
539*cb99500dSGuoyang Zhou recv_msg->seq_id = 0;
540a4957d87SZiyang Xuan return false;
541a4957d87SZiyang Xuan }
542*cb99500dSGuoyang Zhou recv_msg->seq_id = seq_id;
543a4957d87SZiyang Xuan }
544a4957d87SZiyang Xuan
545a4957d87SZiyang Xuan return true;
546a4957d87SZiyang Xuan }
547a4957d87SZiyang Xuan
548a4957d87SZiyang Xuan /**
549a4957d87SZiyang Xuan * hinic_mgmt_recv_msg_handler - handler for message from mgmt cpu
550a4957d87SZiyang Xuan * @pf_to_mgmt: PF to MGMT channel
551a4957d87SZiyang Xuan * @recv_msg: received message details
552a4957d87SZiyang Xuan * @param: customized parameter
553b8582d05SXiaoyun Wang */
hinic_mgmt_recv_msg_handler(struct hinic_msg_pf_to_mgmt * pf_to_mgmt,struct hinic_recv_msg * recv_msg,void * param)554a4957d87SZiyang Xuan static void hinic_mgmt_recv_msg_handler(struct hinic_msg_pf_to_mgmt *pf_to_mgmt,
555a4957d87SZiyang Xuan struct hinic_recv_msg *recv_msg,
556a4957d87SZiyang Xuan void *param)
557a4957d87SZiyang Xuan {
558a4957d87SZiyang Xuan void *buf_out = recv_msg->buf_out;
559a4957d87SZiyang Xuan u16 out_size = 0;
560a4957d87SZiyang Xuan
561a4957d87SZiyang Xuan switch (recv_msg->mod) {
562a4957d87SZiyang Xuan case HINIC_MOD_COMM:
563a4957d87SZiyang Xuan hinic_comm_async_event_handle(pf_to_mgmt->hwdev,
564a4957d87SZiyang Xuan recv_msg->cmd, recv_msg->msg,
565a4957d87SZiyang Xuan recv_msg->msg_len,
566a4957d87SZiyang Xuan buf_out, &out_size);
567a4957d87SZiyang Xuan break;
568a4957d87SZiyang Xuan case HINIC_MOD_L2NIC:
569a4957d87SZiyang Xuan hinic_l2nic_async_event_handle(pf_to_mgmt->hwdev, param,
570a4957d87SZiyang Xuan recv_msg->cmd, recv_msg->msg,
571a4957d87SZiyang Xuan recv_msg->msg_len,
572a4957d87SZiyang Xuan buf_out, &out_size);
573a4957d87SZiyang Xuan break;
574a4957d87SZiyang Xuan case HINIC_MOD_HILINK:
575a4957d87SZiyang Xuan hinic_hilink_async_event_handle(pf_to_mgmt->hwdev,
576a4957d87SZiyang Xuan recv_msg->cmd, recv_msg->msg,
577a4957d87SZiyang Xuan recv_msg->msg_len,
578a4957d87SZiyang Xuan buf_out, &out_size);
579a4957d87SZiyang Xuan break;
580a4957d87SZiyang Xuan default:
5814f1af3cbSXiaoyun Wang PMD_DRV_LOG(ERR, "No handler, mod: %d", recv_msg->mod);
582a4957d87SZiyang Xuan break;
583a4957d87SZiyang Xuan }
584a4957d87SZiyang Xuan
585a4957d87SZiyang Xuan if (!recv_msg->async_mgmt_to_pf) {
586a4957d87SZiyang Xuan if (!out_size)
587a4957d87SZiyang Xuan out_size = BUF_OUT_DEFAULT_SIZE;
588a4957d87SZiyang Xuan
589a4957d87SZiyang Xuan /* MGMT sent sync msg, send the response */
590a4957d87SZiyang Xuan (void)send_msg_to_mgmt_async(pf_to_mgmt, recv_msg->mod,
591a4957d87SZiyang Xuan recv_msg->cmd, buf_out, out_size,
592a4957d87SZiyang Xuan HINIC_MSG_RESPONSE,
593a4957d87SZiyang Xuan recv_msg->msg_id);
594a4957d87SZiyang Xuan }
595a4957d87SZiyang Xuan }
596a4957d87SZiyang Xuan
597a4957d87SZiyang Xuan /**
598a4957d87SZiyang Xuan * recv_mgmt_msg_handler - handler a message from mgmt cpu
599a4957d87SZiyang Xuan * @pf_to_mgmt: PF to MGMT channel
600a4957d87SZiyang Xuan * @header: the header of the message
601a4957d87SZiyang Xuan * @recv_msg: received message details
602a4957d87SZiyang Xuan * @param: customized parameter
603a4957d87SZiyang Xuan * Return: 0 when aeq is response message, -1 default result,
604a4957d87SZiyang Xuan * and when wrong message or not last message
605b8582d05SXiaoyun Wang */
recv_mgmt_msg_handler(struct hinic_msg_pf_to_mgmt * pf_to_mgmt,u8 * header,struct hinic_recv_msg * recv_msg,void * param)606a4957d87SZiyang Xuan static int recv_mgmt_msg_handler(struct hinic_msg_pf_to_mgmt *pf_to_mgmt,
607a4957d87SZiyang Xuan u8 *header, struct hinic_recv_msg *recv_msg,
608a4957d87SZiyang Xuan void *param)
609a4957d87SZiyang Xuan {
610a4957d87SZiyang Xuan u64 msg_header = *((u64 *)header);
611a4957d87SZiyang Xuan void *msg_body = header + sizeof(msg_header);
612a4957d87SZiyang Xuan u8 *dest_msg;
613a4957d87SZiyang Xuan u8 seq_id, seq_len;
6141e4593dbSGuoyang Zhou u8 front_id;
615*cb99500dSGuoyang Zhou u16 msg_id;
616a4957d87SZiyang Xuan
617a4957d87SZiyang Xuan seq_id = HINIC_MSG_HEADER_GET(msg_header, SEQID);
618a4957d87SZiyang Xuan seq_len = HINIC_MSG_HEADER_GET(msg_header, SEG_LEN);
619*cb99500dSGuoyang Zhou front_id = recv_msg->seq_id;
620*cb99500dSGuoyang Zhou msg_id = HINIC_MSG_HEADER_GET(msg_header, MSG_ID);
621a4957d87SZiyang Xuan
622*cb99500dSGuoyang Zhou if (!check_mgmt_seq_id_and_seg_len(recv_msg, seq_id, seq_len, msg_id)) {
623a4957d87SZiyang Xuan PMD_DRV_LOG(ERR,
6244f1af3cbSXiaoyun Wang "Mgmt msg sequence and segment check failed, "
625*cb99500dSGuoyang Zhou "func id: 0x%x, front id: 0x%x, current id: 0x%x, seg len: 0x%x "
626*cb99500dSGuoyang Zhou "front msg_id: %d, cur msg_id: %d",
627a4957d87SZiyang Xuan hinic_global_func_id(pf_to_mgmt->hwdev),
628*cb99500dSGuoyang Zhou front_id, seq_id, seq_len, recv_msg->msg_id, msg_id);
629b8582d05SXiaoyun Wang return HINIC_ERROR;
630a4957d87SZiyang Xuan }
631a4957d87SZiyang Xuan
632a4957d87SZiyang Xuan dest_msg = (u8 *)recv_msg->msg + seq_id * HINIC_MSG_SEG_LEN;
633a4957d87SZiyang Xuan memcpy(dest_msg, msg_body, seq_len);
634a4957d87SZiyang Xuan
635a4957d87SZiyang Xuan if (!HINIC_MSG_HEADER_GET(msg_header, LAST))
636b8582d05SXiaoyun Wang return HINIC_ERROR;
637a4957d87SZiyang Xuan
638a4957d87SZiyang Xuan recv_msg->cmd = HINIC_MSG_HEADER_GET(msg_header, CMD);
639a4957d87SZiyang Xuan recv_msg->mod = HINIC_MSG_HEADER_GET(msg_header, MODULE);
640a4957d87SZiyang Xuan recv_msg->async_mgmt_to_pf = HINIC_MSG_HEADER_GET(msg_header,
641a4957d87SZiyang Xuan ASYNC_MGMT_TO_PF);
642a4957d87SZiyang Xuan recv_msg->msg_len = HINIC_MSG_HEADER_GET(msg_header, MSG_LEN);
643a4957d87SZiyang Xuan recv_msg->msg_id = HINIC_MSG_HEADER_GET(msg_header, MSG_ID);
644a4957d87SZiyang Xuan
645a4957d87SZiyang Xuan if (HINIC_MSG_HEADER_GET(msg_header, DIRECTION) == HINIC_MSG_RESPONSE)
646b8582d05SXiaoyun Wang return HINIC_OK;
647a4957d87SZiyang Xuan
648a4957d87SZiyang Xuan hinic_mgmt_recv_msg_handler(pf_to_mgmt, recv_msg, param);
649a4957d87SZiyang Xuan
650b8582d05SXiaoyun Wang return HINIC_ERROR;
651a4957d87SZiyang Xuan }
652a4957d87SZiyang Xuan
653a4957d87SZiyang Xuan /**
654a4957d87SZiyang Xuan * hinic_mgmt_msg_aeqe_handler - handler for a mgmt message event
655a4957d87SZiyang Xuan * @hwdev: the pointer to the private hardware device object
656a4957d87SZiyang Xuan * @header: the header of the message
657a4957d87SZiyang Xuan * @size: unused
658a4957d87SZiyang Xuan * @param: customized parameter
659a4957d87SZiyang Xuan * Return: 0 when aeq is response message,
660a4957d87SZiyang Xuan * -1 default result, and when wrong message or not last message
661b8582d05SXiaoyun Wang */
hinic_mgmt_msg_aeqe_handler(void * hwdev,u8 * header,__rte_unused u8 size,void * param)662a4957d87SZiyang Xuan static int hinic_mgmt_msg_aeqe_handler(void *hwdev, u8 *header,
663a4957d87SZiyang Xuan __rte_unused u8 size, void *param)
664a4957d87SZiyang Xuan {
665a4957d87SZiyang Xuan struct hinic_msg_pf_to_mgmt *pf_to_mgmt =
666a4957d87SZiyang Xuan ((struct hinic_hwdev *)hwdev)->pf_to_mgmt;
667a4957d87SZiyang Xuan struct hinic_recv_msg *recv_msg;
668a4957d87SZiyang Xuan
669a4957d87SZiyang Xuan recv_msg = (HINIC_MSG_HEADER_GET(*(u64 *)header, DIRECTION) ==
670a4957d87SZiyang Xuan HINIC_MSG_DIRECT_SEND) ?
671a4957d87SZiyang Xuan &pf_to_mgmt->recv_msg_from_mgmt :
672a4957d87SZiyang Xuan &pf_to_mgmt->recv_resp_msg_from_mgmt;
673a4957d87SZiyang Xuan
674a4957d87SZiyang Xuan return recv_mgmt_msg_handler(pf_to_mgmt, header, recv_msg, param);
675a4957d87SZiyang Xuan }
676a4957d87SZiyang Xuan
hinic_handle_aeqe(void * handle,enum hinic_aeq_type event,u8 * data,u8 size,void * param)677a4957d87SZiyang Xuan static int hinic_handle_aeqe(void *handle, enum hinic_aeq_type event,
678a4957d87SZiyang Xuan u8 *data, u8 size, void *param)
679a4957d87SZiyang Xuan {
680a4957d87SZiyang Xuan int rc = 0;
681a4957d87SZiyang Xuan
682a4957d87SZiyang Xuan switch (event) {
683a4957d87SZiyang Xuan case HINIC_MSG_FROM_MGMT_CPU:
684a4957d87SZiyang Xuan rc = hinic_mgmt_msg_aeqe_handler(handle, data, size, param);
685a4957d87SZiyang Xuan break;
686b8582d05SXiaoyun Wang case HINIC_MBX_FROM_FUNC:
687b8582d05SXiaoyun Wang rc = hinic_mbox_func_aeqe_handler(handle, data, size, param);
688b8582d05SXiaoyun Wang break;
689a4957d87SZiyang Xuan default:
690a4957d87SZiyang Xuan PMD_DRV_LOG(ERR, "Unknown event type: 0x%x, size: %d",
691a4957d87SZiyang Xuan event, size);
692b8582d05SXiaoyun Wang rc = HINIC_ERROR;
693a4957d87SZiyang Xuan break;
694a4957d87SZiyang Xuan }
695a4957d87SZiyang Xuan
696a4957d87SZiyang Xuan return rc;
697a4957d87SZiyang Xuan }
698a4957d87SZiyang Xuan
699a4957d87SZiyang Xuan /**
700a4957d87SZiyang Xuan * hinic_aeq_poll_msg - poll one or continue aeqe, and call dedicated process
701a4957d87SZiyang Xuan * @eq: aeq of the chip
702a4957d87SZiyang Xuan * @timeout: 0 - poll all aeqe in eq, used in interrupt mode,
703a4957d87SZiyang Xuan * > 0 - poll aeq until get aeqe with 'last' field set to 1,
704a4957d87SZiyang Xuan * used in polling mode.
705a4957d87SZiyang Xuan * @param: customized parameter
706a4957d87SZiyang Xuan * Return: 0 - Success, EIO - poll timeout, ENODEV - swe not support
707b8582d05SXiaoyun Wang */
hinic_aeq_poll_msg(struct hinic_eq * eq,u32 timeout,void * param)708a4957d87SZiyang Xuan int hinic_aeq_poll_msg(struct hinic_eq *eq, u32 timeout, void *param)
709a4957d87SZiyang Xuan {
710a4957d87SZiyang Xuan struct hinic_aeq_elem *aeqe_pos;
711a4957d87SZiyang Xuan enum hinic_aeq_type event;
712a4957d87SZiyang Xuan u32 aeqe_desc = 0;
713a4957d87SZiyang Xuan u16 i;
714a4957d87SZiyang Xuan u8 size;
715a4957d87SZiyang Xuan int done = HINIC_ERROR;
716a4957d87SZiyang Xuan int err = -EFAULT;
717a4957d87SZiyang Xuan unsigned long end;
718a4957d87SZiyang Xuan
719a4957d87SZiyang Xuan for (i = 0; ((timeout == 0) && (i < eq->eq_len)) ||
720a4957d87SZiyang Xuan ((timeout > 0) && (done != HINIC_OK) && (i < eq->eq_len)); i++) {
721a4957d87SZiyang Xuan err = -EIO;
722a4957d87SZiyang Xuan end = jiffies + msecs_to_jiffies(timeout);
723a4957d87SZiyang Xuan do {
724a4957d87SZiyang Xuan aeqe_pos = GET_CURR_AEQ_ELEM(eq);
725a4957d87SZiyang Xuan rte_rmb();
726a4957d87SZiyang Xuan
727a4957d87SZiyang Xuan /* Data in HW is in Big endian Format */
728a4957d87SZiyang Xuan aeqe_desc = be32_to_cpu(aeqe_pos->desc);
729a4957d87SZiyang Xuan
730a4957d87SZiyang Xuan /* HW updates wrapped bit,
731a4957d87SZiyang Xuan * when it adds eq element event
732a4957d87SZiyang Xuan */
733a4957d87SZiyang Xuan if (EQ_ELEM_DESC_GET(aeqe_desc, WRAPPED)
734a4957d87SZiyang Xuan != eq->wrapped) {
735a4957d87SZiyang Xuan err = 0;
736a4957d87SZiyang Xuan break;
737a4957d87SZiyang Xuan }
738a4957d87SZiyang Xuan
739a4957d87SZiyang Xuan if (timeout != 0)
740ae865766SZiyang Xuan usleep(1000);
741a4957d87SZiyang Xuan } while (time_before(jiffies, end));
742a4957d87SZiyang Xuan
743a4957d87SZiyang Xuan if (err != HINIC_OK) /*poll time out*/
744a4957d87SZiyang Xuan break;
745a4957d87SZiyang Xuan
746a4957d87SZiyang Xuan event = EQ_ELEM_DESC_GET(aeqe_desc, TYPE);
747a4957d87SZiyang Xuan if (EQ_ELEM_DESC_GET(aeqe_desc, SRC)) {
7484f1af3cbSXiaoyun Wang PMD_DRV_LOG(ERR, "AEQ sw event not support %d", event);
749a4957d87SZiyang Xuan return -ENODEV;
750a4957d87SZiyang Xuan
751a4957d87SZiyang Xuan } else {
752a4957d87SZiyang Xuan size = EQ_ELEM_DESC_GET(aeqe_desc, SIZE);
753a4957d87SZiyang Xuan done = hinic_handle_aeqe(eq->hwdev, event,
754a4957d87SZiyang Xuan aeqe_pos->aeqe_data,
755a4957d87SZiyang Xuan size, param);
756a4957d87SZiyang Xuan }
757a4957d87SZiyang Xuan
758a4957d87SZiyang Xuan eq->cons_idx++;
759a4957d87SZiyang Xuan if (eq->cons_idx == eq->eq_len) {
760a4957d87SZiyang Xuan eq->cons_idx = 0;
761a4957d87SZiyang Xuan eq->wrapped = !eq->wrapped;
762a4957d87SZiyang Xuan }
763a4957d87SZiyang Xuan }
764a4957d87SZiyang Xuan
765a4957d87SZiyang Xuan eq_update_ci(eq);
766a4957d87SZiyang Xuan
767a4957d87SZiyang Xuan return err;
768a4957d87SZiyang Xuan }
769a4957d87SZiyang Xuan
hinic_comm_pf_to_mgmt_init(struct hinic_hwdev * hwdev)770a4957d87SZiyang Xuan int hinic_comm_pf_to_mgmt_init(struct hinic_hwdev *hwdev)
771a4957d87SZiyang Xuan {
772a4957d87SZiyang Xuan int rc;
773a4957d87SZiyang Xuan
774b8582d05SXiaoyun Wang /* VF do not support send msg to mgmt directly */
775b8582d05SXiaoyun Wang if (hinic_func_type(hwdev) == TYPE_VF)
776b8582d05SXiaoyun Wang return 0;
777b8582d05SXiaoyun Wang
778a4957d87SZiyang Xuan rc = hinic_pf_to_mgmt_init(hwdev);
779a4957d87SZiyang Xuan if (rc)
780a4957d87SZiyang Xuan return rc;
781a4957d87SZiyang Xuan
782a4957d87SZiyang Xuan hwdev->pf_to_mgmt->rx_aeq = &hwdev->aeqs->aeq[HINIC_MGMT_RSP_AEQN];
783a4957d87SZiyang Xuan
784a4957d87SZiyang Xuan return 0;
785a4957d87SZiyang Xuan }
786a4957d87SZiyang Xuan
hinic_comm_pf_to_mgmt_free(struct hinic_hwdev * hwdev)787a4957d87SZiyang Xuan void hinic_comm_pf_to_mgmt_free(struct hinic_hwdev *hwdev)
788a4957d87SZiyang Xuan {
789b8582d05SXiaoyun Wang /* VF do not support send msg to mgmt directly */
790b8582d05SXiaoyun Wang if (hinic_func_type(hwdev) == TYPE_VF)
791b8582d05SXiaoyun Wang return;
792b8582d05SXiaoyun Wang
793a4957d87SZiyang Xuan hinic_pf_to_mgmt_free(hwdev);
794a4957d87SZiyang Xuan }
795a4957d87SZiyang Xuan
hinic_dev_handle_aeq_event(struct hinic_hwdev * hwdev,void * param)796a4957d87SZiyang Xuan void hinic_dev_handle_aeq_event(struct hinic_hwdev *hwdev, void *param)
797a4957d87SZiyang Xuan {
798a4957d87SZiyang Xuan struct hinic_eq *aeq = &hwdev->aeqs->aeq[0];
799a4957d87SZiyang Xuan
800a4957d87SZiyang Xuan /* clear resend timer cnt register */
801a4957d87SZiyang Xuan hinic_misx_intr_clear_resend_bit(hwdev, aeq->eq_irq.msix_entry_idx,
802a4957d87SZiyang Xuan EQ_MSIX_RESEND_TIMER_CLEAR);
803a4957d87SZiyang Xuan (void)hinic_aeq_poll_msg(aeq, 0, param);
804a4957d87SZiyang Xuan }
805