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