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