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