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