1 /* SPDX-License-Identifier: BSD-3-Clause
2 * Copyright(c) 2017 Huawei Technologies Co., Ltd
5 #include<rte_ethdev_driver.h>
6 #include <rte_bus_pci.h>
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"
19 #define HINIC_DEAULT_EQ_MSIX_PENDING_LIMIT 0
20 #define HINIC_DEAULT_EQ_MSIX_COALESC_TIMER_CFG 0xFF
21 #define HINIC_DEAULT_EQ_MSIX_RESEND_TIMER_CFG 7
23 #define HINIC_FLR_TIMEOUT 1000
25 #define FFM_RECORD_NUM_MAX 32
27 #define HINIC_DMA_ATTR_ENTRY_ST_SHIFT 0
28 #define HINIC_DMA_ATTR_ENTRY_AT_SHIFT 8
29 #define HINIC_DMA_ATTR_ENTRY_PH_SHIFT 10
30 #define HINIC_DMA_ATTR_ENTRY_NO_SNOOPING_SHIFT 12
31 #define HINIC_DMA_ATTR_ENTRY_TPH_EN_SHIFT 13
33 #define HINIC_DMA_ATTR_ENTRY_ST_MASK 0xFF
34 #define HINIC_DMA_ATTR_ENTRY_AT_MASK 0x3
35 #define HINIC_DMA_ATTR_ENTRY_PH_MASK 0x3
36 #define HINIC_DMA_ATTR_ENTRY_NO_SNOOPING_MASK 0x1
37 #define HINIC_DMA_ATTR_ENTRY_TPH_EN_MASK 0x1
39 #define HINIC_DMA_ATTR_ENTRY_SET(val, member) \
40 (((u32)(val) & HINIC_DMA_ATTR_ENTRY_##member##_MASK) << \
41 HINIC_DMA_ATTR_ENTRY_##member##_SHIFT)
43 #define HINIC_DMA_ATTR_ENTRY_CLEAR(val, member) \
44 ((val) & (~(HINIC_DMA_ATTR_ENTRY_##member##_MASK \
45 << HINIC_DMA_ATTR_ENTRY_##member##_SHIFT)))
47 #define HINIC_PCIE_ST_DISABLE 0
48 #define HINIC_PCIE_AT_DISABLE 0
49 #define HINIC_PCIE_PH_DISABLE 0
50 #define PCIE_MSIX_ATTR_ENTRY 0
52 #define HINIC_HASH_FUNC rte_jhash
53 #define HINIC_HASH_KEY_LEN (sizeof(dma_addr_t))
54 #define HINIC_HASH_FUNC_INIT_VAL 0
56 static const char *__hw_to_char_fec[HILINK_FEC_MAX_TYPE] = {
57 "RS-FEC", "BASE-FEC", "NO-FEC"};
59 static const char *__hw_to_char_port_type[LINK_PORT_MAX_TYPE] = {
60 "Unknown", "Fibre", "Electric", "Direct Attach Copper", "AOC",
64 static const char *hinic_module_link_err[LINK_ERR_NUM] = {
65 "Unrecognized module",
69 hinic_dma_mem_zalloc(struct hinic_hwdev *hwdev, size_t size,
70 dma_addr_t *dma_handle, unsigned int flag, unsigned int align)
73 const struct rte_memzone *mz;
74 char z_name[RTE_MEMZONE_NAMESIZE];
78 if (dma_handle == NULL || 0 == size)
81 alloc_cnt = rte_atomic32_add_return(&hwdev->os_dep.dma_alloc_cnt, 1);
82 snprintf(z_name, sizeof(z_name), "%s_%d",
83 hwdev->pcidev_hdl->name, alloc_cnt);
85 mz = rte_memzone_reserve_aligned(z_name, size, SOCKET_ID_ANY,
88 PMD_DRV_LOG(ERR, "Alloc dma able memory failed, errno: %d, ma_name: %s, size: 0x%zx",
89 rte_errno, z_name, size);
95 /* check if phys_addr already exist */
96 sig = HINIC_HASH_FUNC(&iova, HINIC_HASH_KEY_LEN,
97 HINIC_HASH_FUNC_INIT_VAL);
98 rc = rte_hash_lookup_with_hash(hwdev->os_dep.dma_addr_hash,
101 PMD_DRV_LOG(ERR, "Dma addr: %p already in hash table, error: %d, mz_name: %s",
102 (void *)iova, rc, z_name);
103 goto phys_addr_hash_err;
106 /* record paddr in hash table */
107 rte_spinlock_lock(&hwdev->os_dep.dma_hash_lock);
108 rc = rte_hash_add_key_with_hash_data(hwdev->os_dep.dma_addr_hash,
111 rte_spinlock_unlock(&hwdev->os_dep.dma_hash_lock);
113 PMD_DRV_LOG(ERR, "Insert dma addr: %p hash failed, error: %d, mz_name: %s",
114 (void *)iova, rc, z_name);
115 goto phys_addr_hash_err;
118 memset(mz->addr, 0, size);
123 (void)rte_memzone_free(mz);
129 hinic_dma_mem_free(struct hinic_hwdev *hwdev, size_t size,
130 void *virt, dma_addr_t phys)
133 struct rte_memzone *mz = NULL;
134 struct rte_hash *hash;
137 if (virt == NULL || phys == 0)
140 hash = hwdev->os_dep.dma_addr_hash;
141 sig = HINIC_HASH_FUNC(&phys, HINIC_HASH_KEY_LEN,
142 HINIC_HASH_FUNC_INIT_VAL);
143 rc = rte_hash_lookup_with_hash_data(hash, &phys, sig, (void **)&mz);
145 PMD_DRV_LOG(ERR, "Can not find phys_addr: %p, error: %d",
150 if (virt != mz->addr || size > mz->len) {
151 PMD_DRV_LOG(ERR, "Match mz_info failed: "
152 "mz.name: %s, mz.phys: %p, mz.virt: %p, mz.len: %zu, "
153 "phys: %p, virt: %p, size: %zu",
154 mz->name, (void *)mz->iova, mz->addr, mz->len,
155 (void *)phys, virt, size);
158 rte_spinlock_lock(&hwdev->os_dep.dma_hash_lock);
159 (void)rte_hash_del_key_with_hash(hash, &phys, sig);
160 rte_spinlock_unlock(&hwdev->os_dep.dma_hash_lock);
162 (void)rte_memzone_free(mz);
165 void *dma_zalloc_coherent(void *hwdev, size_t size,
166 dma_addr_t *dma_handle, gfp_t flag)
168 return hinic_dma_mem_zalloc(hwdev, size, dma_handle, flag,
169 RTE_CACHE_LINE_SIZE);
172 void *dma_zalloc_coherent_aligned(void *hwdev, size_t size,
173 dma_addr_t *dma_handle, gfp_t flag)
175 return hinic_dma_mem_zalloc(hwdev, size, dma_handle, flag,
179 void *dma_zalloc_coherent_aligned256k(void *hwdev, size_t size,
180 dma_addr_t *dma_handle, gfp_t flag)
182 return hinic_dma_mem_zalloc(hwdev, size, dma_handle, flag,
183 HINIC_PAGE_SIZE * 64);
186 void dma_free_coherent(void *hwdev, size_t size, void *virt, dma_addr_t phys)
188 hinic_dma_mem_free(hwdev, size, virt, phys);
191 void dma_free_coherent_volatile(void *hwdev, size_t size,
192 volatile void *virt, dma_addr_t phys)
195 struct rte_memzone *mz = NULL;
196 struct hinic_hwdev *dev = hwdev;
197 struct rte_hash *hash;
200 if (virt == NULL || phys == 0)
203 hash = dev->os_dep.dma_addr_hash;
204 sig = HINIC_HASH_FUNC(&phys, HINIC_HASH_KEY_LEN,
205 HINIC_HASH_FUNC_INIT_VAL);
206 rc = rte_hash_lookup_with_hash_data(hash, &phys, sig, (void **)&mz);
208 PMD_DRV_LOG(ERR, "Can not find phys_addr: %p, error: %d",
213 if (virt != mz->addr || size > mz->len) {
214 PMD_DRV_LOG(ERR, "Match mz_info failed: "
215 "mz.name:%s, mz.phys:%p, mz.virt:%p, mz.len:%zu, "
216 "phys:%p, virt:%p, size:%zu",
217 mz->name, (void *)mz->iova, mz->addr, mz->len,
218 (void *)phys, virt, size);
221 rte_spinlock_lock(&dev->os_dep.dma_hash_lock);
222 (void)rte_hash_del_key_with_hash(hash, &phys, sig);
223 rte_spinlock_unlock(&dev->os_dep.dma_hash_lock);
225 (void)rte_memzone_free(mz);
228 struct dma_pool *dma_pool_create(const char *name, void *dev,
229 size_t size, size_t align, size_t boundary)
231 struct pci_pool *pool;
233 pool = rte_zmalloc(NULL, sizeof(*pool), HINIC_MEM_ALLOC_ALIGNE_MIN);
238 pool->elem_size = size;
240 pool->boundary = boundary;
242 strncpy(pool->name, name, (sizeof(pool->name) - 1));
247 void dma_pool_destroy(struct dma_pool *pool)
252 if (pool->inuse != 0) {
253 PMD_DRV_LOG(ERR, "Leak memory, dma_pool:%s, inuse_count:%u",
254 pool->name, pool->inuse);
260 void *dma_pool_alloc(struct pci_pool *pool, int flags, dma_addr_t *dma_addr)
264 buf = hinic_dma_mem_zalloc(pool->hwdev, pool->elem_size,
265 dma_addr, flags, (u32)pool->align);
272 void dma_pool_free(struct pci_pool *pool, void *vaddr, dma_addr_t dma)
275 hinic_dma_mem_free(pool->hwdev, pool->elem_size, vaddr, dma);
280 #define HINIC_MAX_DMA_ENTRIES 8192
281 int hinic_osdep_init(struct hinic_hwdev *hwdev)
283 struct rte_hash_parameters dh_params = { 0 };
284 struct rte_hash *paddr_hash = NULL;
286 rte_atomic32_set(&hwdev->os_dep.dma_alloc_cnt, 0);
287 rte_spinlock_init(&hwdev->os_dep.dma_hash_lock);
289 dh_params.name = hwdev->pcidev_hdl->name;
290 dh_params.entries = HINIC_MAX_DMA_ENTRIES;
291 dh_params.key_len = HINIC_HASH_KEY_LEN;
292 dh_params.hash_func = HINIC_HASH_FUNC;
293 dh_params.hash_func_init_val = HINIC_HASH_FUNC_INIT_VAL;
294 dh_params.socket_id = SOCKET_ID_ANY;
296 paddr_hash = rte_hash_find_existing(dh_params.name);
297 if (paddr_hash == NULL) {
298 paddr_hash = rte_hash_create(&dh_params);
299 if (paddr_hash == NULL) {
300 PMD_DRV_LOG(ERR, "Create nic_dev phys_addr hash table failed");
304 PMD_DRV_LOG(INFO, "Using existing dma hash table %s",
307 hwdev->os_dep.dma_addr_hash = paddr_hash;
312 void hinic_osdep_deinit(struct hinic_hwdev *hwdev)
316 struct rte_memzone *data_mz = NULL;
317 struct rte_hash *paddr_hash = hwdev->os_dep.dma_addr_hash;
320 /* iterate through the hash table */
321 while (rte_hash_iterate(paddr_hash, (const void **)&key_pa,
322 (void **)&data_mz, &iter) >= 0) {
324 PMD_DRV_LOG(WARNING, "Free leaked dma_addr: %p, mz: %s",
325 (void *)key_pa, data_mz->name);
326 (void)rte_memzone_free(data_mz);
330 /* free phys_addr hash table */
331 rte_hash_free(paddr_hash);
348 * hinic_set_ci_table - set ci attribute table
349 * @hwdev: the hardware interface of a nic device
350 * @q_id: Queue id of SQ
351 * @attr: Point to SQ CI attribute table
353 * 0 on success and ci attribute table is filled,
354 * negative error value otherwise.
356 int hinic_set_ci_table(void *hwdev, u16 q_id, struct hinic_sq_attr *attr)
358 struct hinic_cons_idx_attr cons_idx_attr;
360 memset(&cons_idx_attr, 0, sizeof(cons_idx_attr));
361 cons_idx_attr.mgmt_msg_head.resp_aeq_num = HINIC_AEQ1;
362 cons_idx_attr.func_idx = hinic_global_func_id(hwdev);
363 cons_idx_attr.dma_attr_off = attr->dma_attr_off;
364 cons_idx_attr.pending_limit = attr->pending_limit;
365 cons_idx_attr.coalescing_time = attr->coalescing_time;
367 cons_idx_attr.intr_en = attr->intr_en;
368 cons_idx_attr.intr_idx = attr->intr_idx;
371 cons_idx_attr.l2nic_sqn = attr->l2nic_sqn;
372 cons_idx_attr.sq_id = q_id;
373 cons_idx_attr.ci_addr = attr->ci_dma_base;
375 return hinic_msg_to_mgmt_sync(hwdev, HINIC_MOD_COMM,
376 HINIC_MGMT_CMD_L2NIC_SQ_CI_ATTR_SET,
377 &cons_idx_attr, sizeof(cons_idx_attr),
382 * hinic_set_pagesize - set page size to vat table
383 * @hwdev: the hardware interface of a nic device
384 * @page_size: vat page size
387 * negative error value otherwise.
389 int hinic_set_pagesize(void *hwdev, u8 page_size)
391 struct hinic_page_size cmd;
393 if (page_size > HINIC_PAGE_SIZE_MAX) {
394 PMD_DRV_LOG(ERR, "Invalid page_size %u, bigger than %u",
395 page_size, HINIC_PAGE_SIZE_MAX);
399 memset(&cmd, 0, sizeof(cmd));
400 cmd.mgmt_msg_head.resp_aeq_num = HINIC_AEQ1;
401 cmd.func_idx = hinic_global_func_id(hwdev);
402 cmd.ppf_idx = hinic_ppf_idx(hwdev);
403 cmd.page_size = page_size;
405 return hinic_msg_to_mgmt_sync(hwdev, HINIC_MOD_COMM,
406 HINIC_MGMT_CMD_PAGESIZE_SET,
411 static int wait_for_flr_finish(struct hinic_hwif *hwif)
414 enum hinic_pf_status status;
416 end = jiffies + msecs_to_jiffies(HINIC_FLR_TIMEOUT);
418 status = hinic_get_pf_status(hwif);
419 if (status == HINIC_PF_STATUS_FLR_FINISH_FLAG) {
420 hinic_set_pf_status(hwif, HINIC_PF_STATUS_ACTIVE_FLAG);
425 } while (time_before(jiffies, end));
430 #define HINIC_WAIT_CMDQ_IDLE_TIMEOUT 1000
432 static int wait_cmdq_stop(struct hinic_hwdev *hwdev)
434 enum hinic_cmdq_type cmdq_type;
435 struct hinic_cmdqs *cmdqs = hwdev->cmdqs;
439 if (!(cmdqs->status & HINIC_CMDQ_ENABLE))
442 cmdqs->status &= ~HINIC_CMDQ_ENABLE;
444 end = jiffies + msecs_to_jiffies(HINIC_WAIT_CMDQ_IDLE_TIMEOUT);
447 cmdq_type = HINIC_CMDQ_SYNC;
448 for (; cmdq_type < HINIC_MAX_CMDQ_TYPES; cmdq_type++) {
449 if (!hinic_cmdq_idle(&cmdqs->cmdq[cmdq_type])) {
459 } while (time_before(jiffies, end));
461 cmdqs->status |= HINIC_CMDQ_ENABLE;
467 * hinic_pf_rx_tx_flush - clean up hardware resource
468 * @hwdev: the hardware interface of a nic device
471 * negative error value otherwise.
473 static int hinic_pf_rx_tx_flush(struct hinic_hwdev *hwdev)
475 struct hinic_hwif *hwif = hwdev->hwif;
476 struct hinic_clear_doorbell clear_db;
477 struct hinic_clear_resource clr_res;
482 err = wait_cmdq_stop(hwdev);
484 PMD_DRV_LOG(ERR, "Cmdq is still working");
488 hinic_disable_doorbell(hwif);
489 memset(&clear_db, 0, sizeof(clear_db));
490 clear_db.mgmt_msg_head.resp_aeq_num = HINIC_AEQ1;
491 clear_db.func_idx = HINIC_HWIF_GLOBAL_IDX(hwif);
492 clear_db.ppf_idx = HINIC_HWIF_PPF_IDX(hwif);
493 err = hinic_msg_to_mgmt_sync(hwdev, HINIC_MOD_COMM,
494 HINIC_MGMT_CMD_FLUSH_DOORBELL, &clear_db,
495 sizeof(clear_db), NULL, NULL, 0);
497 PMD_DRV_LOG(WARNING, "Flush doorbell failed");
499 hinic_set_pf_status(hwif, HINIC_PF_STATUS_FLR_START_FLAG);
500 memset(&clr_res, 0, sizeof(clr_res));
501 clr_res.mgmt_msg_head.resp_aeq_num = HINIC_AEQ1;
502 clr_res.func_idx = HINIC_HWIF_GLOBAL_IDX(hwif);
503 clr_res.ppf_idx = HINIC_HWIF_PPF_IDX(hwif);
505 err = hinic_msg_to_mgmt_no_ack(hwdev, HINIC_MOD_COMM,
506 HINIC_MGMT_CMD_START_FLR, &clr_res,
507 sizeof(clr_res), NULL, NULL);
509 PMD_DRV_LOG(WARNING, "Notice flush message failed");
511 err = wait_for_flr_finish(hwif);
513 PMD_DRV_LOG(WARNING, "Wait firmware FLR timeout");
515 hinic_enable_doorbell(hwif);
517 err = hinic_reinit_cmdq_ctxts(hwdev);
519 PMD_DRV_LOG(WARNING, "Reinit cmdq failed");
524 int hinic_func_rx_tx_flush(struct hinic_hwdev *hwdev)
526 return hinic_pf_rx_tx_flush(hwdev);
530 * hinic_get_interrupt_cfg - get interrupt configuration from NIC
531 * @hwdev: the hardware interface of a nic device
532 * @interrupt_info: Information of Interrupt aggregation
533 * Return: 0 on success, negative error value otherwise.
535 static int hinic_get_interrupt_cfg(struct hinic_hwdev *hwdev,
536 struct nic_interrupt_info *interrupt_info)
538 struct hinic_msix_config msix_cfg;
539 u16 out_size = sizeof(msix_cfg);
542 memset(&msix_cfg, 0, sizeof(msix_cfg));
543 msix_cfg.mgmt_msg_head.resp_aeq_num = HINIC_AEQ1;
544 msix_cfg.func_id = hinic_global_func_id(hwdev);
545 msix_cfg.msix_index = interrupt_info->msix_index;
547 err = hinic_msg_to_mgmt_sync(hwdev, HINIC_MOD_COMM,
548 HINIC_MGMT_CMD_MSI_CTRL_REG_RD_BY_UP,
549 &msix_cfg, sizeof(msix_cfg),
550 &msix_cfg, &out_size, 0);
551 if (err || !out_size || msix_cfg.mgmt_msg_head.status) {
552 PMD_DRV_LOG(ERR, "Get interrupt config failed, ret: %d",
553 msix_cfg.mgmt_msg_head.status);
557 interrupt_info->lli_credit_limit = msix_cfg.lli_credit_cnt;
558 interrupt_info->lli_timer_cfg = msix_cfg.lli_tmier_cnt;
559 interrupt_info->pending_limt = msix_cfg.pending_cnt;
560 interrupt_info->coalesc_timer_cfg = msix_cfg.coalesct_timer_cnt;
561 interrupt_info->resend_timer_cfg = msix_cfg.resend_timer_cnt;
566 * hinic_set_interrupt_cfg - set interrupt configuration to NIC
567 * @hwdev: the hardware interface of a nic device
568 * @interrupt_info: Information of Interrupt aggregation
569 * Return: 0 on success, negative error value otherwise.
571 int hinic_set_interrupt_cfg(struct hinic_hwdev *hwdev,
572 struct nic_interrupt_info interrupt_info)
574 struct hinic_msix_config msix_cfg;
575 struct nic_interrupt_info temp_info;
576 u16 out_size = sizeof(msix_cfg);
579 memset(&msix_cfg, 0, sizeof(msix_cfg));
580 msix_cfg.mgmt_msg_head.resp_aeq_num = HINIC_AEQ1;
581 msix_cfg.func_id = hinic_global_func_id(hwdev);
582 msix_cfg.msix_index = (u16)interrupt_info.msix_index;
584 temp_info.msix_index = interrupt_info.msix_index;
586 err = hinic_get_interrupt_cfg(hwdev, &temp_info);
590 msix_cfg.lli_credit_cnt = temp_info.lli_credit_limit;
591 msix_cfg.lli_tmier_cnt = temp_info.lli_timer_cfg;
592 msix_cfg.pending_cnt = temp_info.pending_limt;
593 msix_cfg.coalesct_timer_cnt = temp_info.coalesc_timer_cfg;
594 msix_cfg.resend_timer_cnt = temp_info.resend_timer_cfg;
596 if (interrupt_info.lli_set) {
597 msix_cfg.lli_credit_cnt = interrupt_info.lli_credit_limit;
598 msix_cfg.lli_tmier_cnt = interrupt_info.lli_timer_cfg;
601 if (interrupt_info.interrupt_coalesc_set) {
602 msix_cfg.pending_cnt = interrupt_info.pending_limt;
603 msix_cfg.coalesct_timer_cnt = interrupt_info.coalesc_timer_cfg;
604 msix_cfg.resend_timer_cnt = interrupt_info.resend_timer_cfg;
607 err = hinic_msg_to_mgmt_sync(hwdev, HINIC_MOD_COMM,
608 HINIC_MGMT_CMD_MSI_CTRL_REG_WR_BY_UP,
609 &msix_cfg, sizeof(msix_cfg),
610 &msix_cfg, &out_size, 0);
611 if (err || !out_size || msix_cfg.mgmt_msg_head.status) {
612 PMD_DRV_LOG(ERR, "Set interrupt config failed, ret: %d",
613 msix_cfg.mgmt_msg_head.status);
621 * init_aeqs_msix_attr - Init interrupt attributes of aeq
622 * @hwdev: the hardware interface of a nic device
625 * negative error value otherwise.
627 int init_aeqs_msix_attr(void *hwdev)
629 struct hinic_hwdev *nic_hwdev = hwdev;
630 struct hinic_aeqs *aeqs = nic_hwdev->aeqs;
631 struct nic_interrupt_info info = {0};
637 info.interrupt_coalesc_set = 1;
638 info.pending_limt = HINIC_DEAULT_EQ_MSIX_PENDING_LIMIT;
639 info.coalesc_timer_cfg = HINIC_DEAULT_EQ_MSIX_COALESC_TIMER_CFG;
640 info.resend_timer_cfg = HINIC_DEAULT_EQ_MSIX_RESEND_TIMER_CFG;
642 for (q_id = 0; q_id < aeqs->num_aeqs; q_id++) {
643 eq = &aeqs->aeq[q_id];
644 info.msix_index = eq->eq_irq.msix_entry_idx;
645 err = hinic_set_interrupt_cfg(hwdev, info);
647 PMD_DRV_LOG(ERR, "Set msix attr for aeq %d failed",
657 * set_pf_dma_attr_entry - set the dma attributes for entry
658 * @hwdev: the pointer to the private hardware device object
659 * @entry_idx: the entry index in the dma table
660 * @st: PCIE TLP steering tag
661 * @at: PCIE TLP AT field
662 * @ph: PCIE TLP Processing Hint field
663 * @no_snooping: PCIE TLP No snooping
664 * @tph_en: PCIE TLP Processing Hint Enable
666 static void set_pf_dma_attr_entry(struct hinic_hwdev *hwdev, u32 entry_idx,
668 enum hinic_pcie_nosnoop no_snooping,
669 enum hinic_pcie_tph tph_en)
671 u32 addr, val, dma_attr_entry;
673 /* Read Modify Write */
674 addr = HINIC_CSR_DMA_ATTR_TBL_ADDR(entry_idx);
676 val = hinic_hwif_read_reg(hwdev->hwif, addr);
677 val = HINIC_DMA_ATTR_ENTRY_CLEAR(val, ST) &
678 HINIC_DMA_ATTR_ENTRY_CLEAR(val, AT) &
679 HINIC_DMA_ATTR_ENTRY_CLEAR(val, PH) &
680 HINIC_DMA_ATTR_ENTRY_CLEAR(val, NO_SNOOPING) &
681 HINIC_DMA_ATTR_ENTRY_CLEAR(val, TPH_EN);
683 dma_attr_entry = HINIC_DMA_ATTR_ENTRY_SET(st, ST) |
684 HINIC_DMA_ATTR_ENTRY_SET(at, AT) |
685 HINIC_DMA_ATTR_ENTRY_SET(ph, PH) |
686 HINIC_DMA_ATTR_ENTRY_SET(no_snooping, NO_SNOOPING) |
687 HINIC_DMA_ATTR_ENTRY_SET(tph_en, TPH_EN);
689 val |= dma_attr_entry;
690 hinic_hwif_write_reg(hwdev->hwif, addr, val);
694 * dma_attr_table_init - initialize the the default dma attributes
695 * @hwdev: the pointer to the private hardware device object
697 static void dma_attr_table_init(struct hinic_hwdev *hwdev)
699 if (HINIC_IS_VF(hwdev))
702 set_pf_dma_attr_entry(hwdev, PCIE_MSIX_ATTR_ENTRY,
703 HINIC_PCIE_ST_DISABLE,
704 HINIC_PCIE_AT_DISABLE,
705 HINIC_PCIE_PH_DISABLE,
707 HINIC_PCIE_TPH_DISABLE);
710 int hinic_init_attr_table(struct hinic_hwdev *hwdev)
712 dma_attr_table_init(hwdev);
714 return init_aeqs_msix_attr(hwdev);
717 #define FAULT_SHOW_STR_LEN 16
718 static void fault_report_show(struct hinic_hwdev *hwdev,
719 struct hinic_fault_event *event)
721 char fault_type[FAULT_TYPE_MAX][FAULT_SHOW_STR_LEN + 1] = {
722 "chip", "ucode", "mem rd timeout", "mem wr timeout",
723 "reg rd timeout", "reg wr timeout"};
724 char fault_level[FAULT_LEVEL_MAX][FAULT_SHOW_STR_LEN + 1] = {
725 "fatal", "reset", "flr", "general", "suggestion"};
726 char type_str[FAULT_SHOW_STR_LEN + 1] = { 0 };
727 char level_str[FAULT_SHOW_STR_LEN + 1] = { 0 };
730 PMD_DRV_LOG(WARNING, "Fault event report received, func_id: %d",
731 hinic_global_func_id(hwdev));
733 if (event->type < FAULT_TYPE_MAX)
734 strncpy(type_str, fault_type[event->type], FAULT_SHOW_STR_LEN);
736 strncpy(type_str, "unknown", FAULT_SHOW_STR_LEN);
737 PMD_DRV_LOG(WARNING, "fault type: %d [%s]",
738 event->type, type_str);
739 PMD_DRV_LOG(WARNING, "fault val[0]: 0x%08x",
740 event->event.val[0]);
741 PMD_DRV_LOG(WARNING, "fault val[1]: 0x%08x",
742 event->event.val[1]);
743 PMD_DRV_LOG(WARNING, "fault val[2]: 0x%08x",
744 event->event.val[2]);
745 PMD_DRV_LOG(WARNING, "fault val[3]: 0x%08x",
746 event->event.val[3]);
748 switch (event->type) {
749 case FAULT_TYPE_CHIP:
750 err_level = event->event.chip.err_level;
751 if (err_level < FAULT_LEVEL_MAX)
752 strncpy(level_str, fault_level[err_level],
755 strncpy(level_str, "unknown",
758 PMD_DRV_LOG(WARNING, "err_level: %d [%s]",
759 err_level, level_str);
761 if (err_level == FAULT_LEVEL_SERIOUS_FLR) {
762 PMD_DRV_LOG(WARNING, "flr func_id: %d",
763 event->event.chip.func_id);
765 PMD_DRV_LOG(WARNING, "node_id: %d",
766 event->event.chip.node_id);
767 PMD_DRV_LOG(WARNING, "err_type: %d",
768 event->event.chip.err_type);
769 PMD_DRV_LOG(WARNING, "err_csr_addr: %d",
770 event->event.chip.err_csr_addr);
771 PMD_DRV_LOG(WARNING, "err_csr_value: %d",
772 event->event.chip.err_csr_value);
775 case FAULT_TYPE_UCODE:
776 PMD_DRV_LOG(WARNING, "cause_id: %d",
777 event->event.ucode.cause_id);
778 PMD_DRV_LOG(WARNING, "core_id: %d",
779 event->event.ucode.core_id);
780 PMD_DRV_LOG(WARNING, "c_id: %d",
781 event->event.ucode.c_id);
782 PMD_DRV_LOG(WARNING, "epc: %d",
783 event->event.ucode.epc);
785 case FAULT_TYPE_MEM_RD_TIMEOUT:
786 case FAULT_TYPE_MEM_WR_TIMEOUT:
787 PMD_DRV_LOG(WARNING, "err_csr_ctrl: %d",
788 event->event.mem_timeout.err_csr_ctrl);
789 PMD_DRV_LOG(WARNING, "err_csr_data: %d",
790 event->event.mem_timeout.err_csr_data);
791 PMD_DRV_LOG(WARNING, "ctrl_tab: %d",
792 event->event.mem_timeout.ctrl_tab);
793 PMD_DRV_LOG(WARNING, "mem_index: %d",
794 event->event.mem_timeout.mem_index);
796 case FAULT_TYPE_REG_RD_TIMEOUT:
797 case FAULT_TYPE_REG_WR_TIMEOUT:
798 PMD_DRV_LOG(WARNING, "err_csr: %d",
799 event->event.reg_timeout.err_csr);
806 static int resources_state_set(struct hinic_hwdev *hwdev,
807 enum hinic_res_state state)
809 struct hinic_hwif *hwif = hwdev->hwif;
810 struct hinic_cmd_set_res_state res_state;
812 memset(&res_state, 0, sizeof(res_state));
813 res_state.mgmt_msg_head.resp_aeq_num = HINIC_AEQ1;
814 res_state.func_idx = HINIC_HWIF_GLOBAL_IDX(hwif);
815 res_state.state = state;
817 return hinic_msg_to_mgmt_sync(hwdev, HINIC_MOD_COMM,
818 HINIC_MGMT_CMD_RES_STATE_SET,
819 &res_state, sizeof(res_state), NULL, NULL, 0);
823 * hinic_activate_hwdev_state - Active host nic state and notify mgmt channel
824 * that host nic is ready.
825 * @hwdev: the hardware interface of a nic device
828 * negative error value otherwise.
830 int hinic_activate_hwdev_state(struct hinic_hwdev *hwdev)
837 if (!HINIC_IS_VF(hwdev))
838 hinic_set_pf_status(hwdev->hwif,
839 HINIC_PF_STATUS_ACTIVE_FLAG);
841 rc = resources_state_set(hwdev, HINIC_RES_ACTIVE);
843 PMD_DRV_LOG(ERR, "Initialize resources state failed");
851 * hinic_deactivate_hwdev_state - Deactivate host nic state and notify mgmt
852 * channel that host nic is not ready.
853 * @hwdev: the pointer to the private hardware device object
855 void hinic_deactivate_hwdev_state(struct hinic_hwdev *hwdev)
862 rc = resources_state_set(hwdev, HINIC_RES_CLEAN);
864 PMD_DRV_LOG(ERR, "Deinit resources state failed");
866 if (!HINIC_IS_VF(hwdev))
867 hinic_set_pf_status(hwdev->hwif, HINIC_PF_STATUS_INIT);
870 int hinic_get_board_info(void *hwdev, struct hinic_board_info *info)
872 struct hinic_comm_board_info board_info;
873 u16 out_size = sizeof(board_info);
879 memset(&board_info, 0, sizeof(board_info));
880 board_info.mgmt_msg_head.resp_aeq_num = HINIC_AEQ1;
881 err = hinic_msg_to_mgmt_sync(hwdev, HINIC_MOD_COMM,
882 HINIC_MGMT_CMD_GET_BOARD_INFO,
883 &board_info, sizeof(board_info),
884 &board_info, &out_size, 0);
885 if (err || board_info.mgmt_msg_head.status || !out_size) {
886 PMD_DRV_LOG(ERR, "Failed to get board info, err: %d, status: 0x%x, out size: 0x%x",
887 err, board_info.mgmt_msg_head.status, out_size);
891 memcpy(info, &board_info.info, sizeof(*info));
896 * hinic_l2nic_reset - Restore the initial state of NIC
897 * @hwdev: the hardware interface of a nic device
900 * negative error value otherwise.
902 int hinic_l2nic_reset(struct hinic_hwdev *hwdev)
904 struct hinic_hwif *hwif = hwdev->hwif;
905 struct hinic_l2nic_reset l2nic_reset;
908 err = hinic_set_vport_enable(hwdev, false);
910 PMD_DRV_LOG(ERR, "Set vport disable failed");
916 memset(&l2nic_reset, 0, sizeof(l2nic_reset));
917 l2nic_reset.mgmt_msg_head.resp_aeq_num = HINIC_AEQ1;
918 l2nic_reset.func_id = HINIC_HWIF_GLOBAL_IDX(hwif);
919 err = hinic_msg_to_mgmt_sync(hwdev, HINIC_MOD_COMM,
920 HINIC_MGMT_CMD_L2NIC_RESET,
921 &l2nic_reset, sizeof(l2nic_reset),
923 if (err || l2nic_reset.mgmt_msg_head.status) {
924 PMD_DRV_LOG(ERR, "Reset L2NIC resources failed");
932 hinic_show_sw_watchdog_timeout_info(void *buf_in, u16 in_size,
933 void *buf_out, u16 *out_size)
935 struct hinic_mgmt_watchdog_info *watchdog_info;
936 u32 *dump_addr, *reg, stack_len, i, j;
938 if (in_size != sizeof(*watchdog_info)) {
939 PMD_DRV_LOG(ERR, "Invalid mgmt watchdog report, length: %d, should be %zu",
940 in_size, sizeof(*watchdog_info));
944 watchdog_info = (struct hinic_mgmt_watchdog_info *)buf_in;
946 PMD_DRV_LOG(ERR, "Mgmt deadloop time: 0x%x 0x%x, task id: 0x%x, sp: 0x%x",
947 watchdog_info->curr_time_h, watchdog_info->curr_time_l,
948 watchdog_info->task_id, watchdog_info->sp);
949 PMD_DRV_LOG(ERR, "Stack current used: 0x%x, peak used: 0x%x, overflow flag: 0x%x, top: 0x%x, bottom: 0x%x",
950 watchdog_info->curr_used, watchdog_info->peak_used,
951 watchdog_info->is_overflow, watchdog_info->stack_top,
952 watchdog_info->stack_bottom);
954 PMD_DRV_LOG(ERR, "Mgmt pc: 0x%08x, lr: 0x%08x, cpsr:0x%08x",
955 watchdog_info->pc, watchdog_info->lr, watchdog_info->cpsr);
957 PMD_DRV_LOG(ERR, "Mgmt register info");
959 for (i = 0; i < 3; i++) {
960 reg = watchdog_info->reg + (u64)(u32)(4 * i);
961 PMD_DRV_LOG(ERR, "0x%08x 0x%08x 0x%08x 0x%08x",
962 *(reg), *(reg + 1), *(reg + 2), *(reg + 3));
965 PMD_DRV_LOG(ERR, "0x%08x", watchdog_info->reg[12]);
967 if (watchdog_info->stack_actlen <= 1024) {
968 stack_len = watchdog_info->stack_actlen;
970 PMD_DRV_LOG(ERR, "Oops stack length: 0x%x is wrong",
971 watchdog_info->stack_actlen);
975 PMD_DRV_LOG(ERR, "Mgmt dump stack, 16Bytes per line(start from sp)");
976 for (i = 0; i < (stack_len / 16); i++) {
977 dump_addr = (u32 *)(watchdog_info->data + ((u64)(u32)(i * 16)));
978 PMD_DRV_LOG(ERR, "0x%08x 0x%08x 0x%08x 0x%08x",
979 *dump_addr, *(dump_addr + 1), *(dump_addr + 2),
983 for (j = 0; j < ((stack_len % 16) / 4); j++) {
984 dump_addr = (u32 *)(watchdog_info->data +
985 ((u64)(u32)(i * 16 + j * 4)));
986 PMD_DRV_LOG(ERR, "0x%08x", *dump_addr);
989 *out_size = sizeof(*watchdog_info);
990 watchdog_info = (struct hinic_mgmt_watchdog_info *)buf_out;
991 watchdog_info->mgmt_msg_head.status = 0;
994 static void hinic_show_pcie_dfx_info(struct hinic_hwdev *hwdev,
995 void *buf_in, u16 in_size,
996 void *buf_out, u16 *out_size)
998 struct hinic_pcie_dfx_ntc *notice_info =
999 (struct hinic_pcie_dfx_ntc *)buf_in;
1000 struct hinic_pcie_dfx_info dfx_info;
1008 if (in_size != sizeof(*notice_info)) {
1009 PMD_DRV_LOG(ERR, "Invalid pcie dfx notice info, length: %d, should be %zu.",
1010 in_size, sizeof(*notice_info));
1014 ((struct hinic_pcie_dfx_ntc *)buf_out)->mgmt_msg_head.status = 0;
1015 *out_size = sizeof(*notice_info);
1016 memset(&dfx_info, 0, sizeof(dfx_info));
1017 num = (u32)(notice_info->len / 1024);
1018 PMD_DRV_LOG(INFO, "INFO LEN: %d", notice_info->len);
1019 PMD_DRV_LOG(INFO, "PCIE DFX:");
1020 dfx_info.host_id = 0;
1021 dfx_info.mgmt_msg_head.resp_aeq_num = HINIC_AEQ1;
1022 for (i = 0; i < num; i++) {
1023 dfx_info.offset = i * MAX_PCIE_DFX_BUF_SIZE;
1026 size = sizeof(dfx_info);
1027 err = hinic_msg_to_mgmt_sync(hwdev, HINIC_MOD_COMM,
1028 HINIC_MGMT_CMD_PCIE_DFX_GET,
1029 &dfx_info, sizeof(dfx_info),
1030 &dfx_info, &size, 0);
1031 if (err || dfx_info.mgmt_msg_head.status || !size) {
1032 PMD_DRV_LOG(ERR, "Failed to get pcie dfx info, err: %d, status: 0x%x, out size: 0x%x",
1033 err, dfx_info.mgmt_msg_head.status, size);
1037 reg = (u32 *)dfx_info.data;
1038 for (j = 0; j < 256; j = j + 8) {
1039 PMD_DRV_LOG(ERR, "0x%04x: 0x%08x 0x%08x 0x%08x 0x%08x 0x%08x 0x%08x 0x%08x 0x%08x",
1040 cnt, reg[j], reg[(u32)(j + 1)],
1041 reg[(u32)(j + 2)], reg[(u32)(j + 3)],
1042 reg[(u32)(j + 4)], reg[(u32)(j + 5)],
1043 reg[(u32)(j + 6)], reg[(u32)(j + 7)]);
1046 memset(dfx_info.data, 0, MAX_PCIE_DFX_BUF_SIZE);
1051 hinic_show_ffm_info(struct hinic_hwdev *hwdev, void *buf_in, u16 in_size)
1053 struct ffm_intr_info *intr;
1055 if (in_size != sizeof(struct ffm_intr_info)) {
1056 PMD_DRV_LOG(ERR, "Invalid input buffer len, length: %d, should be %zu.",
1057 in_size, sizeof(struct ffm_intr_info));
1061 if (hwdev->ffm_num < FFM_RECORD_NUM_MAX) {
1063 intr = (struct ffm_intr_info *)buf_in;
1064 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)",
1067 intr->err_csr_value,
1073 void hinic_comm_async_event_handle(struct hinic_hwdev *hwdev, u8 cmd,
1074 void *buf_in, u16 in_size,
1075 void *buf_out, u16 *out_size)
1077 struct hinic_cmd_fault_event *fault_event, *ret_fault_event;
1085 case HINIC_MGMT_CMD_FAULT_REPORT:
1086 if (in_size != sizeof(*fault_event)) {
1087 PMD_DRV_LOG(ERR, "Invalid fault event report, length: %d, should be %zu",
1088 in_size, sizeof(*fault_event));
1092 fault_event = (struct hinic_cmd_fault_event *)buf_in;
1093 fault_report_show(hwdev, &fault_event->event);
1095 if (hinic_func_type(hwdev) != TYPE_VF) {
1097 (struct hinic_cmd_fault_event *)buf_out;
1098 ret_fault_event->mgmt_msg_head.status = 0;
1099 *out_size = sizeof(*ret_fault_event);
1103 case HINIC_MGMT_CMD_WATCHDOG_INFO:
1104 hinic_show_sw_watchdog_timeout_info(buf_in, in_size,
1108 case HINIC_MGMT_CMD_PCIE_DFX_NTC:
1109 hinic_show_pcie_dfx_info(hwdev, buf_in, in_size,
1113 case HINIC_MGMT_CMD_FFM_SET:
1114 hinic_show_ffm_info(hwdev, buf_in, in_size);
1123 hinic_cable_status_event(u8 cmd, void *buf_in, __rte_unused u16 in_size,
1124 void *buf_out, u16 *out_size)
1126 struct hinic_cable_plug_event *plug_event;
1127 struct hinic_link_err_event *link_err;
1129 if (cmd == HINIC_PORT_CMD_CABLE_PLUG_EVENT) {
1130 plug_event = (struct hinic_cable_plug_event *)buf_in;
1131 PMD_DRV_LOG(INFO, "Port module event: Cable %s",
1132 plug_event->plugged ? "plugged" : "unplugged");
1134 *out_size = sizeof(*plug_event);
1135 plug_event = (struct hinic_cable_plug_event *)buf_out;
1136 plug_event->mgmt_msg_head.status = 0;
1137 } else if (cmd == HINIC_PORT_CMD_LINK_ERR_EVENT) {
1138 link_err = (struct hinic_link_err_event *)buf_in;
1139 if (link_err->err_type >= LINK_ERR_NUM) {
1140 PMD_DRV_LOG(ERR, "Link failed, Unknown type: 0x%x",
1141 link_err->err_type);
1143 PMD_DRV_LOG(INFO, "Link failed, type: 0x%x: %s",
1145 hinic_module_link_err[link_err->err_type]);
1148 *out_size = sizeof(*link_err);
1149 link_err = (struct hinic_link_err_event *)buf_out;
1150 link_err->mgmt_msg_head.status = 0;
1154 static int hinic_link_event_process(struct hinic_hwdev *hwdev,
1155 struct rte_eth_dev *eth_dev, u8 status)
1157 uint32_t port_speed[LINK_SPEED_MAX] = {ETH_SPEED_NUM_10M,
1158 ETH_SPEED_NUM_100M, ETH_SPEED_NUM_1G,
1159 ETH_SPEED_NUM_10G, ETH_SPEED_NUM_25G,
1160 ETH_SPEED_NUM_40G, ETH_SPEED_NUM_100G};
1161 struct nic_port_info port_info;
1162 struct rte_eth_link link;
1166 link.link_status = ETH_LINK_DOWN;
1167 link.link_speed = 0;
1168 link.link_duplex = ETH_LINK_HALF_DUPLEX;
1169 link.link_autoneg = ETH_LINK_FIXED;
1171 link.link_status = ETH_LINK_UP;
1173 memset(&port_info, 0, sizeof(port_info));
1174 rc = hinic_get_port_info(hwdev, &port_info);
1176 link.link_speed = ETH_SPEED_NUM_NONE;
1177 link.link_duplex = ETH_LINK_FULL_DUPLEX;
1178 link.link_autoneg = ETH_LINK_FIXED;
1180 link.link_speed = port_speed[port_info.speed %
1182 link.link_duplex = port_info.duplex;
1183 link.link_autoneg = port_info.autoneg_state;
1186 (void)rte_eth_linkstatus_set(eth_dev, &link);
1191 static void hinic_lsc_process(struct hinic_hwdev *hwdev,
1192 struct rte_eth_dev *rte_dev, u8 status)
1196 ret = hinic_link_event_process(hwdev, rte_dev, status);
1197 /* check if link has changed, notify callback */
1199 _rte_eth_dev_callback_process(rte_dev,
1200 RTE_ETH_EVENT_INTR_LSC,
1204 void hinic_l2nic_async_event_handle(struct hinic_hwdev *hwdev,
1205 void *param, u8 cmd,
1206 void *buf_in, u16 in_size,
1207 void *buf_out, u16 *out_size)
1209 struct hinic_port_link_status *in_link;
1210 struct rte_eth_dev *eth_dev;
1218 case HINIC_PORT_CMD_LINK_STATUS_REPORT:
1220 in_link = (struct hinic_port_link_status *)buf_in;
1221 PMD_DRV_LOG(INFO, "Link status event report, dev_name: %s, port_id: %d, link_status: %s",
1222 eth_dev->data->name, eth_dev->data->port_id,
1223 in_link->link ? "UP" : "DOWN");
1225 hinic_lsc_process(hwdev, eth_dev, in_link->link);
1228 case HINIC_PORT_CMD_CABLE_PLUG_EVENT:
1229 case HINIC_PORT_CMD_LINK_ERR_EVENT:
1230 hinic_cable_status_event(cmd, buf_in, in_size,
1234 case HINIC_PORT_CMD_MGMT_RESET:
1235 PMD_DRV_LOG(WARNING, "Mgmt is reset");
1239 PMD_DRV_LOG(ERR, "Unsupported event %d to process",
1245 static void print_cable_info(struct hinic_link_info *info)
1247 char tmp_str[512] = {0};
1248 char tmp_vendor[17] = {0};
1249 const char *port_type = "Unknown port type";
1252 if (info->cable_absent) {
1253 PMD_DRV_LOG(INFO, "Cable unpresent");
1257 if (info->port_type < LINK_PORT_MAX_TYPE)
1258 port_type = __hw_to_char_port_type[info->port_type];
1260 PMD_DRV_LOG(INFO, "Unknown port type: %u",
1262 if (info->port_type == LINK_PORT_FIBRE) {
1263 if (info->port_sub_type == FIBRE_SUBTYPE_SR)
1264 port_type = "Fibre-SR";
1265 else if (info->port_sub_type == FIBRE_SUBTYPE_LR)
1266 port_type = "Fibre-LR";
1269 for (i = sizeof(info->vendor_name) - 1; i >= 0; i--) {
1270 if (info->vendor_name[i] == ' ')
1271 info->vendor_name[i] = '\0';
1276 memcpy(tmp_vendor, info->vendor_name, sizeof(info->vendor_name));
1277 snprintf(tmp_str, (sizeof(tmp_str) - 1),
1278 "Vendor: %s, %s, %s, length: %um, max_speed: %uGbps",
1279 tmp_vendor, info->sfp_type ? "SFP" : "QSFP", port_type,
1280 info->cable_length, info->cable_max_speed);
1281 if (info->port_type != LINK_PORT_COPPER)
1282 snprintf(tmp_str + strlen(tmp_str), (sizeof(tmp_str) - 1),
1283 "%s, Temperature: %u", tmp_str,
1286 PMD_DRV_LOG(INFO, "Cable information: %s", tmp_str);
1289 static void print_hi30_status(struct hinic_link_info *info)
1291 struct hi30_ffe_data *ffe_data;
1292 struct hi30_ctle_data *ctle_data;
1294 ffe_data = (struct hi30_ffe_data *)info->hi30_ffe;
1295 ctle_data = (struct hi30_ctle_data *)info->hi30_ctle;
1297 PMD_DRV_LOG(INFO, "TX_FFE: PRE2=%s%d; PRE1=%s%d; MAIN=%d; POST1=%s%d; POST1X=%s%d",
1298 (ffe_data->PRE1 & 0x10) ? "-" : "",
1299 (int)(ffe_data->PRE1 & 0xf),
1300 (ffe_data->PRE2 & 0x10) ? "-" : "",
1301 (int)(ffe_data->PRE2 & 0xf),
1302 (int)ffe_data->MAIN,
1303 (ffe_data->POST1 & 0x10) ? "-" : "",
1304 (int)(ffe_data->POST1 & 0xf),
1305 (ffe_data->POST2 & 0x10) ? "-" : "",
1306 (int)(ffe_data->POST2 & 0xf));
1307 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",
1308 ctle_data->ctlebst[0], ctle_data->ctlebst[1],
1309 ctle_data->ctlebst[2], ctle_data->ctlecmband[0],
1310 ctle_data->ctlecmband[1], ctle_data->ctlecmband[2],
1311 ctle_data->ctlermband[0], ctle_data->ctlermband[1],
1312 ctle_data->ctlermband[2], ctle_data->ctleza[0],
1313 ctle_data->ctleza[1], ctle_data->ctleza[2]);
1316 static void print_link_info(struct hinic_link_info *info,
1317 enum hilink_info_print_event type)
1319 const char *fec = "None";
1321 if (info->fec < HILINK_FEC_MAX_TYPE)
1322 fec = __hw_to_char_fec[info->fec];
1324 PMD_DRV_LOG(INFO, "Unknown fec type: %u",
1327 if (type == HILINK_EVENT_LINK_UP || !info->an_state) {
1328 PMD_DRV_LOG(INFO, "Link information: speed %dGbps, %s, autoneg %s",
1329 info->speed, fec, info->an_state ? "on" : "off");
1331 PMD_DRV_LOG(INFO, "Link information: antoneg: %s",
1332 info->an_state ? "on" : "off");
1336 static const char *hilink_info_report_type[HILINK_EVENT_MAX_TYPE] = {
1337 "", "link up", "link down", "cable plugged"
1340 static void hinic_print_hilink_info(void *buf_in, u16 in_size,
1341 void *buf_out, u16 *out_size)
1343 struct hinic_hilink_link_info *hilink_info =
1344 (struct hinic_hilink_link_info *)buf_in;
1345 struct hinic_link_info *info;
1346 enum hilink_info_print_event type;
1348 if (in_size != sizeof(*hilink_info)) {
1349 PMD_DRV_LOG(ERR, "Invalid hilink info message size %d, should be %zu",
1350 in_size, sizeof(*hilink_info));
1354 ((struct hinic_hilink_link_info *)buf_out)->mgmt_msg_head.status = 0;
1355 *out_size = sizeof(*hilink_info);
1357 info = &hilink_info->info;
1358 type = hilink_info->info_type;
1360 if (type < HILINK_EVENT_LINK_UP || type >= HILINK_EVENT_MAX_TYPE) {
1361 PMD_DRV_LOG(INFO, "Invalid hilink info report, type: %d",
1366 PMD_DRV_LOG(INFO, "Hilink info report after %s",
1367 hilink_info_report_type[type]);
1369 print_cable_info(info);
1371 print_link_info(info, type);
1373 print_hi30_status(info);
1375 if (type == HILINK_EVENT_LINK_UP)
1378 if (type == HILINK_EVENT_CABLE_PLUGGED) {
1379 PMD_DRV_LOG(INFO, "alos: %u, rx_los: %u",
1380 info->alos, info->rx_los);
1384 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",
1385 info->pma_status ? "on" : "off",
1386 info->mac_tx_en ? "enable" : "disable",
1387 info->mac_rx_en ? "enable" : "disable", info->pma_dbg_info_reg,
1388 info->pma_signal_ok_reg, info->rf_lf_status_reg);
1389 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",
1390 info->alos, info->rx_los, info->pcs_err_blk_cnt_reg,
1391 info->pcs_link_reg, info->mac_link_reg, info->pcs_err_cnt);
1394 void hinic_hilink_async_event_handle(struct hinic_hwdev *hwdev, u8 cmd,
1395 void *buf_in, u16 in_size,
1396 void *buf_out, u16 *out_size)
1404 case HINIC_HILINK_CMD_GET_LINK_INFO:
1405 hinic_print_hilink_info(buf_in, in_size, buf_out,
1410 PMD_DRV_LOG(ERR, "Unsupported event %d to process",