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