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 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 22 23 #define HINIC_FLR_TIMEOUT 1000 24 25 #define FFM_RECORD_NUM_MAX 32 26 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 32 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 38 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) 42 43 #define HINIC_DMA_ATTR_ENTRY_CLEAR(val, member) \ 44 ((val) & (~(HINIC_DMA_ATTR_ENTRY_##member##_MASK \ 45 << HINIC_DMA_ATTR_ENTRY_##member##_SHIFT))) 46 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 51 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 55 56 static const char *__hw_to_char_fec[HILINK_FEC_MAX_TYPE] = { 57 "RS-FEC", "BASE-FEC", "NO-FEC"}; 58 59 static const char *__hw_to_char_port_type[LINK_PORT_MAX_TYPE] = { 60 "Unknown", "Fibre", "Electric", "Direct Attach Copper", "AOC", 61 "Back plane", "BaseT" 62 }; 63 64 static const char *hinic_module_link_err[LINK_ERR_NUM] = { 65 "Unrecognized module", 66 }; 67 68 static void * 69 hinic_dma_mem_zalloc(struct hinic_hwdev *hwdev, size_t size, 70 dma_addr_t *dma_handle, unsigned int flag, unsigned int align) 71 { 72 int rc, alloc_cnt; 73 const struct rte_memzone *mz; 74 char z_name[RTE_MEMZONE_NAMESIZE]; 75 hash_sig_t sig; 76 rte_iova_t iova; 77 78 if (dma_handle == NULL || 0 == size) 79 return NULL; 80 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); 84 85 mz = rte_memzone_reserve_aligned(z_name, size, SOCKET_ID_ANY, 86 flag, align); 87 if (!mz) { 88 PMD_DRV_LOG(ERR, "Alloc dma able memory failed, errno: %d, ma_name: %s, size: 0x%zx", 89 rte_errno, z_name, size); 90 return NULL; 91 } 92 93 iova = mz->iova; 94 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, 99 &iova, sig); 100 if (rc >= 0) { 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; 104 } 105 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, 109 &iova, sig, 110 (void *)(u64)mz); 111 rte_spinlock_unlock(&hwdev->os_dep.dma_hash_lock); 112 if (rc) { 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; 116 } 117 *dma_handle = iova; 118 memset(mz->addr, 0, size); 119 120 return mz->addr; 121 122 phys_addr_hash_err: 123 (void)rte_memzone_free(mz); 124 125 return NULL; 126 } 127 128 static void 129 hinic_dma_mem_free(struct hinic_hwdev *hwdev, size_t size, 130 void *virt, dma_addr_t phys) 131 { 132 int rc; 133 struct rte_memzone *mz = NULL; 134 struct rte_hash *hash; 135 hash_sig_t sig; 136 137 if (virt == NULL || phys == 0) 138 return; 139 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); 144 if (rc < 0) { 145 PMD_DRV_LOG(ERR, "Can not find phys_addr: %p, error: %d", 146 (void *)phys, rc); 147 return; 148 } 149 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); 156 } 157 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); 161 162 (void)rte_memzone_free(mz); 163 } 164 165 void *dma_zalloc_coherent(void *hwdev, size_t size, 166 dma_addr_t *dma_handle, gfp_t flag) 167 { 168 return hinic_dma_mem_zalloc(hwdev, size, dma_handle, flag, 169 RTE_CACHE_LINE_SIZE); 170 } 171 172 void *dma_zalloc_coherent_aligned(void *hwdev, size_t size, 173 dma_addr_t *dma_handle, gfp_t flag) 174 { 175 return hinic_dma_mem_zalloc(hwdev, size, dma_handle, flag, 176 HINIC_PAGE_SIZE); 177 } 178 179 void *dma_zalloc_coherent_aligned256k(void *hwdev, size_t size, 180 dma_addr_t *dma_handle, gfp_t flag) 181 { 182 return hinic_dma_mem_zalloc(hwdev, size, dma_handle, flag, 183 HINIC_PAGE_SIZE * 64); 184 } 185 186 void dma_free_coherent(void *hwdev, size_t size, void *virt, dma_addr_t phys) 187 { 188 hinic_dma_mem_free(hwdev, size, virt, phys); 189 } 190 191 void dma_free_coherent_volatile(void *hwdev, size_t size, 192 volatile void *virt, dma_addr_t phys) 193 { 194 int rc; 195 struct rte_memzone *mz = NULL; 196 struct hinic_hwdev *dev = hwdev; 197 struct rte_hash *hash; 198 hash_sig_t sig; 199 200 if (virt == NULL || phys == 0) 201 return; 202 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); 207 if (rc < 0) { 208 PMD_DRV_LOG(ERR, "Can not find phys_addr: %p, error: %d", 209 (void *)phys, rc); 210 return; 211 } 212 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); 219 } 220 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); 224 225 (void)rte_memzone_free(mz); 226 } 227 228 struct dma_pool *dma_pool_create(const char *name, void *dev, 229 size_t size, size_t align, size_t boundary) 230 { 231 struct pci_pool *pool; 232 233 pool = rte_zmalloc(NULL, sizeof(*pool), HINIC_MEM_ALLOC_ALIGNE_MIN); 234 if (!pool) 235 return NULL; 236 237 pool->inuse = 0; 238 pool->elem_size = size; 239 pool->align = align; 240 pool->boundary = boundary; 241 pool->hwdev = dev; 242 strncpy(pool->name, name, (sizeof(pool->name) - 1)); 243 244 return pool; 245 } 246 247 void dma_pool_destroy(struct dma_pool *pool) 248 { 249 if (!pool) 250 return; 251 252 if (pool->inuse != 0) { 253 PMD_DRV_LOG(ERR, "Leak memory, dma_pool:%s, inuse_count:%u", 254 pool->name, pool->inuse); 255 } 256 257 rte_free(pool); 258 } 259 260 void *dma_pool_alloc(struct pci_pool *pool, int flags, dma_addr_t *dma_addr) 261 { 262 void *buf; 263 264 buf = hinic_dma_mem_zalloc(pool->hwdev, pool->elem_size, 265 dma_addr, flags, (u32)pool->align); 266 if (buf) 267 pool->inuse++; 268 269 return buf; 270 } 271 272 void dma_pool_free(struct pci_pool *pool, void *vaddr, dma_addr_t dma) 273 { 274 pool->inuse--; 275 hinic_dma_mem_free(pool->hwdev, pool->elem_size, vaddr, dma); 276 } 277 278 279 280 #define HINIC_MAX_DMA_ENTRIES 8192 281 int hinic_osdep_init(struct hinic_hwdev *hwdev) 282 { 283 struct rte_hash_parameters dh_params = { 0 }; 284 struct rte_hash *paddr_hash = NULL; 285 286 rte_atomic32_set(&hwdev->os_dep.dma_alloc_cnt, 0); 287 rte_spinlock_init(&hwdev->os_dep.dma_hash_lock); 288 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; 295 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"); 301 return -ENOMEM; 302 } 303 } else { 304 PMD_DRV_LOG(INFO, "Using existing dma hash table %s", 305 dh_params.name); 306 } 307 hwdev->os_dep.dma_addr_hash = paddr_hash; 308 309 return 0; 310 } 311 312 void hinic_osdep_deinit(struct hinic_hwdev *hwdev) 313 { 314 uint32_t iter = 0; 315 dma_addr_t key_pa; 316 struct rte_memzone *data_mz = NULL; 317 struct rte_hash *paddr_hash = hwdev->os_dep.dma_addr_hash; 318 319 if (paddr_hash) { 320 /* iterate through the hash table */ 321 while (rte_hash_iterate(paddr_hash, (const void **)&key_pa, 322 (void **)&data_mz, &iter) >= 0) { 323 if (data_mz) { 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); 327 } 328 } 329 330 /* free phys_addr hash table */ 331 rte_hash_free(paddr_hash); 332 } 333 } 334 335 336 337 338 339 340 341 342 343 344 345 346 347 /** 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 352 * @return 353 * 0 on success and ci attribute table is filled, 354 * negative error value otherwise. 355 **/ 356 int hinic_set_ci_table(void *hwdev, u16 q_id, struct hinic_sq_attr *attr) 357 { 358 struct hinic_cons_idx_attr cons_idx_attr; 359 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; 366 if (attr->intr_en) { 367 cons_idx_attr.intr_en = attr->intr_en; 368 cons_idx_attr.intr_idx = attr->intr_idx; 369 } 370 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; 374 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), 378 NULL, NULL, 0); 379 } 380 381 /** 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 385 * @return 386 * 0 on success, 387 * negative error value otherwise. 388 **/ 389 int hinic_set_pagesize(void *hwdev, u8 page_size) 390 { 391 struct hinic_page_size cmd; 392 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); 396 return -EINVAL; 397 } 398 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; 404 405 return hinic_msg_to_mgmt_sync(hwdev, HINIC_MOD_COMM, 406 HINIC_MGMT_CMD_PAGESIZE_SET, 407 &cmd, sizeof(cmd), 408 NULL, NULL, 0); 409 } 410 411 static int wait_for_flr_finish(struct hinic_hwif *hwif) 412 { 413 unsigned long end; 414 enum hinic_pf_status status; 415 416 end = jiffies + msecs_to_jiffies(HINIC_FLR_TIMEOUT); 417 do { 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); 421 return 0; 422 } 423 424 rte_delay_ms(10); 425 } while (time_before(jiffies, end)); 426 427 return -EFAULT; 428 } 429 430 #define HINIC_WAIT_CMDQ_IDLE_TIMEOUT 1000 431 432 static int wait_cmdq_stop(struct hinic_hwdev *hwdev) 433 { 434 enum hinic_cmdq_type cmdq_type; 435 struct hinic_cmdqs *cmdqs = hwdev->cmdqs; 436 unsigned long end; 437 int err = 0; 438 439 if (!(cmdqs->status & HINIC_CMDQ_ENABLE)) 440 return 0; 441 442 cmdqs->status &= ~HINIC_CMDQ_ENABLE; 443 444 end = jiffies + msecs_to_jiffies(HINIC_WAIT_CMDQ_IDLE_TIMEOUT); 445 do { 446 err = 0; 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])) { 450 err = -EBUSY; 451 break; 452 } 453 } 454 455 if (!err) 456 return 0; 457 458 rte_delay_ms(1); 459 } while (time_before(jiffies, end)); 460 461 cmdqs->status |= HINIC_CMDQ_ENABLE; 462 463 return err; 464 } 465 466 /** 467 * hinic_pf_rx_tx_flush - clean up hardware resource 468 * @hwdev: the hardware interface of a nic device 469 * @return 470 * 0 on success, 471 * negative error value otherwise. 472 **/ 473 static int hinic_pf_rx_tx_flush(struct hinic_hwdev *hwdev) 474 { 475 struct hinic_hwif *hwif = hwdev->hwif; 476 struct hinic_clear_doorbell clear_db; 477 struct hinic_clear_resource clr_res; 478 int err; 479 480 rte_delay_ms(100); 481 482 err = wait_cmdq_stop(hwdev); 483 if (err) { 484 PMD_DRV_LOG(ERR, "Cmdq is still working"); 485 return err; 486 } 487 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); 496 if (err) 497 PMD_DRV_LOG(WARNING, "Flush doorbell failed"); 498 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); 504 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); 508 if (err) 509 PMD_DRV_LOG(WARNING, "Notice flush message failed"); 510 511 err = wait_for_flr_finish(hwif); 512 if (err) 513 PMD_DRV_LOG(WARNING, "Wait firmware FLR timeout"); 514 515 hinic_enable_doorbell(hwif); 516 517 err = hinic_reinit_cmdq_ctxts(hwdev); 518 if (err) 519 PMD_DRV_LOG(WARNING, "Reinit cmdq failed"); 520 521 return 0; 522 } 523 524 int hinic_func_rx_tx_flush(struct hinic_hwdev *hwdev) 525 { 526 return hinic_pf_rx_tx_flush(hwdev); 527 } 528 529 /** 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. 534 **/ 535 static int hinic_get_interrupt_cfg(struct hinic_hwdev *hwdev, 536 struct nic_interrupt_info *interrupt_info) 537 { 538 struct hinic_msix_config msix_cfg; 539 u16 out_size = sizeof(msix_cfg); 540 int err; 541 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; 546 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); 554 return -EINVAL; 555 } 556 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; 562 return 0; 563 } 564 565 /** 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. 570 **/ 571 int hinic_set_interrupt_cfg(struct hinic_hwdev *hwdev, 572 struct nic_interrupt_info interrupt_info) 573 { 574 struct hinic_msix_config msix_cfg; 575 struct nic_interrupt_info temp_info; 576 u16 out_size = sizeof(msix_cfg); 577 int err; 578 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; 583 584 temp_info.msix_index = interrupt_info.msix_index; 585 586 err = hinic_get_interrupt_cfg(hwdev, &temp_info); 587 if (err) 588 return -EINVAL; 589 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; 595 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; 599 } 600 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; 605 } 606 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); 614 return -EINVAL; 615 } 616 617 return 0; 618 } 619 620 /** 621 * init_aeqs_msix_attr - Init interrupt attributes of aeq 622 * @hwdev: the hardware interface of a nic device 623 * @return 624 * 0 on success, 625 * negative error value otherwise. 626 **/ 627 int init_aeqs_msix_attr(void *hwdev) 628 { 629 struct hinic_hwdev *nic_hwdev = hwdev; 630 struct hinic_aeqs *aeqs = nic_hwdev->aeqs; 631 struct nic_interrupt_info info = {0}; 632 struct hinic_eq *eq; 633 u16 q_id; 634 int err; 635 636 info.lli_set = 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; 641 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); 646 if (err) { 647 PMD_DRV_LOG(ERR, "Set msix attr for aeq %d failed", 648 q_id); 649 return -EFAULT; 650 } 651 } 652 653 return 0; 654 } 655 656 /** 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 665 **/ 666 static void set_pf_dma_attr_entry(struct hinic_hwdev *hwdev, u32 entry_idx, 667 u8 st, u8 at, u8 ph, 668 enum hinic_pcie_nosnoop no_snooping, 669 enum hinic_pcie_tph tph_en) 670 { 671 u32 addr, val, dma_attr_entry; 672 673 /* Read Modify Write */ 674 addr = HINIC_CSR_DMA_ATTR_TBL_ADDR(entry_idx); 675 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); 682 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); 688 689 val |= dma_attr_entry; 690 hinic_hwif_write_reg(hwdev->hwif, addr, val); 691 } 692 693 /** 694 * dma_attr_table_init - initialize the the default dma attributes 695 * @hwdev: the pointer to the private hardware device object 696 **/ 697 static void dma_attr_table_init(struct hinic_hwdev *hwdev) 698 { 699 if (HINIC_IS_VF(hwdev)) 700 return; 701 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, 706 HINIC_PCIE_SNOOP, 707 HINIC_PCIE_TPH_DISABLE); 708 } 709 710 int hinic_init_attr_table(struct hinic_hwdev *hwdev) 711 { 712 dma_attr_table_init(hwdev); 713 714 return init_aeqs_msix_attr(hwdev); 715 } 716 717 #define FAULT_SHOW_STR_LEN 16 718 static void fault_report_show(struct hinic_hwdev *hwdev, 719 struct hinic_fault_event *event) 720 { 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 }; 728 u8 err_level; 729 730 PMD_DRV_LOG(WARNING, "Fault event report received, func_id: %d", 731 hinic_global_func_id(hwdev)); 732 733 if (event->type < FAULT_TYPE_MAX) 734 strncpy(type_str, fault_type[event->type], FAULT_SHOW_STR_LEN); 735 else 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]); 747 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], 753 FAULT_SHOW_STR_LEN); 754 else 755 strncpy(level_str, "unknown", 756 FAULT_SHOW_STR_LEN); 757 758 PMD_DRV_LOG(WARNING, "err_level: %d [%s]", 759 err_level, level_str); 760 761 if (err_level == FAULT_LEVEL_SERIOUS_FLR) { 762 PMD_DRV_LOG(WARNING, "flr func_id: %d", 763 event->event.chip.func_id); 764 } else { 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); 773 } 774 break; 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); 784 break; 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); 795 break; 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); 800 break; 801 default: 802 break; 803 } 804 } 805 806 static int resources_state_set(struct hinic_hwdev *hwdev, 807 enum hinic_res_state state) 808 { 809 struct hinic_hwif *hwif = hwdev->hwif; 810 struct hinic_cmd_set_res_state res_state; 811 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; 816 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); 820 } 821 822 /** 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 826 * @return 827 * 0 on success, 828 * negative error value otherwise. 829 **/ 830 int hinic_activate_hwdev_state(struct hinic_hwdev *hwdev) 831 { 832 int rc = HINIC_OK; 833 834 if (!hwdev) 835 return -EINVAL; 836 837 if (!HINIC_IS_VF(hwdev)) 838 hinic_set_pf_status(hwdev->hwif, 839 HINIC_PF_STATUS_ACTIVE_FLAG); 840 841 rc = resources_state_set(hwdev, HINIC_RES_ACTIVE); 842 if (rc) { 843 PMD_DRV_LOG(ERR, "Initialize resources state failed"); 844 return rc; 845 } 846 847 return 0; 848 } 849 850 /** 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 854 **/ 855 void hinic_deactivate_hwdev_state(struct hinic_hwdev *hwdev) 856 { 857 int rc = HINIC_OK; 858 859 if (!hwdev) 860 return; 861 862 rc = resources_state_set(hwdev, HINIC_RES_CLEAN); 863 if (rc) 864 PMD_DRV_LOG(ERR, "Deinit resources state failed"); 865 866 if (!HINIC_IS_VF(hwdev)) 867 hinic_set_pf_status(hwdev->hwif, HINIC_PF_STATUS_INIT); 868 } 869 870 int hinic_get_board_info(void *hwdev, struct hinic_board_info *info) 871 { 872 struct hinic_comm_board_info board_info; 873 u16 out_size = sizeof(board_info); 874 int err; 875 876 if (!hwdev || !info) 877 return -EINVAL; 878 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); 888 return -EFAULT; 889 } 890 891 memcpy(info, &board_info.info, sizeof(*info)); 892 return 0; 893 } 894 895 /** 896 * hinic_l2nic_reset - Restore the initial state of NIC 897 * @hwdev: the hardware interface of a nic device 898 * @return 899 * 0 on success, 900 * negative error value otherwise. 901 **/ 902 int hinic_l2nic_reset(struct hinic_hwdev *hwdev) 903 { 904 struct hinic_hwif *hwif = hwdev->hwif; 905 struct hinic_l2nic_reset l2nic_reset; 906 int err = 0; 907 908 err = hinic_set_vport_enable(hwdev, false); 909 if (err) { 910 PMD_DRV_LOG(ERR, "Set vport disable failed"); 911 return err; 912 } 913 914 rte_delay_ms(100); 915 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), 922 NULL, NULL, 0); 923 if (err || l2nic_reset.mgmt_msg_head.status) { 924 PMD_DRV_LOG(ERR, "Reset L2NIC resources failed"); 925 return -EFAULT; 926 } 927 928 return 0; 929 } 930 931 static void 932 hinic_show_sw_watchdog_timeout_info(void *buf_in, u16 in_size, 933 void *buf_out, u16 *out_size) 934 { 935 struct hinic_mgmt_watchdog_info *watchdog_info; 936 u32 *dump_addr, *reg, stack_len, i, j; 937 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)); 941 return; 942 } 943 944 watchdog_info = (struct hinic_mgmt_watchdog_info *)buf_in; 945 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); 953 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); 956 957 PMD_DRV_LOG(ERR, "Mgmt register info"); 958 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)); 963 } 964 965 PMD_DRV_LOG(ERR, "0x%08x", watchdog_info->reg[12]); 966 967 if (watchdog_info->stack_actlen <= 1024) { 968 stack_len = watchdog_info->stack_actlen; 969 } else { 970 PMD_DRV_LOG(ERR, "Oops stack length: 0x%x is wrong", 971 watchdog_info->stack_actlen); 972 stack_len = 1024; 973 } 974 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), 980 *(dump_addr + 3)); 981 } 982 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); 987 } 988 989 *out_size = sizeof(*watchdog_info); 990 watchdog_info = (struct hinic_mgmt_watchdog_info *)buf_out; 991 watchdog_info->mgmt_msg_head.status = 0; 992 } 993 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) 997 { 998 struct hinic_pcie_dfx_ntc *notice_info = 999 (struct hinic_pcie_dfx_ntc *)buf_in; 1000 struct hinic_pcie_dfx_info dfx_info; 1001 u16 size = 0; 1002 u16 cnt = 0; 1003 u32 num = 0; 1004 u32 i, j; 1005 int err; 1006 u32 *reg; 1007 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)); 1011 return; 1012 } 1013 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; 1024 if (i == (num - 1)) 1025 dfx_info.last = 1; 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); 1034 return; 1035 } 1036 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)]); 1044 cnt = cnt + 32; 1045 } 1046 memset(dfx_info.data, 0, MAX_PCIE_DFX_BUF_SIZE); 1047 } 1048 } 1049 1050 static void 1051 hinic_show_ffm_info(struct hinic_hwdev *hwdev, void *buf_in, u16 in_size) 1052 { 1053 struct ffm_intr_info *intr; 1054 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)); 1058 return; 1059 } 1060 1061 if (hwdev->ffm_num < FFM_RECORD_NUM_MAX) { 1062 hwdev->ffm_num++; 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)", 1065 intr->node_id, 1066 intr->err_csr_addr, 1067 intr->err_csr_value, 1068 intr->err_level, 1069 intr->err_type); 1070 } 1071 } 1072 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) 1076 { 1077 struct hinic_cmd_fault_event *fault_event, *ret_fault_event; 1078 1079 if (!hwdev) 1080 return; 1081 1082 *out_size = 0; 1083 1084 switch (cmd) { 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)); 1089 return; 1090 } 1091 1092 fault_event = (struct hinic_cmd_fault_event *)buf_in; 1093 fault_report_show(hwdev, &fault_event->event); 1094 1095 if (hinic_func_type(hwdev) != TYPE_VF) { 1096 ret_fault_event = 1097 (struct hinic_cmd_fault_event *)buf_out; 1098 ret_fault_event->mgmt_msg_head.status = 0; 1099 *out_size = sizeof(*ret_fault_event); 1100 } 1101 break; 1102 1103 case HINIC_MGMT_CMD_WATCHDOG_INFO: 1104 hinic_show_sw_watchdog_timeout_info(buf_in, in_size, 1105 buf_out, out_size); 1106 break; 1107 1108 case HINIC_MGMT_CMD_PCIE_DFX_NTC: 1109 hinic_show_pcie_dfx_info(hwdev, buf_in, in_size, 1110 buf_out, out_size); 1111 break; 1112 1113 case HINIC_MGMT_CMD_FFM_SET: 1114 hinic_show_ffm_info(hwdev, buf_in, in_size); 1115 break; 1116 1117 default: 1118 break; 1119 } 1120 } 1121 1122 static void 1123 hinic_cable_status_event(u8 cmd, void *buf_in, __rte_unused u16 in_size, 1124 void *buf_out, u16 *out_size) 1125 { 1126 struct hinic_cable_plug_event *plug_event; 1127 struct hinic_link_err_event *link_err; 1128 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"); 1133 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); 1142 } else { 1143 PMD_DRV_LOG(INFO, "Link failed, type: 0x%x: %s", 1144 link_err->err_type, 1145 hinic_module_link_err[link_err->err_type]); 1146 } 1147 1148 *out_size = sizeof(*link_err); 1149 link_err = (struct hinic_link_err_event *)buf_out; 1150 link_err->mgmt_msg_head.status = 0; 1151 } 1152 } 1153 1154 static int hinic_link_event_process(struct hinic_hwdev *hwdev, 1155 struct rte_eth_dev *eth_dev, u8 status) 1156 { 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; 1163 int rc = HINIC_OK; 1164 1165 if (!status) { 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; 1170 } else { 1171 link.link_status = ETH_LINK_UP; 1172 1173 memset(&port_info, 0, sizeof(port_info)); 1174 rc = hinic_get_port_info(hwdev, &port_info); 1175 if (rc) { 1176 link.link_speed = ETH_SPEED_NUM_NONE; 1177 link.link_duplex = ETH_LINK_FULL_DUPLEX; 1178 link.link_autoneg = ETH_LINK_FIXED; 1179 } else { 1180 link.link_speed = port_speed[port_info.speed % 1181 LINK_SPEED_MAX]; 1182 link.link_duplex = port_info.duplex; 1183 link.link_autoneg = port_info.autoneg_state; 1184 } 1185 } 1186 (void)rte_eth_linkstatus_set(eth_dev, &link); 1187 1188 return rc; 1189 } 1190 1191 static void hinic_lsc_process(struct hinic_hwdev *hwdev, 1192 struct rte_eth_dev *rte_dev, u8 status) 1193 { 1194 int ret; 1195 1196 ret = hinic_link_event_process(hwdev, rte_dev, status); 1197 /* check if link has changed, notify callback */ 1198 if (ret == 0) 1199 _rte_eth_dev_callback_process(rte_dev, 1200 RTE_ETH_EVENT_INTR_LSC, 1201 NULL); 1202 } 1203 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) 1208 { 1209 struct hinic_port_link_status *in_link; 1210 struct rte_eth_dev *eth_dev; 1211 1212 if (!hwdev) 1213 return; 1214 1215 *out_size = 0; 1216 1217 switch (cmd) { 1218 case HINIC_PORT_CMD_LINK_STATUS_REPORT: 1219 eth_dev = param; 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"); 1224 1225 hinic_lsc_process(hwdev, eth_dev, in_link->link); 1226 break; 1227 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, 1231 buf_out, out_size); 1232 break; 1233 1234 case HINIC_PORT_CMD_MGMT_RESET: 1235 PMD_DRV_LOG(WARNING, "Mgmt is reset"); 1236 break; 1237 1238 default: 1239 PMD_DRV_LOG(ERR, "Unsupported event %d to process", 1240 cmd); 1241 break; 1242 } 1243 } 1244 1245 static void print_cable_info(struct hinic_link_info *info) 1246 { 1247 char tmp_str[512] = {0}; 1248 char tmp_vendor[17] = {0}; 1249 const char *port_type = "Unknown port type"; 1250 int i; 1251 1252 if (info->cable_absent) { 1253 PMD_DRV_LOG(INFO, "Cable unpresent"); 1254 return; 1255 } 1256 1257 if (info->port_type < LINK_PORT_MAX_TYPE) 1258 port_type = __hw_to_char_port_type[info->port_type]; 1259 else 1260 PMD_DRV_LOG(INFO, "Unknown port type: %u", 1261 info->port_type); 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"; 1267 } 1268 1269 for (i = sizeof(info->vendor_name) - 1; i >= 0; i--) { 1270 if (info->vendor_name[i] == ' ') 1271 info->vendor_name[i] = '\0'; 1272 else 1273 break; 1274 } 1275 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, 1284 info->cable_temp); 1285 1286 PMD_DRV_LOG(INFO, "Cable information: %s", tmp_str); 1287 } 1288 1289 static void print_hi30_status(struct hinic_link_info *info) 1290 { 1291 struct hi30_ffe_data *ffe_data; 1292 struct hi30_ctle_data *ctle_data; 1293 1294 ffe_data = (struct hi30_ffe_data *)info->hi30_ffe; 1295 ctle_data = (struct hi30_ctle_data *)info->hi30_ctle; 1296 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]); 1314 } 1315 1316 static void print_link_info(struct hinic_link_info *info, 1317 enum hilink_info_print_event type) 1318 { 1319 const char *fec = "None"; 1320 1321 if (info->fec < HILINK_FEC_MAX_TYPE) 1322 fec = __hw_to_char_fec[info->fec]; 1323 else 1324 PMD_DRV_LOG(INFO, "Unknown fec type: %u", 1325 info->fec); 1326 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"); 1330 } else { 1331 PMD_DRV_LOG(INFO, "Link information: antoneg: %s", 1332 info->an_state ? "on" : "off"); 1333 } 1334 } 1335 1336 static const char *hilink_info_report_type[HILINK_EVENT_MAX_TYPE] = { 1337 "", "link up", "link down", "cable plugged" 1338 }; 1339 1340 static void hinic_print_hilink_info(void *buf_in, u16 in_size, 1341 void *buf_out, u16 *out_size) 1342 { 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; 1347 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)); 1351 return; 1352 } 1353 1354 ((struct hinic_hilink_link_info *)buf_out)->mgmt_msg_head.status = 0; 1355 *out_size = sizeof(*hilink_info); 1356 1357 info = &hilink_info->info; 1358 type = hilink_info->info_type; 1359 1360 if (type < HILINK_EVENT_LINK_UP || type >= HILINK_EVENT_MAX_TYPE) { 1361 PMD_DRV_LOG(INFO, "Invalid hilink info report, type: %d", 1362 type); 1363 return; 1364 } 1365 1366 PMD_DRV_LOG(INFO, "Hilink info report after %s", 1367 hilink_info_report_type[type]); 1368 1369 print_cable_info(info); 1370 1371 print_link_info(info, type); 1372 1373 print_hi30_status(info); 1374 1375 if (type == HILINK_EVENT_LINK_UP) 1376 return; 1377 1378 if (type == HILINK_EVENT_CABLE_PLUGGED) { 1379 PMD_DRV_LOG(INFO, "alos: %u, rx_los: %u", 1380 info->alos, info->rx_los); 1381 return; 1382 } 1383 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); 1392 } 1393 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) 1397 { 1398 if (!hwdev) 1399 return; 1400 1401 *out_size = 0; 1402 1403 switch (cmd) { 1404 case HINIC_HILINK_CMD_GET_LINK_INFO: 1405 hinic_print_hilink_info(buf_in, in_size, buf_out, 1406 out_size); 1407 break; 1408 1409 default: 1410 PMD_DRV_LOG(ERR, "Unsupported event %d to process", 1411 cmd); 1412 break; 1413 } 1414 } 1415