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