net/hinic/base: check output of management sync channel
[dpdk.git] / drivers / net / hinic / base / hinic_pmd_hwdev.c
1 /* SPDX-License-Identifier: BSD-3-Clause
2  * Copyright(c) 2017 Huawei Technologies Co., Ltd
3  */
4
5 #include<rte_ethdev_driver.h>
6 #include <rte_bus_pci.h>
7 #include <rte_hash.h>
8 #include <rte_jhash.h>
9
10 #include "hinic_compat.h"
11 #include "hinic_csr.h"
12 #include "hinic_pmd_hwdev.h"
13 #include "hinic_pmd_hwif.h"
14 #include "hinic_pmd_wq.h"
15 #include "hinic_pmd_cmdq.h"
16 #include "hinic_pmd_mgmt.h"
17 #include "hinic_pmd_niccfg.h"
18 #include "hinic_pmd_mbox.h"
19
20 #define HINIC_DEAULT_EQ_MSIX_PENDING_LIMIT              0
21 #define HINIC_DEAULT_EQ_MSIX_COALESC_TIMER_CFG          0xFF
22 #define HINIC_DEAULT_EQ_MSIX_RESEND_TIMER_CFG           7
23
24 #define HINIC_FLR_TIMEOUT                               1000
25
26 #define FFM_RECORD_NUM_MAX                              32
27
28 #define HINIC_DMA_ATTR_ENTRY_ST_SHIFT                   0
29 #define HINIC_DMA_ATTR_ENTRY_AT_SHIFT                   8
30 #define HINIC_DMA_ATTR_ENTRY_PH_SHIFT                   10
31 #define HINIC_DMA_ATTR_ENTRY_NO_SNOOPING_SHIFT          12
32 #define HINIC_DMA_ATTR_ENTRY_TPH_EN_SHIFT               13
33
34 #define HINIC_DMA_ATTR_ENTRY_ST_MASK                    0xFF
35 #define HINIC_DMA_ATTR_ENTRY_AT_MASK                    0x3
36 #define HINIC_DMA_ATTR_ENTRY_PH_MASK                    0x3
37 #define HINIC_DMA_ATTR_ENTRY_NO_SNOOPING_MASK           0x1
38 #define HINIC_DMA_ATTR_ENTRY_TPH_EN_MASK                0x1
39
40 #define HINIC_DMA_ATTR_ENTRY_SET(val, member)                   \
41                 (((u32)(val) & HINIC_DMA_ATTR_ENTRY_##member##_MASK) << \
42                         HINIC_DMA_ATTR_ENTRY_##member##_SHIFT)
43
44 #define HINIC_DMA_ATTR_ENTRY_CLEAR(val, member)         \
45                 ((val) & (~(HINIC_DMA_ATTR_ENTRY_##member##_MASK        \
46                         << HINIC_DMA_ATTR_ENTRY_##member##_SHIFT)))
47
48 #define HINIC_PCIE_ST_DISABLE                           0
49 #define HINIC_PCIE_AT_DISABLE                           0
50 #define HINIC_PCIE_PH_DISABLE                           0
51 #define PCIE_MSIX_ATTR_ENTRY                            0
52
53 #define HINIC_HASH_FUNC                                 rte_jhash
54 #define HINIC_HASH_KEY_LEN                              (sizeof(dma_addr_t))
55 #define HINIC_HASH_FUNC_INIT_VAL                        0
56
57 static const char *__hw_to_char_fec[HILINK_FEC_MAX_TYPE] = {
58         "RS-FEC", "BASE-FEC", "NO-FEC"};
59
60 static const char *__hw_to_char_port_type[LINK_PORT_MAX_TYPE] = {
61         "Unknown", "Fibre", "Electric", "Direct Attach Copper", "AOC",
62         "Back plane", "BaseT"
63 };
64
65 static const char *hinic_module_link_err[LINK_ERR_NUM] = {
66         "Unrecognized module",
67 };
68
69 struct hinic_vf_dma_attr_table {
70         struct hinic_mgmt_msg_head mgmt_msg_head;
71
72         u16     func_idx;
73         u8      func_dma_entry_num;
74         u8      entry_idx;
75         u8      st;
76         u8      at;
77         u8      ph;
78         u8      no_snooping;
79         u8      tph_en;
80         u8      resv1[3];
81 };
82
83 /**
84  * hinic_cpu_to_be32 - convert data to big endian 32 bit format
85  * @data: the data to convert
86  * @len: length of data to convert, must be Multiple of 4B
87  */
88 void hinic_cpu_to_be32(void *data, u32 len)
89 {
90         u32 i;
91         u32 *mem = (u32 *)data;
92
93         for (i = 0; i < (len >> 2); i++) {
94                 *mem = cpu_to_be32(*mem);
95                 mem++;
96         }
97 }
98
99 /**
100  * hinic_be32_to_cpu - convert data from big endian 32 bit format
101  * @data: the data to convert
102  * @len: length of data to convert, must be Multiple of 4B
103  */
104 void hinic_be32_to_cpu(void *data, u32 len)
105 {
106         u32 i;
107         u32 *mem = (u32 *)data;
108
109         for (i = 0; i < (len >> 2); i++) {
110                 *mem = be32_to_cpu(*mem);
111                 mem++;
112         }
113 }
114
115 static void *hinic_dma_mem_zalloc(struct hinic_hwdev *hwdev, size_t size,
116                            dma_addr_t *dma_handle, unsigned int align,
117                            unsigned int socket_id)
118 {
119         int rc, alloc_cnt;
120         const struct rte_memzone *mz;
121         char z_name[RTE_MEMZONE_NAMESIZE];
122         hash_sig_t sig;
123         rte_iova_t iova;
124
125         if (dma_handle == NULL || 0 == size)
126                 return NULL;
127
128         alloc_cnt = rte_atomic32_add_return(&hwdev->os_dep.dma_alloc_cnt, 1);
129         snprintf(z_name, sizeof(z_name), "%s_%d",
130                  hwdev->pcidev_hdl->name, alloc_cnt);
131
132         mz = rte_memzone_reserve_aligned(z_name, size, socket_id,
133                                          RTE_MEMZONE_IOVA_CONTIG, align);
134         if (!mz) {
135                 PMD_DRV_LOG(ERR, "Alloc dma able memory failed, errno: %d, ma_name: %s, size: 0x%zx",
136                             rte_errno, z_name, size);
137                 return NULL;
138         }
139
140         iova = mz->iova;
141
142         /* check if phys_addr already exist */
143         sig = HINIC_HASH_FUNC(&iova, HINIC_HASH_KEY_LEN,
144                               HINIC_HASH_FUNC_INIT_VAL);
145         rc = rte_hash_lookup_with_hash(hwdev->os_dep.dma_addr_hash,
146                                        &iova, sig);
147         if (rc >= 0) {
148                 PMD_DRV_LOG(ERR, "Dma addr: %p already in hash table, error: %d, mz_name: %s",
149                         (void *)iova, rc, z_name);
150                 goto phys_addr_hash_err;
151         }
152
153         /* record paddr in hash table */
154         rte_spinlock_lock(&hwdev->os_dep.dma_hash_lock);
155         rc = rte_hash_add_key_with_hash_data(hwdev->os_dep.dma_addr_hash,
156                                              &iova, sig,
157                                              (void *)(u64)mz);
158         rte_spinlock_unlock(&hwdev->os_dep.dma_hash_lock);
159         if (rc) {
160                 PMD_DRV_LOG(ERR, "Insert dma addr: %p hash failed, error: %d, mz_name: %s",
161                         (void *)iova, rc, z_name);
162                 goto phys_addr_hash_err;
163         }
164         *dma_handle = iova;
165         memset(mz->addr, 0, size);
166
167         return mz->addr;
168
169 phys_addr_hash_err:
170         (void)rte_memzone_free(mz);
171
172         return NULL;
173 }
174
175 static void
176 hinic_dma_mem_free(struct hinic_hwdev *hwdev, size_t size,
177                    void *virt, dma_addr_t phys)
178 {
179         int rc;
180         struct rte_memzone *mz = NULL;
181         struct rte_hash *hash;
182         hash_sig_t sig;
183
184         if (virt == NULL || phys == 0)
185                 return;
186
187         hash = hwdev->os_dep.dma_addr_hash;
188         sig = HINIC_HASH_FUNC(&phys, HINIC_HASH_KEY_LEN,
189                               HINIC_HASH_FUNC_INIT_VAL);
190         rc = rte_hash_lookup_with_hash_data(hash, &phys, sig, (void **)&mz);
191         if (rc < 0) {
192                 PMD_DRV_LOG(ERR, "Can not find phys_addr: %p, error: %d",
193                         (void *)phys, rc);
194                 return;
195         }
196
197         if (virt != mz->addr || size > mz->len) {
198                 PMD_DRV_LOG(ERR, "Match mz_info failed: "
199                         "mz.name: %s, mz.phys: %p, mz.virt: %p, mz.len: %zu, "
200                         "phys: %p, virt: %p, size: %zu",
201                         mz->name, (void *)mz->iova, mz->addr, mz->len,
202                         (void *)phys, virt, size);
203         }
204
205         rte_spinlock_lock(&hwdev->os_dep.dma_hash_lock);
206         (void)rte_hash_del_key_with_hash(hash, &phys, sig);
207         rte_spinlock_unlock(&hwdev->os_dep.dma_hash_lock);
208
209         (void)rte_memzone_free(mz);
210 }
211
212 void *dma_zalloc_coherent(void *hwdev, size_t size, dma_addr_t *dma_handle,
213                           unsigned int socket_id)
214 {
215         return hinic_dma_mem_zalloc(hwdev, size, dma_handle,
216                                     RTE_CACHE_LINE_SIZE, socket_id);
217 }
218
219 void *dma_zalloc_coherent_aligned(void *hwdev, size_t size,
220                                 dma_addr_t *dma_handle, unsigned int socket_id)
221 {
222         return hinic_dma_mem_zalloc(hwdev, size, dma_handle, HINIC_PAGE_SIZE,
223                                     socket_id);
224 }
225
226 void *dma_zalloc_coherent_aligned256k(void *hwdev, size_t size,
227                                       dma_addr_t *dma_handle,
228                                       unsigned int socket_id)
229 {
230         return hinic_dma_mem_zalloc(hwdev, size, dma_handle,
231                                     HINIC_PAGE_SIZE * 64, socket_id);
232 }
233
234 void dma_free_coherent(void *hwdev, size_t size, void *virt, dma_addr_t phys)
235 {
236         hinic_dma_mem_free(hwdev, size, virt, phys);
237 }
238
239 void dma_free_coherent_volatile(void *hwdev, size_t size,
240                                 volatile void *virt, dma_addr_t phys)
241 {
242         int rc;
243         struct rte_memzone *mz = NULL;
244         struct hinic_hwdev *dev = hwdev;
245         struct rte_hash *hash;
246         hash_sig_t sig;
247
248         if (virt == NULL || phys == 0)
249                 return;
250
251         hash = dev->os_dep.dma_addr_hash;
252         sig = HINIC_HASH_FUNC(&phys, HINIC_HASH_KEY_LEN,
253                               HINIC_HASH_FUNC_INIT_VAL);
254         rc = rte_hash_lookup_with_hash_data(hash, &phys, sig, (void **)&mz);
255         if (rc < 0) {
256                 PMD_DRV_LOG(ERR, "Can not find phys_addr: %p, error: %d",
257                         (void *)phys, rc);
258                 return;
259         }
260
261         if (virt != mz->addr || size > mz->len) {
262                 PMD_DRV_LOG(ERR, "Match mz_info failed: "
263                         "mz.name:%s, mz.phys:%p, mz.virt:%p, mz.len:%zu, "
264                         "phys:%p, virt:%p, size:%zu",
265                         mz->name, (void *)mz->iova, mz->addr, mz->len,
266                         (void *)phys, virt, size);
267         }
268
269         rte_spinlock_lock(&dev->os_dep.dma_hash_lock);
270         (void)rte_hash_del_key_with_hash(hash, &phys, sig);
271         rte_spinlock_unlock(&dev->os_dep.dma_hash_lock);
272
273         (void)rte_memzone_free(mz);
274 }
275
276 struct dma_pool *dma_pool_create(const char *name, void *dev,
277                                  size_t size, size_t align, size_t boundary)
278 {
279         struct pci_pool *pool;
280
281         pool = rte_zmalloc(NULL, sizeof(*pool), HINIC_MEM_ALLOC_ALIGN_MIN);
282         if (!pool)
283                 return NULL;
284
285         rte_atomic32_set(&pool->inuse, 0);
286         pool->elem_size = size;
287         pool->align = align;
288         pool->boundary = boundary;
289         pool->hwdev = dev;
290         strncpy(pool->name, name, (sizeof(pool->name) - 1));
291
292         return pool;
293 }
294
295 void dma_pool_destroy(struct dma_pool *pool)
296 {
297         if (!pool)
298                 return;
299
300         if (rte_atomic32_read(&pool->inuse) != 0) {
301                 PMD_DRV_LOG(ERR, "Leak memory, dma_pool: %s, inuse_count: %d",
302                             pool->name, rte_atomic32_read(&pool->inuse));
303         }
304
305         rte_free(pool);
306 }
307
308 void *dma_pool_alloc(struct pci_pool *pool, dma_addr_t *dma_addr)
309 {
310         void *buf;
311
312         buf = hinic_dma_mem_zalloc(pool->hwdev, pool->elem_size, dma_addr,
313                                 (u32)pool->align, SOCKET_ID_ANY);
314         if (buf)
315                 rte_atomic32_inc(&pool->inuse);
316
317         return buf;
318 }
319
320 void dma_pool_free(struct pci_pool *pool, void *vaddr, dma_addr_t dma)
321 {
322         rte_atomic32_dec(&pool->inuse);
323         hinic_dma_mem_free(pool->hwdev, pool->elem_size, vaddr, dma);
324 }
325
326 #define HINIC_MAX_DMA_ENTRIES           8192
327 int hinic_osdep_init(struct hinic_hwdev *hwdev)
328 {
329         struct rte_hash_parameters dh_params = { 0 };
330         struct rte_hash *paddr_hash = NULL;
331
332         rte_atomic32_set(&hwdev->os_dep.dma_alloc_cnt, 0);
333         rte_spinlock_init(&hwdev->os_dep.dma_hash_lock);
334
335         dh_params.name = hwdev->pcidev_hdl->name;
336         dh_params.entries = HINIC_MAX_DMA_ENTRIES;
337         dh_params.key_len = HINIC_HASH_KEY_LEN;
338         dh_params.hash_func = HINIC_HASH_FUNC;
339         dh_params.hash_func_init_val = HINIC_HASH_FUNC_INIT_VAL;
340         dh_params.socket_id = SOCKET_ID_ANY;
341
342         paddr_hash = rte_hash_find_existing(dh_params.name);
343         if (paddr_hash == NULL) {
344                 paddr_hash = rte_hash_create(&dh_params);
345                 if (paddr_hash == NULL) {
346                         PMD_DRV_LOG(ERR, "Create nic_dev phys_addr hash table failed");
347                         return -ENOMEM;
348                 }
349         } else {
350                 PMD_DRV_LOG(INFO, "Using existing dma hash table %s",
351                             dh_params.name);
352         }
353         hwdev->os_dep.dma_addr_hash = paddr_hash;
354
355         return 0;
356 }
357
358 void hinic_osdep_deinit(struct hinic_hwdev *hwdev)
359 {
360         uint32_t iter = 0;
361         dma_addr_t key_pa;
362         struct rte_memzone *data_mz = NULL;
363         struct rte_hash *paddr_hash = hwdev->os_dep.dma_addr_hash;
364
365         if (paddr_hash) {
366                 /* iterate through the hash table */
367                 while (rte_hash_iterate(paddr_hash, (const void **)&key_pa,
368                                         (void **)&data_mz, &iter) >= 0) {
369                         if (data_mz) {
370                                 PMD_DRV_LOG(WARNING, "Free leaked dma_addr: %p, mz: %s",
371                                         (void *)key_pa, data_mz->name);
372                                 (void)rte_memzone_free(data_mz);
373                         }
374                 }
375
376                 /* free phys_addr hash table */
377                 rte_hash_free(paddr_hash);
378         }
379 }
380
381 /**
382  * hinic_set_ci_table - set ci attribute table
383  * @hwdev: the hardware interface of a nic device
384  * @q_id: Queue id of SQ
385  * @attr: Point to SQ CI attribute table
386  * @return
387  *   0 on success and ci attribute table is filled,
388  *   negative error value otherwise.
389  */
390 int hinic_set_ci_table(void *hwdev, u16 q_id, struct hinic_sq_attr *attr)
391 {
392         struct hinic_cons_idx_attr cons_idx_attr;
393         u16 out_size = sizeof(cons_idx_attr);
394         int err;
395
396         memset(&cons_idx_attr, 0, sizeof(cons_idx_attr));
397         cons_idx_attr.mgmt_msg_head.resp_aeq_num = HINIC_AEQ1;
398         cons_idx_attr.func_idx = hinic_global_func_id(hwdev);
399         cons_idx_attr.dma_attr_off  = attr->dma_attr_off;
400         cons_idx_attr.pending_limit = attr->pending_limit;
401         cons_idx_attr.coalescing_time = attr->coalescing_time;
402         if (attr->intr_en) {
403                 cons_idx_attr.intr_en = attr->intr_en;
404                 cons_idx_attr.intr_idx = attr->intr_idx;
405         }
406
407         cons_idx_attr.l2nic_sqn = attr->l2nic_sqn;
408         cons_idx_attr.sq_id = q_id;
409         cons_idx_attr.ci_addr = attr->ci_dma_base;
410
411         err = hinic_msg_to_mgmt_sync(hwdev, HINIC_MOD_COMM,
412                                       HINIC_MGMT_CMD_L2NIC_SQ_CI_ATTR_SET,
413                                       &cons_idx_attr, sizeof(cons_idx_attr),
414                                       &cons_idx_attr, &out_size, 0);
415         if (err || !out_size || cons_idx_attr.mgmt_msg_head.status) {
416                 PMD_DRV_LOG(ERR, "Set ci attribute table failed, err: %d, status: 0x%x, out_size: 0x%x",
417                         err, cons_idx_attr.mgmt_msg_head.status, out_size);
418                 return -EIO;
419         }
420
421         return 0;
422 }
423
424 /**
425  * hinic_set_pagesize - set page size to vat table
426  * @hwdev: the hardware interface of a nic device
427  * @page_size: vat page size
428  * @return
429  *   0 on success,
430  *   negative error value otherwise.
431  */
432 int hinic_set_pagesize(void *hwdev, u8 page_size)
433 {
434         struct hinic_page_size page_size_info;
435         u16 out_size = sizeof(page_size_info);
436         int err;
437
438         if (page_size > HINIC_PAGE_SIZE_MAX) {
439                 PMD_DRV_LOG(ERR, "Invalid page_size %u, bigger than %u",
440                        page_size, HINIC_PAGE_SIZE_MAX);
441                 return -EINVAL;
442         }
443
444         memset(&page_size_info, 0, sizeof(page_size_info));
445         page_size_info.mgmt_msg_head.resp_aeq_num = HINIC_AEQ1;
446         page_size_info.func_idx = hinic_global_func_id(hwdev);
447         page_size_info.ppf_idx = hinic_ppf_idx(hwdev);
448         page_size_info.page_size = page_size;
449
450         err = hinic_msg_to_mgmt_sync(hwdev, HINIC_MOD_COMM,
451                                      HINIC_MGMT_CMD_PAGESIZE_SET,
452                                      &page_size_info, sizeof(page_size_info),
453                                      &page_size_info, &out_size, 0);
454         if (err || !out_size || page_size_info.mgmt_msg_head.status) {
455                 PMD_DRV_LOG(ERR, "Set wq page size failed, err: %d, status: 0x%x, out_size: 0x%0x",
456                         err, page_size_info.mgmt_msg_head.status, out_size);
457                 return -EIO;
458         }
459
460         return 0;
461 }
462
463 static int wait_for_flr_finish(struct hinic_hwif *hwif)
464 {
465         unsigned long end;
466         enum hinic_pf_status status;
467
468         end = jiffies + msecs_to_jiffies(HINIC_FLR_TIMEOUT);
469         do {
470                 status = hinic_get_pf_status(hwif);
471                 if (status == HINIC_PF_STATUS_FLR_FINISH_FLAG) {
472                         return 0;
473                 }
474
475                 rte_delay_ms(10);
476         } while (time_before(jiffies, end));
477
478         return -EFAULT;
479 }
480
481 #define HINIC_WAIT_CMDQ_IDLE_TIMEOUT            1000
482
483 static int wait_cmdq_stop(struct hinic_hwdev *hwdev)
484 {
485         enum hinic_cmdq_type cmdq_type;
486         struct hinic_cmdqs *cmdqs = hwdev->cmdqs;
487         unsigned long end;
488         int err = 0;
489
490         if (!(cmdqs->status & HINIC_CMDQ_ENABLE))
491                 return 0;
492
493         cmdqs->status &= ~HINIC_CMDQ_ENABLE;
494
495         end = jiffies + msecs_to_jiffies(HINIC_WAIT_CMDQ_IDLE_TIMEOUT);
496         do {
497                 err = 0;
498                 cmdq_type = HINIC_CMDQ_SYNC;
499                 for (; cmdq_type < HINIC_MAX_CMDQ_TYPES; cmdq_type++) {
500                         if (!hinic_cmdq_idle(&cmdqs->cmdq[cmdq_type])) {
501                                 err = -EBUSY;
502                                 break;
503                         }
504                 }
505
506                 if (!err)
507                         return 0;
508
509                 rte_delay_ms(1);
510         } while (time_before(jiffies, end));
511
512         cmdqs->status |= HINIC_CMDQ_ENABLE;
513
514         return err;
515 }
516
517 static int hinic_vf_rx_tx_flush(struct hinic_hwdev *hwdev)
518 {
519         struct hinic_clear_resource clr_res;
520         int err;
521
522         err = wait_cmdq_stop(hwdev);
523         if (err) {
524                 PMD_DRV_LOG(WARNING, "Cmdq is still working");
525                 return err;
526         }
527
528         memset(&clr_res, 0, sizeof(clr_res));
529         clr_res.func_idx = HINIC_HWIF_GLOBAL_IDX(hwdev->hwif);
530         clr_res.ppf_idx  = HINIC_HWIF_PPF_IDX(hwdev->hwif);
531         err = hinic_mbox_to_pf_no_ack(hwdev, HINIC_MOD_COMM,
532                 HINIC_MGMT_CMD_START_FLR, &clr_res, sizeof(clr_res));
533         if (err)
534                 PMD_DRV_LOG(WARNING, "Notice flush message failed");
535
536         /*
537          * PF firstly set VF doorbell flush csr to be disabled. After PF finish
538          * VF resources flush, PF will set VF doorbell flush csr to be enabled.
539          */
540         err = wait_until_doorbell_flush_states(hwdev->hwif, DISABLE_DOORBELL);
541         if (err)
542                 PMD_DRV_LOG(WARNING, "Wait doorbell flush disable timeout");
543
544         err = wait_until_doorbell_flush_states(hwdev->hwif, ENABLE_DOORBELL);
545         if (err)
546                 PMD_DRV_LOG(WARNING, "Wait doorbell flush enable timeout");
547
548         err = hinic_reinit_cmdq_ctxts(hwdev);
549         if (err)
550                 PMD_DRV_LOG(WARNING, "Reinit cmdq failed when vf flush");
551
552         return err;
553 }
554
555 /**
556  * hinic_pf_rx_tx_flush - clean up hardware resource
557  * @hwdev: the hardware interface of a nic device
558  * @return
559  *   0 on success,
560  *   negative error value otherwise.
561  */
562 static int hinic_pf_rx_tx_flush(struct hinic_hwdev *hwdev)
563 {
564         struct hinic_hwif *hwif = hwdev->hwif;
565         struct hinic_clear_doorbell clear_db;
566         struct hinic_clear_resource clr_res;
567         u16 out_size;
568         int err;
569         int ret = 0;
570
571         rte_delay_ms(100);
572
573         err = wait_cmdq_stop(hwdev);
574         if (err) {
575                 PMD_DRV_LOG(ERR, "Cmdq is still working");
576                 return err;
577         }
578
579         hinic_disable_doorbell(hwif);
580         out_size = sizeof(clear_db);
581         memset(&clear_db, 0, sizeof(clear_db));
582         clear_db.mgmt_msg_head.resp_aeq_num = HINIC_AEQ1;
583         clear_db.func_idx = HINIC_HWIF_GLOBAL_IDX(hwif);
584         clear_db.ppf_idx  = HINIC_HWIF_PPF_IDX(hwif);
585         err = hinic_msg_to_mgmt_sync(hwdev, HINIC_MOD_COMM,
586                                      HINIC_MGMT_CMD_FLUSH_DOORBELL, &clear_db,
587                                      sizeof(clear_db), &clear_db, &out_size, 0);
588         if (err || !out_size || clear_db.mgmt_msg_head.status) {
589                 PMD_DRV_LOG(WARNING, "Flush doorbell failed, err: %d, status: 0x%x, out_size: 0x%x",
590                          err, clear_db.mgmt_msg_head.status, out_size);
591                 ret = err ? err : (-EIO);
592         }
593
594         hinic_set_pf_status(hwif, HINIC_PF_STATUS_FLR_START_FLAG);
595         memset(&clr_res, 0, sizeof(clr_res));
596         clr_res.mgmt_msg_head.resp_aeq_num = HINIC_AEQ1;
597         clr_res.func_idx = HINIC_HWIF_GLOBAL_IDX(hwif);
598         clr_res.ppf_idx  = HINIC_HWIF_PPF_IDX(hwif);
599
600         err = hinic_msg_to_mgmt_no_ack(hwdev, HINIC_MOD_COMM,
601                                        HINIC_MGMT_CMD_START_FLR, &clr_res,
602                                        sizeof(clr_res), NULL, NULL);
603         if (err) {
604                 PMD_DRV_LOG(WARNING, "Notice flush msg failed, err: %d", err);
605                 ret = err;
606         }
607
608         err = wait_for_flr_finish(hwif);
609         if (err) {
610                 PMD_DRV_LOG(WARNING, "Wait firmware FLR timeout, err: %d", err);
611                 ret = err;
612         }
613
614         hinic_enable_doorbell(hwif);
615
616         err = hinic_reinit_cmdq_ctxts(hwdev);
617         if (err) {
618                 PMD_DRV_LOG(WARNING,
619                             "Reinit cmdq failed when pf flush, err: %d", err);
620                 ret = err;
621         }
622
623         return ret;
624 }
625
626 int hinic_func_rx_tx_flush(struct hinic_hwdev *hwdev)
627 {
628         if (HINIC_FUNC_TYPE(hwdev) == TYPE_VF)
629                 return hinic_vf_rx_tx_flush(hwdev);
630         else
631                 return hinic_pf_rx_tx_flush(hwdev);
632 }
633
634 /**
635  * hinic_get_interrupt_cfg - get interrupt configuration from NIC
636  * @hwdev: the hardware interface of a nic device
637  * @interrupt_info: Information of Interrupt aggregation
638  * Return: 0 on success, negative error value otherwise.
639  */
640 static int hinic_get_interrupt_cfg(struct hinic_hwdev *hwdev,
641                                 struct nic_interrupt_info *interrupt_info)
642 {
643         struct hinic_msix_config msix_cfg;
644         u16 out_size = sizeof(msix_cfg);
645         int err;
646
647         memset(&msix_cfg, 0, sizeof(msix_cfg));
648         msix_cfg.mgmt_msg_head.resp_aeq_num = HINIC_AEQ1;
649         msix_cfg.func_id = hinic_global_func_id(hwdev);
650         msix_cfg.msix_index = interrupt_info->msix_index;
651
652         err = hinic_msg_to_mgmt_sync(hwdev, HINIC_MOD_COMM,
653                                      HINIC_MGMT_CMD_MSI_CTRL_REG_RD_BY_UP,
654                                      &msix_cfg, sizeof(msix_cfg),
655                                      &msix_cfg, &out_size, 0);
656         if (err || !out_size || msix_cfg.mgmt_msg_head.status) {
657                 PMD_DRV_LOG(ERR, "Get interrupt config failed, err: %d, status: 0x%x, out size: 0x%x",
658                         err, msix_cfg.mgmt_msg_head.status, out_size);
659                 return -EIO;
660         }
661
662         interrupt_info->lli_credit_limit = msix_cfg.lli_credit_cnt;
663         interrupt_info->lli_timer_cfg = msix_cfg.lli_tmier_cnt;
664         interrupt_info->pending_limt = msix_cfg.pending_cnt;
665         interrupt_info->coalesc_timer_cfg = msix_cfg.coalesct_timer_cnt;
666         interrupt_info->resend_timer_cfg = msix_cfg.resend_timer_cnt;
667         return 0;
668 }
669
670 /**
671  * hinic_set_interrupt_cfg - set interrupt configuration to NIC
672  * @hwdev: the hardware interface of a nic device
673  * @interrupt_info: Information of Interrupt aggregation
674  * Return: 0 on success, negative error value otherwise.
675  */
676 int hinic_set_interrupt_cfg(struct hinic_hwdev *hwdev,
677                             struct nic_interrupt_info interrupt_info)
678 {
679         struct hinic_msix_config msix_cfg;
680         struct nic_interrupt_info temp_info;
681         u16 out_size = sizeof(msix_cfg);
682         int err;
683
684         memset(&msix_cfg, 0, sizeof(msix_cfg));
685         msix_cfg.mgmt_msg_head.resp_aeq_num = HINIC_AEQ1;
686         msix_cfg.func_id = hinic_global_func_id(hwdev);
687         msix_cfg.msix_index = (u16)interrupt_info.msix_index;
688
689         temp_info.msix_index = interrupt_info.msix_index;
690
691         err = hinic_get_interrupt_cfg(hwdev, &temp_info);
692         if (err)
693                 return -EINVAL;
694
695         msix_cfg.lli_credit_cnt = temp_info.lli_credit_limit;
696         msix_cfg.lli_tmier_cnt = temp_info.lli_timer_cfg;
697         msix_cfg.pending_cnt = temp_info.pending_limt;
698         msix_cfg.coalesct_timer_cnt = temp_info.coalesc_timer_cfg;
699         msix_cfg.resend_timer_cnt = temp_info.resend_timer_cfg;
700
701         if (interrupt_info.lli_set) {
702                 msix_cfg.lli_credit_cnt = interrupt_info.lli_credit_limit;
703                 msix_cfg.lli_tmier_cnt = interrupt_info.lli_timer_cfg;
704         }
705
706         if (interrupt_info.interrupt_coalesc_set) {
707                 msix_cfg.pending_cnt = interrupt_info.pending_limt;
708                 msix_cfg.coalesct_timer_cnt = interrupt_info.coalesc_timer_cfg;
709                 msix_cfg.resend_timer_cnt = interrupt_info.resend_timer_cfg;
710         }
711
712         err = hinic_msg_to_mgmt_sync(hwdev, HINIC_MOD_COMM,
713                                      HINIC_MGMT_CMD_MSI_CTRL_REG_WR_BY_UP,
714                                      &msix_cfg, sizeof(msix_cfg),
715                                      &msix_cfg, &out_size, 0);
716         if (err || !out_size || msix_cfg.mgmt_msg_head.status) {
717                 PMD_DRV_LOG(ERR, "Set interrupt config failed, err: %d, status: 0x%x, out size: 0x%x",
718                         err, msix_cfg.mgmt_msg_head.status, out_size);
719                 return -EIO;
720         }
721
722         return 0;
723 }
724
725 /**
726  * init_aeqs_msix_attr - Init interrupt attributes of aeq
727  * @hwdev: the hardware interface of a nic device
728  * @return
729  *   0 on success,
730  *   negative error value otherwise.
731  */
732 int init_aeqs_msix_attr(void *hwdev)
733 {
734         struct hinic_hwdev *nic_hwdev = hwdev;
735         struct hinic_aeqs *aeqs = nic_hwdev->aeqs;
736         struct nic_interrupt_info info = {0};
737         struct hinic_eq *eq;
738         u16 q_id;
739         int err;
740
741         info.lli_set = 0;
742         info.interrupt_coalesc_set = 1;
743         info.pending_limt = HINIC_DEAULT_EQ_MSIX_PENDING_LIMIT;
744         info.coalesc_timer_cfg = HINIC_DEAULT_EQ_MSIX_COALESC_TIMER_CFG;
745         info.resend_timer_cfg = HINIC_DEAULT_EQ_MSIX_RESEND_TIMER_CFG;
746
747         for (q_id = 0; q_id < aeqs->num_aeqs; q_id++) {
748                 eq = &aeqs->aeq[q_id];
749                 info.msix_index = eq->eq_irq.msix_entry_idx;
750                 err = hinic_set_interrupt_cfg(hwdev, info);
751                 if (err) {
752                         PMD_DRV_LOG(ERR, "Set msix attr for aeq %d failed",
753                                     q_id);
754                         return -EFAULT;
755                 }
756         }
757
758         return 0;
759 }
760
761 /**
762  * set_pf_dma_attr_entry - set the dma attributes for entry
763  * @hwdev: the pointer to the private hardware device object
764  * @entry_idx: the entry index in the dma table
765  * @st: PCIE TLP steering tag
766  * @at: PCIE TLP AT field
767  * @ph: PCIE TLP Processing Hint field
768  * @no_snooping: PCIE TLP No snooping
769  * @tph_en: PCIE TLP Processing Hint Enable
770  */
771 static void set_pf_dma_attr_entry(struct hinic_hwdev *hwdev, u32 entry_idx,
772                                   u8 st, u8 at, u8 ph,
773                                   enum hinic_pcie_nosnoop no_snooping,
774                                   enum hinic_pcie_tph tph_en)
775 {
776         u32 addr, val, dma_attr_entry;
777
778         /* Read Modify Write */
779         addr = HINIC_CSR_DMA_ATTR_TBL_ADDR(entry_idx);
780
781         val = hinic_hwif_read_reg(hwdev->hwif, addr);
782         val = HINIC_DMA_ATTR_ENTRY_CLEAR(val, ST)       &
783                 HINIC_DMA_ATTR_ENTRY_CLEAR(val, AT)     &
784                 HINIC_DMA_ATTR_ENTRY_CLEAR(val, PH)     &
785                 HINIC_DMA_ATTR_ENTRY_CLEAR(val, NO_SNOOPING)    &
786                 HINIC_DMA_ATTR_ENTRY_CLEAR(val, TPH_EN);
787
788         dma_attr_entry = HINIC_DMA_ATTR_ENTRY_SET(st, ST)       |
789                          HINIC_DMA_ATTR_ENTRY_SET(at, AT)       |
790                          HINIC_DMA_ATTR_ENTRY_SET(ph, PH)       |
791                          HINIC_DMA_ATTR_ENTRY_SET(no_snooping, NO_SNOOPING) |
792                          HINIC_DMA_ATTR_ENTRY_SET(tph_en, TPH_EN);
793
794         val |= dma_attr_entry;
795         hinic_hwif_write_reg(hwdev->hwif, addr, val);
796 }
797
798 static int set_vf_dma_attr_entry(struct hinic_hwdev *hwdev, u8 entry_idx,
799                                 u8 st, u8 at, u8 ph,
800                                 enum hinic_pcie_nosnoop no_snooping,
801                                 enum hinic_pcie_tph tph_en)
802 {
803         struct hinic_vf_dma_attr_table attr;
804         u16 out_size = sizeof(attr);
805         int err;
806
807         memset(&attr, 0, sizeof(attr));
808         attr.func_idx = hinic_global_func_id(hwdev);
809         attr.mgmt_msg_head.resp_aeq_num = HINIC_AEQ1;
810         attr.func_dma_entry_num = hinic_dma_attr_entry_num(hwdev);
811         attr.entry_idx = entry_idx;
812         attr.st = st;
813         attr.at = at;
814         attr.ph = ph;
815         attr.no_snooping = no_snooping;
816         attr.tph_en = tph_en;
817
818         err = hinic_msg_to_mgmt_sync(hwdev, HINIC_MOD_COMM,
819                                      HINIC_MGMT_CMD_DMA_ATTR_SET,
820                                      &attr, sizeof(attr), &attr, &out_size, 0);
821         if (err || !out_size || attr.mgmt_msg_head.status) {
822                 PMD_DRV_LOG(ERR, "Set dma attribute failed, err: %d, status: 0x%x, out_size: 0x%x",
823                         err, attr.mgmt_msg_head.status, out_size);
824                 return -EIO;
825         }
826
827         return 0;
828 }
829
830 /**
831  * dma_attr_table_init - initialize the the default dma attributes
832  * @hwdev: the pointer to the private hardware device object
833  */
834 static int dma_attr_table_init(struct hinic_hwdev *hwdev)
835 {
836         int err = 0;
837
838         if (HINIC_IS_VF(hwdev))
839                 err = set_vf_dma_attr_entry(hwdev, PCIE_MSIX_ATTR_ENTRY,
840                                 HINIC_PCIE_ST_DISABLE, HINIC_PCIE_AT_DISABLE,
841                                 HINIC_PCIE_PH_DISABLE, HINIC_PCIE_SNOOP,
842                                 HINIC_PCIE_TPH_DISABLE);
843         else
844                 set_pf_dma_attr_entry(hwdev, PCIE_MSIX_ATTR_ENTRY,
845                                 HINIC_PCIE_ST_DISABLE, HINIC_PCIE_AT_DISABLE,
846                                 HINIC_PCIE_PH_DISABLE, HINIC_PCIE_SNOOP,
847                                 HINIC_PCIE_TPH_DISABLE);
848
849         return err;
850 }
851
852 /**
853  * hinic_init_attr_table - init dma and aeq msix attribute table
854  * @hwdev: the pointer to the private hardware device object
855  */
856 int hinic_init_attr_table(struct hinic_hwdev *hwdev)
857 {
858         int err;
859
860         err = dma_attr_table_init(hwdev);
861         if (err) {
862                 PMD_DRV_LOG(ERR, "Initialize dma attribute table failed, err: %d",
863                                 err);
864                 return err;
865         }
866
867         err = init_aeqs_msix_attr(hwdev);
868         if (err) {
869                 PMD_DRV_LOG(ERR, "Initialize aeqs msix attribute failed, err: %d",
870                                 err);
871                 return err;
872         }
873
874         return 0;
875 }
876
877 #define FAULT_SHOW_STR_LEN 16
878 static void fault_report_show(struct hinic_hwdev *hwdev,
879                               struct hinic_fault_event *event)
880 {
881         char fault_type[FAULT_TYPE_MAX][FAULT_SHOW_STR_LEN + 1] = {
882                 "chip", "ucode", "mem rd timeout", "mem wr timeout",
883                 "reg rd timeout", "reg wr timeout"};
884         char fault_level[FAULT_LEVEL_MAX][FAULT_SHOW_STR_LEN + 1] = {
885                 "fatal", "reset", "flr", "general", "suggestion"};
886         char type_str[FAULT_SHOW_STR_LEN + 1] = { 0 };
887         char level_str[FAULT_SHOW_STR_LEN + 1] = { 0 };
888         u8 err_level;
889
890         PMD_DRV_LOG(WARNING, "Fault event report received, func_id: %d",
891                  hinic_global_func_id(hwdev));
892
893         if (event->type < FAULT_TYPE_MAX)
894                 strncpy(type_str, fault_type[event->type], FAULT_SHOW_STR_LEN);
895         else
896                 strncpy(type_str, "unknown", FAULT_SHOW_STR_LEN);
897         PMD_DRV_LOG(WARNING, "fault type:    %d [%s]",
898                  event->type, type_str);
899         PMD_DRV_LOG(WARNING, "fault val[0]:  0x%08x",
900                  event->event.val[0]);
901         PMD_DRV_LOG(WARNING, "fault val[1]:  0x%08x",
902                  event->event.val[1]);
903         PMD_DRV_LOG(WARNING, "fault val[2]:  0x%08x",
904                  event->event.val[2]);
905         PMD_DRV_LOG(WARNING, "fault val[3]:  0x%08x",
906                  event->event.val[3]);
907
908         switch (event->type) {
909         case FAULT_TYPE_CHIP:
910                 err_level = event->event.chip.err_level;
911                 if (err_level < FAULT_LEVEL_MAX)
912                         strncpy(level_str, fault_level[err_level],
913                                 FAULT_SHOW_STR_LEN);
914                 else
915                         strncpy(level_str, "unknown",
916                                 FAULT_SHOW_STR_LEN);
917
918                 PMD_DRV_LOG(WARNING, "err_level:     %d [%s]",
919                          err_level, level_str);
920
921                 if (err_level == FAULT_LEVEL_SERIOUS_FLR) {
922                         PMD_DRV_LOG(WARNING, "flr func_id:   %d",
923                                  event->event.chip.func_id);
924                 } else {
925                         PMD_DRV_LOG(WARNING, "node_id:       %d",
926                                  event->event.chip.node_id);
927                         PMD_DRV_LOG(WARNING, "err_type:      %d",
928                                  event->event.chip.err_type);
929                         PMD_DRV_LOG(WARNING, "err_csr_addr:  %d",
930                                  event->event.chip.err_csr_addr);
931                         PMD_DRV_LOG(WARNING, "err_csr_value: %d",
932                                  event->event.chip.err_csr_value);
933                 }
934                 break;
935         case FAULT_TYPE_UCODE:
936                 PMD_DRV_LOG(WARNING, "cause_id:      %d",
937                          event->event.ucode.cause_id);
938                 PMD_DRV_LOG(WARNING, "core_id:       %d",
939                          event->event.ucode.core_id);
940                 PMD_DRV_LOG(WARNING, "c_id:          %d",
941                          event->event.ucode.c_id);
942                 PMD_DRV_LOG(WARNING, "epc:           %d",
943                          event->event.ucode.epc);
944                 break;
945         case FAULT_TYPE_MEM_RD_TIMEOUT:
946         case FAULT_TYPE_MEM_WR_TIMEOUT:
947                 PMD_DRV_LOG(WARNING, "err_csr_ctrl:  %d",
948                          event->event.mem_timeout.err_csr_ctrl);
949                 PMD_DRV_LOG(WARNING, "err_csr_data:  %d",
950                          event->event.mem_timeout.err_csr_data);
951                 PMD_DRV_LOG(WARNING, "ctrl_tab:      %d",
952                          event->event.mem_timeout.ctrl_tab);
953                 PMD_DRV_LOG(WARNING, "mem_index:     %d",
954                          event->event.mem_timeout.mem_index);
955                 break;
956         case FAULT_TYPE_REG_RD_TIMEOUT:
957         case FAULT_TYPE_REG_WR_TIMEOUT:
958                 PMD_DRV_LOG(WARNING, "err_csr:       %d",
959                          event->event.reg_timeout.err_csr);
960                 break;
961         default:
962                 break;
963         }
964 }
965
966 static int resources_state_set(struct hinic_hwdev *hwdev,
967                                enum hinic_res_state state)
968 {
969         struct hinic_cmd_set_res_state res_state;
970         u16 out_size = sizeof(res_state);
971         int err;
972
973         memset(&res_state, 0, sizeof(res_state));
974         res_state.mgmt_msg_head.resp_aeq_num = HINIC_AEQ1;
975         res_state.func_idx = HINIC_HWIF_GLOBAL_IDX(hwdev->hwif);
976         res_state.state = state;
977
978         err = hinic_msg_to_mgmt_sync(hwdev, HINIC_MOD_COMM,
979                                  HINIC_MGMT_CMD_RES_STATE_SET,
980                                  &res_state, sizeof(res_state),
981                                  &res_state, &out_size, 0);
982         if (err || !out_size || res_state.mgmt_msg_head.status) {
983                 PMD_DRV_LOG(ERR, "Set resources state failed, err: %d, status: 0x%x, out_size: 0x%x",
984                         err, res_state.mgmt_msg_head.status, out_size);
985                 return -EIO;
986         }
987
988         return 0;
989 }
990
991 /**
992  * hinic_activate_hwdev_state - Active host nic state and notify mgmt channel
993  * that host nic is ready.
994  * @hwdev: the hardware interface of a nic device
995  * @return
996  *   0 on success,
997  *   negative error value otherwise.
998  */
999 int hinic_activate_hwdev_state(struct hinic_hwdev *hwdev)
1000 {
1001         int rc = HINIC_OK;
1002
1003         if (!hwdev)
1004                 return -EINVAL;
1005
1006         hinic_set_pf_status(hwdev->hwif, HINIC_PF_STATUS_ACTIVE_FLAG);
1007
1008         rc = resources_state_set(hwdev, HINIC_RES_ACTIVE);
1009         if (rc) {
1010                 PMD_DRV_LOG(ERR, "Initialize resources state failed");
1011                 return rc;
1012         }
1013
1014         return 0;
1015 }
1016
1017 /**
1018  * hinic_deactivate_hwdev_state - Deactivate host nic state and notify mgmt
1019  * channel that host nic is not ready.
1020  * @hwdev: the pointer to the private hardware device object
1021  */
1022 void hinic_deactivate_hwdev_state(struct hinic_hwdev *hwdev)
1023 {
1024         int rc = HINIC_OK;
1025
1026         if (!hwdev)
1027                 return;
1028
1029         rc = resources_state_set(hwdev, HINIC_RES_CLEAN);
1030         if (rc)
1031                 PMD_DRV_LOG(ERR, "Deinit resources state failed");
1032
1033         hinic_set_pf_status(hwdev->hwif, HINIC_PF_STATUS_INIT);
1034 }
1035
1036 int hinic_get_board_info(void *hwdev, struct hinic_board_info *info)
1037 {
1038         struct hinic_comm_board_info board_info;
1039         u16 out_size = sizeof(board_info);
1040         int err;
1041
1042         if (!hwdev || !info)
1043                 return -EINVAL;
1044
1045         memset(&board_info, 0, sizeof(board_info));
1046         board_info.mgmt_msg_head.resp_aeq_num = HINIC_AEQ1;
1047         err = hinic_msg_to_mgmt_sync(hwdev, HINIC_MOD_COMM,
1048                                      HINIC_MGMT_CMD_GET_BOARD_INFO,
1049                                      &board_info, sizeof(board_info),
1050                                      &board_info, &out_size, 0);
1051         if (err || board_info.mgmt_msg_head.status || !out_size) {
1052                 PMD_DRV_LOG(ERR, "Failed to get board info, err: %d, status: 0x%x, out size: 0x%x",
1053                         err, board_info.mgmt_msg_head.status, out_size);
1054                 return -EFAULT;
1055         }
1056
1057         memcpy(info, &board_info.info, sizeof(*info));
1058         return 0;
1059 }
1060
1061 /**
1062  * hinic_l2nic_reset - Restore the initial state of NIC
1063  * @hwdev: the hardware interface of a nic device
1064  * @return
1065  *   0 on success,
1066  *   negative error value otherwise.
1067  */
1068 int hinic_l2nic_reset(struct hinic_hwdev *hwdev)
1069 {
1070         struct hinic_hwif *hwif = hwdev->hwif;
1071         struct hinic_l2nic_reset l2nic_reset;
1072         u16 out_size = sizeof(l2nic_reset);
1073         int err = 0;
1074
1075         err = hinic_set_vport_enable(hwdev, false);
1076         if (err) {
1077                 PMD_DRV_LOG(ERR, "Set vport disable failed");
1078                 return err;
1079         }
1080
1081         rte_delay_ms(100);
1082
1083         memset(&l2nic_reset, 0, sizeof(l2nic_reset));
1084         l2nic_reset.mgmt_msg_head.resp_aeq_num = HINIC_AEQ1;
1085         l2nic_reset.func_id = HINIC_HWIF_GLOBAL_IDX(hwif);
1086         err = hinic_msg_to_mgmt_sync(hwdev, HINIC_MOD_COMM,
1087                                      HINIC_MGMT_CMD_L2NIC_RESET,
1088                                      &l2nic_reset, sizeof(l2nic_reset),
1089                                      &l2nic_reset, &out_size, 0);
1090         if (err || !out_size || l2nic_reset.mgmt_msg_head.status) {
1091                 PMD_DRV_LOG(ERR, "Reset L2NIC resources failed, err: %d, status: 0x%x, out_size: 0x%x",
1092                         err, l2nic_reset.mgmt_msg_head.status, out_size);
1093                 return -EIO;
1094         }
1095
1096         return 0;
1097 }
1098
1099 static void
1100 hinic_show_sw_watchdog_timeout_info(void *buf_in, u16 in_size,
1101                                     void *buf_out, u16 *out_size)
1102 {
1103         struct hinic_mgmt_watchdog_info *watchdog_info;
1104         u32 *dump_addr, *reg, stack_len, i, j;
1105
1106         if (in_size != sizeof(*watchdog_info)) {
1107                 PMD_DRV_LOG(ERR, "Invalid mgmt watchdog report, length: %d, should be %zu",
1108                         in_size, sizeof(*watchdog_info));
1109                 return;
1110         }
1111
1112         watchdog_info = (struct hinic_mgmt_watchdog_info *)buf_in;
1113
1114         PMD_DRV_LOG(ERR, "Mgmt deadloop time: 0x%x 0x%x, task id: 0x%x, sp: 0x%x",
1115                 watchdog_info->curr_time_h, watchdog_info->curr_time_l,
1116                 watchdog_info->task_id, watchdog_info->sp);
1117         PMD_DRV_LOG(ERR, "Stack current used: 0x%x, peak used: 0x%x, overflow flag: 0x%x, top: 0x%x, bottom: 0x%x",
1118                 watchdog_info->curr_used, watchdog_info->peak_used,
1119                 watchdog_info->is_overflow, watchdog_info->stack_top,
1120                 watchdog_info->stack_bottom);
1121
1122         PMD_DRV_LOG(ERR, "Mgmt pc: 0x%08x, lr: 0x%08x, cpsr: 0x%08x",
1123                 watchdog_info->pc, watchdog_info->lr, watchdog_info->cpsr);
1124
1125         PMD_DRV_LOG(ERR, "Mgmt register info");
1126
1127         for (i = 0; i < 3; i++) {
1128                 reg = watchdog_info->reg + (u64)(u32)(4 * i);
1129                 PMD_DRV_LOG(ERR, "0x%08x 0x%08x 0x%08x 0x%08x",
1130                         *(reg), *(reg + 1), *(reg + 2), *(reg + 3));
1131         }
1132
1133         PMD_DRV_LOG(ERR, "0x%08x", watchdog_info->reg[12]);
1134
1135         if (watchdog_info->stack_actlen <= 1024) {
1136                 stack_len = watchdog_info->stack_actlen;
1137         } else {
1138                 PMD_DRV_LOG(ERR, "Oops stack length: 0x%x is wrong",
1139                         watchdog_info->stack_actlen);
1140                 stack_len = 1024;
1141         }
1142
1143         PMD_DRV_LOG(ERR, "Mgmt dump stack, 16Bytes per line(start from sp)");
1144         for (i = 0; i < (stack_len / 16); i++) {
1145                 dump_addr = (u32 *)(watchdog_info->data + ((u64)(u32)(i * 16)));
1146                 PMD_DRV_LOG(ERR, "0x%08x 0x%08x 0x%08x 0x%08x",
1147                         *dump_addr, *(dump_addr + 1), *(dump_addr + 2),
1148                         *(dump_addr + 3));
1149         }
1150
1151         for (j = 0; j < ((stack_len % 16) / 4); j++) {
1152                 dump_addr = (u32 *)(watchdog_info->data +
1153                             ((u64)(u32)(i * 16 + j * 4)));
1154                 PMD_DRV_LOG(ERR, "0x%08x", *dump_addr);
1155         }
1156
1157         *out_size = sizeof(*watchdog_info);
1158         watchdog_info = (struct hinic_mgmt_watchdog_info *)buf_out;
1159         watchdog_info->mgmt_msg_head.status = 0;
1160 }
1161
1162 static void hinic_show_pcie_dfx_info(struct hinic_hwdev *hwdev,
1163                                      void *buf_in, u16 in_size,
1164                                      void *buf_out, u16 *out_size)
1165 {
1166         struct hinic_pcie_dfx_ntc *notice_info =
1167                 (struct hinic_pcie_dfx_ntc *)buf_in;
1168         struct hinic_pcie_dfx_info dfx_info;
1169         u16 size = 0;
1170         u16 cnt = 0;
1171         u32 num = 0;
1172         u32 i, j;
1173         int err;
1174         u32 *reg;
1175
1176         if (in_size != sizeof(*notice_info)) {
1177                 PMD_DRV_LOG(ERR, "Invalid pcie dfx notice info, length: %d, should be %zu.",
1178                         in_size, sizeof(*notice_info));
1179                 return;
1180         }
1181
1182         ((struct hinic_pcie_dfx_ntc *)buf_out)->mgmt_msg_head.status = 0;
1183         *out_size = sizeof(*notice_info);
1184         memset(&dfx_info, 0, sizeof(dfx_info));
1185         num = (u32)(notice_info->len / 1024);
1186         PMD_DRV_LOG(INFO, "INFO LEN: %d", notice_info->len);
1187         PMD_DRV_LOG(INFO, "PCIE DFX:");
1188         dfx_info.host_id = 0;
1189         dfx_info.mgmt_msg_head.resp_aeq_num = HINIC_AEQ1;
1190         for (i = 0; i < num; i++) {
1191                 dfx_info.offset = i * MAX_PCIE_DFX_BUF_SIZE;
1192                 if (i == (num - 1))
1193                         dfx_info.last = 1;
1194                 size = sizeof(dfx_info);
1195                 err = hinic_msg_to_mgmt_sync(hwdev, HINIC_MOD_COMM,
1196                                              HINIC_MGMT_CMD_PCIE_DFX_GET,
1197                                              &dfx_info, sizeof(dfx_info),
1198                                              &dfx_info, &size, 0);
1199                 if (err || dfx_info.mgmt_msg_head.status || !size) {
1200                         PMD_DRV_LOG(ERR, "Failed to get pcie dfx info, err: %d, status: 0x%x, out size: 0x%x",
1201                                 err, dfx_info.mgmt_msg_head.status, size);
1202                         return;
1203                 }
1204
1205                 reg = (u32 *)dfx_info.data;
1206                 for (j = 0; j < 256; j = j + 8) {
1207                         PMD_DRV_LOG(ERR, "0x%04x: 0x%08x 0x%08x 0x%08x 0x%08x 0x%08x 0x%08x 0x%08x 0x%08x",
1208                                 cnt, reg[j], reg[(u32)(j + 1)],
1209                                 reg[(u32)(j + 2)], reg[(u32)(j + 3)],
1210                                 reg[(u32)(j + 4)], reg[(u32)(j + 5)],
1211                                 reg[(u32)(j + 6)], reg[(u32)(j + 7)]);
1212                         cnt = cnt + 32;
1213                 }
1214                 memset(dfx_info.data, 0, MAX_PCIE_DFX_BUF_SIZE);
1215         }
1216 }
1217
1218 static void
1219 hinic_show_ffm_info(struct hinic_hwdev *hwdev, void *buf_in, u16 in_size)
1220 {
1221         struct ffm_intr_info *intr;
1222
1223         if (in_size != sizeof(struct ffm_intr_info)) {
1224                 PMD_DRV_LOG(ERR, "Invalid input buffer len, length: %d, should be %zu.",
1225                         in_size, sizeof(struct ffm_intr_info));
1226                 return;
1227         }
1228
1229         if (hwdev->ffm_num < FFM_RECORD_NUM_MAX) {
1230                 hwdev->ffm_num++;
1231                 intr = (struct ffm_intr_info *)buf_in;
1232                 PMD_DRV_LOG(WARNING, "node_id(%d),err_csr_addr(0x%x),err_csr_val(0x%x),err_level(0x%x),err_type(0x%x)",
1233                             intr->node_id,
1234                             intr->err_csr_addr,
1235                             intr->err_csr_value,
1236                             intr->err_level,
1237                             intr->err_type);
1238         }
1239 }
1240
1241 void hinic_comm_async_event_handle(struct hinic_hwdev *hwdev, u8 cmd,
1242                                    void *buf_in, u16 in_size,
1243                                    void *buf_out, u16 *out_size)
1244 {
1245         struct hinic_cmd_fault_event *fault_event, *ret_fault_event;
1246
1247         if (!hwdev)
1248                 return;
1249
1250         *out_size = 0;
1251
1252         switch (cmd) {
1253         case HINIC_MGMT_CMD_FAULT_REPORT:
1254                 if (in_size != sizeof(*fault_event)) {
1255                         PMD_DRV_LOG(ERR, "Invalid fault event report, length: %d, should be %zu",
1256                                 in_size, sizeof(*fault_event));
1257                         return;
1258                 }
1259
1260                 fault_event = (struct hinic_cmd_fault_event *)buf_in;
1261                 fault_report_show(hwdev, &fault_event->event);
1262
1263                 if (hinic_func_type(hwdev) != TYPE_VF) {
1264                         ret_fault_event =
1265                                 (struct hinic_cmd_fault_event *)buf_out;
1266                         ret_fault_event->mgmt_msg_head.status = 0;
1267                         *out_size = sizeof(*ret_fault_event);
1268                 }
1269                 break;
1270
1271         case HINIC_MGMT_CMD_WATCHDOG_INFO:
1272                 hinic_show_sw_watchdog_timeout_info(buf_in, in_size,
1273                                                     buf_out, out_size);
1274                 break;
1275
1276         case HINIC_MGMT_CMD_PCIE_DFX_NTC:
1277                 hinic_show_pcie_dfx_info(hwdev, buf_in, in_size,
1278                                          buf_out, out_size);
1279                 break;
1280
1281         case HINIC_MGMT_CMD_FFM_SET:
1282                 hinic_show_ffm_info(hwdev, buf_in, in_size);
1283                 break;
1284
1285         default:
1286                 break;
1287         }
1288 }
1289
1290 static void
1291 hinic_cable_status_event(u8 cmd, void *buf_in, __rte_unused u16 in_size,
1292                          void *buf_out, u16 *out_size)
1293 {
1294         struct hinic_cable_plug_event *plug_event;
1295         struct hinic_link_err_event *link_err;
1296
1297         if (cmd == HINIC_PORT_CMD_CABLE_PLUG_EVENT) {
1298                 plug_event = (struct hinic_cable_plug_event *)buf_in;
1299                 PMD_DRV_LOG(INFO, "Port module event: Cable %s",
1300                          plug_event->plugged ? "plugged" : "unplugged");
1301
1302                 *out_size = sizeof(*plug_event);
1303                 plug_event = (struct hinic_cable_plug_event *)buf_out;
1304                 plug_event->mgmt_msg_head.status = 0;
1305         } else if (cmd == HINIC_PORT_CMD_LINK_ERR_EVENT) {
1306                 link_err = (struct hinic_link_err_event *)buf_in;
1307                 if (link_err->err_type >= LINK_ERR_NUM) {
1308                         PMD_DRV_LOG(ERR, "Link failed, Unknown type: 0x%x",
1309                                 link_err->err_type);
1310                 } else {
1311                         PMD_DRV_LOG(INFO, "Link failed, type: 0x%x: %s",
1312                                  link_err->err_type,
1313                                  hinic_module_link_err[link_err->err_type]);
1314                 }
1315
1316                 *out_size = sizeof(*link_err);
1317                 link_err = (struct hinic_link_err_event *)buf_out;
1318                 link_err->mgmt_msg_head.status = 0;
1319         }
1320 }
1321
1322 static int hinic_link_event_process(struct hinic_hwdev *hwdev,
1323                                     struct rte_eth_dev *eth_dev, u8 status)
1324 {
1325         uint32_t port_speed[LINK_SPEED_MAX] = {ETH_SPEED_NUM_10M,
1326                                         ETH_SPEED_NUM_100M, ETH_SPEED_NUM_1G,
1327                                         ETH_SPEED_NUM_10G, ETH_SPEED_NUM_25G,
1328                                         ETH_SPEED_NUM_40G, ETH_SPEED_NUM_100G};
1329         struct nic_port_info port_info;
1330         struct rte_eth_link link;
1331         int rc = HINIC_OK;
1332
1333         if (!status) {
1334                 link.link_status = ETH_LINK_DOWN;
1335                 link.link_speed = 0;
1336                 link.link_duplex = ETH_LINK_HALF_DUPLEX;
1337                 link.link_autoneg = ETH_LINK_FIXED;
1338         } else {
1339                 link.link_status = ETH_LINK_UP;
1340
1341                 memset(&port_info, 0, sizeof(port_info));
1342                 rc = hinic_get_port_info(hwdev, &port_info);
1343                 if (rc) {
1344                         link.link_speed = ETH_SPEED_NUM_NONE;
1345                         link.link_duplex = ETH_LINK_FULL_DUPLEX;
1346                         link.link_autoneg = ETH_LINK_FIXED;
1347                 } else {
1348                         link.link_speed = port_speed[port_info.speed %
1349                                                 LINK_SPEED_MAX];
1350                         link.link_duplex = port_info.duplex;
1351                         link.link_autoneg = port_info.autoneg_state;
1352                 }
1353         }
1354         (void)rte_eth_linkstatus_set(eth_dev, &link);
1355
1356         return rc;
1357 }
1358
1359 static void hinic_lsc_process(struct hinic_hwdev *hwdev,
1360                               struct rte_eth_dev *rte_dev, u8 status)
1361 {
1362         int ret;
1363
1364         ret = hinic_link_event_process(hwdev, rte_dev, status);
1365         /* check if link has changed, notify callback */
1366         if (ret == 0)
1367                 _rte_eth_dev_callback_process(rte_dev,
1368                                               RTE_ETH_EVENT_INTR_LSC,
1369                                               NULL);
1370 }
1371
1372 void hinic_l2nic_async_event_handle(struct hinic_hwdev *hwdev,
1373                                     void *param, u8 cmd,
1374                                     void *buf_in, u16 in_size,
1375                                     void *buf_out, u16 *out_size)
1376 {
1377         struct hinic_port_link_status *in_link;
1378         struct rte_eth_dev *eth_dev;
1379
1380         if (!hwdev)
1381                 return;
1382
1383         *out_size = 0;
1384
1385         switch (cmd) {
1386         case HINIC_PORT_CMD_LINK_STATUS_REPORT:
1387                 eth_dev = param;
1388                 in_link = (struct hinic_port_link_status *)buf_in;
1389                 PMD_DRV_LOG(INFO, "Link status event report, dev_name: %s, port_id: %d, link_status: %s",
1390                          eth_dev->data->name, eth_dev->data->port_id,
1391                          in_link->link ? "UP" : "DOWN");
1392
1393                 hinic_lsc_process(hwdev, eth_dev, in_link->link);
1394                 break;
1395
1396         case HINIC_PORT_CMD_CABLE_PLUG_EVENT:
1397         case HINIC_PORT_CMD_LINK_ERR_EVENT:
1398                 hinic_cable_status_event(cmd, buf_in, in_size,
1399                                          buf_out, out_size);
1400                 break;
1401
1402         case HINIC_PORT_CMD_MGMT_RESET:
1403                 PMD_DRV_LOG(WARNING, "Mgmt is reset");
1404                 break;
1405
1406         default:
1407                 PMD_DRV_LOG(ERR, "Unsupported event %d to process",
1408                         cmd);
1409                 break;
1410         }
1411 }
1412
1413 static void print_cable_info(struct hinic_link_info *info)
1414 {
1415         char tmp_str[512] = {0};
1416         char tmp_vendor[17] = {0};
1417         const char *port_type = "Unknown port type";
1418         int i;
1419
1420         if (info->cable_absent) {
1421                 PMD_DRV_LOG(INFO, "Cable unpresent");
1422                 return;
1423         }
1424
1425         if (info->port_type < LINK_PORT_MAX_TYPE)
1426                 port_type = __hw_to_char_port_type[info->port_type];
1427         else
1428                 PMD_DRV_LOG(INFO, "Unknown port type: %u",
1429                          info->port_type);
1430         if (info->port_type == LINK_PORT_FIBRE) {
1431                 if (info->port_sub_type == FIBRE_SUBTYPE_SR)
1432                         port_type = "Fibre-SR";
1433                 else if (info->port_sub_type == FIBRE_SUBTYPE_LR)
1434                         port_type = "Fibre-LR";
1435         }
1436
1437         for (i = sizeof(info->vendor_name) - 1; i >= 0; i--) {
1438                 if (info->vendor_name[i] == ' ')
1439                         info->vendor_name[i] = '\0';
1440                 else
1441                         break;
1442         }
1443
1444         memcpy(tmp_vendor, info->vendor_name, sizeof(info->vendor_name));
1445         snprintf(tmp_str, sizeof(tmp_str),
1446                  "Vendor: %s, %s, %s, length: %um, max_speed: %uGbps",
1447                  tmp_vendor, info->sfp_type ? "SFP" : "QSFP", port_type,
1448                  info->cable_length, info->cable_max_speed);
1449         if (info->port_type != LINK_PORT_COPPER)
1450                 snprintf(tmp_str + strlen(tmp_str),
1451                          sizeof(tmp_str) - strlen(tmp_str),
1452                          ", Temperature: %u", info->cable_temp);
1453
1454         PMD_DRV_LOG(INFO, "Cable information: %s", tmp_str);
1455 }
1456
1457 static void print_hi30_status(struct hinic_link_info *info)
1458 {
1459         struct hi30_ffe_data *ffe_data;
1460         struct hi30_ctle_data *ctle_data;
1461
1462         ffe_data = (struct hi30_ffe_data *)info->hi30_ffe;
1463         ctle_data = (struct hi30_ctle_data *)info->hi30_ctle;
1464
1465         PMD_DRV_LOG(INFO, "TX_FFE: PRE2=%s%d; PRE1=%s%d; MAIN=%d; POST1=%s%d; POST1X=%s%d",
1466                  (ffe_data->PRE1 & 0x10) ? "-" : "",
1467                  (int)(ffe_data->PRE1 & 0xf),
1468                  (ffe_data->PRE2 & 0x10) ? "-" : "",
1469                  (int)(ffe_data->PRE2 & 0xf),
1470                  (int)ffe_data->MAIN,
1471                  (ffe_data->POST1 & 0x10) ? "-" : "",
1472                  (int)(ffe_data->POST1 & 0xf),
1473                  (ffe_data->POST2 & 0x10) ? "-" : "",
1474                  (int)(ffe_data->POST2 & 0xf));
1475         PMD_DRV_LOG(INFO, "RX_CTLE: Gain1~3=%u %u %u; Boost1~3=%u %u %u; Zero1~3=%u %u %u; Squelch1~3=%u %u %u",
1476                  ctle_data->ctlebst[0], ctle_data->ctlebst[1],
1477                  ctle_data->ctlebst[2], ctle_data->ctlecmband[0],
1478                  ctle_data->ctlecmband[1], ctle_data->ctlecmband[2],
1479                  ctle_data->ctlermband[0], ctle_data->ctlermband[1],
1480                  ctle_data->ctlermband[2], ctle_data->ctleza[0],
1481                  ctle_data->ctleza[1], ctle_data->ctleza[2]);
1482 }
1483
1484 static void print_link_info(struct hinic_link_info *info,
1485                             enum hilink_info_print_event type)
1486 {
1487         const char *fec = "None";
1488
1489         if (info->fec < HILINK_FEC_MAX_TYPE)
1490                 fec = __hw_to_char_fec[info->fec];
1491         else
1492                 PMD_DRV_LOG(INFO, "Unknown fec type: %u",
1493                          info->fec);
1494
1495         if (type == HILINK_EVENT_LINK_UP || !info->an_state) {
1496                 PMD_DRV_LOG(INFO, "Link information: speed %dGbps, %s, autoneg %s",
1497                          info->speed, fec, info->an_state ? "on" : "off");
1498         } else {
1499                 PMD_DRV_LOG(INFO, "Link information: antoneg: %s",
1500                          info->an_state ? "on" : "off");
1501         }
1502 }
1503
1504 static const char *hilink_info_report_type[HILINK_EVENT_MAX_TYPE] = {
1505         "", "link up", "link down", "cable plugged"
1506 };
1507
1508 static void hinic_print_hilink_info(void *buf_in, u16 in_size,
1509                                     void *buf_out, u16 *out_size)
1510 {
1511         struct hinic_hilink_link_info *hilink_info =
1512                 (struct hinic_hilink_link_info *)buf_in;
1513         struct hinic_link_info *info;
1514         enum hilink_info_print_event type;
1515
1516         if (in_size != sizeof(*hilink_info)) {
1517                 PMD_DRV_LOG(ERR, "Invalid hilink info message size %d, should be %zu",
1518                         in_size, sizeof(*hilink_info));
1519                 return;
1520         }
1521
1522         ((struct hinic_hilink_link_info *)buf_out)->mgmt_msg_head.status = 0;
1523         *out_size = sizeof(*hilink_info);
1524
1525         info = &hilink_info->info;
1526         type = hilink_info->info_type;
1527
1528         if (type < HILINK_EVENT_LINK_UP || type >= HILINK_EVENT_MAX_TYPE) {
1529                 PMD_DRV_LOG(INFO, "Invalid hilink info report, type: %d",
1530                          type);
1531                 return;
1532         }
1533
1534         PMD_DRV_LOG(INFO, "Hilink info report after %s",
1535                  hilink_info_report_type[type]);
1536
1537         print_cable_info(info);
1538
1539         print_link_info(info, type);
1540
1541         print_hi30_status(info);
1542
1543         if (type == HILINK_EVENT_LINK_UP)
1544                 return;
1545
1546         if (type == HILINK_EVENT_CABLE_PLUGGED) {
1547                 PMD_DRV_LOG(INFO, "alos: %u, rx_los: %u",
1548                          info->alos, info->rx_los);
1549                 return;
1550         }
1551
1552         PMD_DRV_LOG(INFO, "PMA ctrl: %s, MAC tx %s, MAC rx %s, PMA debug inforeg: 0x%x, PMA signal ok reg: 0x%x, RF/LF status reg: 0x%x",
1553                  info->pma_status ? "on" : "off",
1554                  info->mac_tx_en ? "enable" : "disable",
1555                  info->mac_rx_en ? "enable" : "disable", info->pma_dbg_info_reg,
1556                  info->pma_signal_ok_reg, info->rf_lf_status_reg);
1557         PMD_DRV_LOG(INFO, "alos: %u, rx_los: %u, PCS block counter reg: 0x%x,PCS link: 0x%x, MAC link: 0x%x PCS_err_cnt: 0x%x",
1558                  info->alos, info->rx_los, info->pcs_err_blk_cnt_reg,
1559                  info->pcs_link_reg, info->mac_link_reg, info->pcs_err_cnt);
1560 }
1561
1562 void hinic_hilink_async_event_handle(struct hinic_hwdev *hwdev, u8 cmd,
1563                                      void *buf_in, u16 in_size,
1564                                      void *buf_out, u16 *out_size)
1565 {
1566         if (!hwdev)
1567                 return;
1568
1569         *out_size = 0;
1570
1571         switch (cmd) {
1572         case HINIC_HILINK_CMD_GET_LINK_INFO:
1573                 hinic_print_hilink_info(buf_in, in_size, buf_out,
1574                                         out_size);
1575                 break;
1576
1577         default:
1578                 PMD_DRV_LOG(ERR, "Unsupported event %d to process",
1579                         cmd);
1580                 break;
1581         }
1582 }