Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux
1
fork

Configure Feed

Select the types of activity you want to include in your feed.

Merge branch 'net-hinic3-pf-initialization'

Fan Gong says:

====================
net: hinic3: PF initialization

This is [2/3] part of hinic3 Ethernet driver second submission.
With this patch hinic3 becomes a complete Ethernet driver with
pf and vf.

Add cmdq detailed-response interfaces.
Add dump interfaces for cmdq, aeq, ceq and mailbox.
Add msg_send_lock for message sending concurrency.
Add PF device support and chip_present_flag to check cards.
Add rx vlan offload support.
Add PF FLR wait and timeout handling.
Add 5 ethtool ops for information of driver and link.

v1: https://lore.kernel.org/netdev/cover.1771916043.git.zhuyikai1@h-partners.com/
v2: https://lore.kernel.org/netdev/cover.1772697509.git.zhuyikai1@h-partners.com/
====================

Link: https://patch.msgid.link/cover.1773062356.git.zhuyikai1@h-partners.com
Signed-off-by: Paolo Abeni <pabeni@redhat.com>

+1146 -30
+1
drivers/net/ethernet/huawei/hinic3/Makefile
··· 6 6 hinic3-objs := hinic3_cmdq.o \ 7 7 hinic3_common.o \ 8 8 hinic3_eqs.o \ 9 + hinic3_ethtool.o \ 9 10 hinic3_filter.o \ 10 11 hinic3_hw_cfg.o \ 11 12 hinic3_hw_comm.o \
+182 -13
drivers/net/ethernet/huawei/hinic3/hinic3_cmdq.c
··· 6 6 #include <linux/dma-mapping.h> 7 7 8 8 #include "hinic3_cmdq.h" 9 + #include "hinic3_eqs.h" 9 10 #include "hinic3_hwdev.h" 10 11 #include "hinic3_hwif.h" 11 12 #include "hinic3_mbox.h" 12 13 13 14 #define CMDQ_BUF_SIZE 2048 14 15 #define CMDQ_WQEBB_SIZE 64 16 + #define CMDQ_WQE_HEAD_LEN 32 15 17 16 18 #define CMDQ_CMD_TIMEOUT 5000 17 19 #define CMDQ_ENABLE_WAIT_TIMEOUT 300 ··· 63 61 #define CMDQ_DB_HEAD_SET(val, member) \ 64 62 FIELD_PREP(CMDQ_DB_HEAD_##member##_MASK, val) 65 63 64 + #define SAVED_DATA_ARM_MASK BIT(31) 65 + #define SAVED_DATA_SET(val, member) \ 66 + FIELD_PREP(SAVED_DATA_##member##_MASK, val) 67 + 66 68 #define CMDQ_CEQE_TYPE_MASK GENMASK(2, 0) 67 69 #define CMDQ_CEQE_GET(val, member) \ 68 70 FIELD_GET(CMDQ_CEQE_##member##_MASK, le32_to_cpu(val)) ··· 90 84 CMDQ_DATA_DIRECT = 1, 91 85 }; 92 86 87 + enum cmdq_scmd_type { 88 + CMDQ_SET_ARM_CMD = 2, 89 + }; 90 + 93 91 enum cmdq_ctrl_sect_len { 94 92 CMDQ_CTRL_SECT_LEN = 1, 95 93 CMDQ_CTRL_DIRECT_SECT_LEN = 2, ··· 115 105 }; 116 106 117 107 #define CMDQ_WQE_NUM_WQEBBS 1 108 + 109 + static void hinic3_dump_cmdq_wqe_head(struct hinic3_hwdev *hwdev, 110 + struct cmdq_wqe *wqe) 111 + { 112 + u32 *data = (u32 *)wqe; 113 + u32 i; 114 + 115 + for (i = 0; i < (CMDQ_WQE_HEAD_LEN / sizeof(u32)); i += 0x4) { 116 + dev_dbg(hwdev->dev, 117 + "wqe data: 0x%08x, 0x%08x, 0x%08x, 0x%08x\n", 118 + *(data + i), *(data + i + 0x1), *(data + i + 0x2), 119 + *(data + i + 0x3)); 120 + } 121 + } 118 122 119 123 static struct cmdq_wqe *cmdq_read_wqe(struct hinic3_wq *wq, u16 *ci) 120 124 { ··· 190 166 hinic3_free_cmd_buf(hwdev, cmd_info->buf_in); 191 167 cmd_info->buf_in = NULL; 192 168 } 169 + 170 + if (cmd_info->buf_out) { 171 + hinic3_free_cmd_buf(hwdev, cmd_info->buf_out); 172 + cmd_info->buf_out = NULL; 173 + } 193 174 } 194 175 195 176 static void clear_wqe_complete_bit(struct hinic3_cmdq *cmdq, ··· 216 187 cmdq->cmd_infos[ci].cmd_type = HINIC3_CMD_TYPE_NONE; 217 188 wmb(); /* verify wqe is clear before updating ci */ 218 189 hinic3_wq_put_wqebbs(&cmdq->wq, CMDQ_WQE_NUM_WQEBBS); 190 + } 191 + 192 + static int cmdq_arm_ceq_handler(struct hinic3_cmdq *cmdq, 193 + struct cmdq_wqe *wqe, u16 ci) 194 + { 195 + struct cmdq_ctrl *ctrl = &wqe->wqe_scmd.ctrl; 196 + __le32 ctrl_info = ctrl->ctrl_info; 197 + 198 + if (!CMDQ_WQE_COMPLETED(ctrl_info)) 199 + return -EBUSY; 200 + 201 + clear_wqe_complete_bit(cmdq, wqe, ci); 202 + 203 + return 0; 219 204 } 220 205 221 206 static void cmdq_update_cmd_status(struct hinic3_cmdq *cmdq, u16 prod_idx, ··· 295 252 case HINIC3_CMD_TYPE_TIMEOUT: 296 253 dev_warn(hwdev->dev, "Cmdq timeout, q_id: %u, ci: %u\n", 297 254 cmdq_type, ci); 255 + hinic3_dump_cmdq_wqe_head(hwdev, wqe); 298 256 fallthrough; 299 257 case HINIC3_CMD_TYPE_FAKE_TIMEOUT: 300 258 cmdq_clear_cmd_buf(cmd_info, hwdev); 301 259 clear_wqe_complete_bit(cmdq, wqe, ci); 260 + break; 261 + case HINIC3_CMD_TYPE_SET_ARM: 262 + /* arm_bit was set until here */ 263 + if (cmdq_arm_ceq_handler(cmdq, wqe, ci)) 264 + return; 302 265 break; 303 266 default: 304 267 /* only arm bit is using scmd wqe, ··· 332 283 } 333 284 } 334 285 286 + static int cmdq_params_valid(const struct hinic3_hwdev *hwdev, 287 + const struct hinic3_cmd_buf *buf_in) 288 + { 289 + if (le16_to_cpu(buf_in->size) > CMDQ_BUF_SIZE) { 290 + dev_err(hwdev->dev, "Invalid CMDQ buffer size: 0x%x\n", 291 + le16_to_cpu(buf_in->size)); 292 + return -EINVAL; 293 + } 294 + 295 + return 0; 296 + } 297 + 335 298 static int wait_cmdqs_enable(struct hinic3_cmdqs *cmdqs) 336 299 { 337 300 unsigned long end; ··· 353 292 if (cmdqs->status & HINIC3_CMDQ_ENABLE) 354 293 return 0; 355 294 usleep_range(1000, 2000); 356 - } while (time_before(jiffies, end) && !cmdqs->disable_flag); 295 + } while (time_before(jiffies, end) && !cmdqs->disable_flag && 296 + cmdqs->hwdev->chip_present_flag); 357 297 358 298 cmdqs->disable_flag = 1; 359 299 ··· 418 356 enum cmdq_bufdesc_len buf_len) 419 357 { 420 358 struct cmdq_header *hdr = CMDQ_WQE_HEADER(wqe); 359 + __le32 saved_data = hdr->saved_data; 421 360 enum cmdq_ctrl_sect_len ctrl_len; 422 361 struct cmdq_wqe_lcmd *wqe_lcmd; 423 362 struct cmdq_wqe_scmd *wqe_scmd; ··· 449 386 CMDQ_WQE_HDR_SET(3, COMPLETE_SECT_LEN) | 450 387 CMDQ_WQE_HDR_SET(ctrl_len, CTRL_LEN) | 451 388 CMDQ_WQE_HDR_SET(wrapped, HW_BUSY_BIT)); 389 + 390 + saved_data &= ~cpu_to_le32(SAVED_DATA_ARM_MASK); 391 + if (cmd == CMDQ_SET_ARM_CMD && mod == MGMT_MOD_COMM) 392 + saved_data |= cpu_to_le32(SAVED_DATA_SET(1, ARM)); 393 + hdr->saved_data = saved_data; 452 394 } 453 395 454 396 static void cmdq_set_lcmd_wqe(struct cmdq_wqe *wqe, ··· 553 485 clear_cmd_info(cmd_info, saved_cmd_info); 554 486 spin_unlock_bh(&cmdq->cmdq_lock); 555 487 488 + hinic3_dump_ceq_info(cmdq->hwdev); 489 + 556 490 return err; 557 491 } 558 492 559 - static int cmdq_sync_cmd_direct_resp(struct hinic3_cmdq *cmdq, u8 mod, u8 cmd, 560 - struct hinic3_cmd_buf *buf_in, 561 - __le64 *out_param) 493 + static int cmdq_sync_cmd_exec(struct hinic3_cmdq *cmdq, u8 mod, u8 cmd, 494 + struct hinic3_cmd_buf *buf_in, 495 + struct hinic3_cmd_buf *buf_out, 496 + __le64 *out_param, u8 cmd_type, u8 wqe_cmd) 562 497 { 563 498 struct hinic3_cmdq_cmd_info *cmd_info, saved_cmd_info; 564 499 int cmpt_code = CMDQ_SEND_CMPT_CODE; ··· 591 520 cmd_info = &cmdq->cmd_infos[curr_prod_idx]; 592 521 init_completion(&done); 593 522 refcount_inc(&buf_in->ref_cnt); 594 - cmd_info->cmd_type = HINIC3_CMD_TYPE_DIRECT_RESP; 523 + if (buf_out) 524 + refcount_inc(&buf_out->ref_cnt); 525 + 526 + cmd_info->cmd_type = cmd_type; 595 527 cmd_info->done = &done; 596 528 cmd_info->errcode = &errcode; 597 529 cmd_info->direct_resp = out_param; 598 530 cmd_info->cmpt_code = &cmpt_code; 599 531 cmd_info->buf_in = buf_in; 532 + if (buf_out) 533 + cmd_info->buf_out = buf_out; 534 + 600 535 saved_cmd_info = *cmd_info; 601 - cmdq_set_lcmd_wqe(&wqe, CMDQ_CMD_DIRECT_RESP, buf_in, NULL, 536 + cmdq_set_lcmd_wqe(&wqe, wqe_cmd, buf_in, buf_out, 602 537 wrapped, mod, cmd, curr_prod_idx); 603 538 604 539 cmdq_wqe_fill(curr_wqe, &wqe); 605 540 (cmd_info->cmdq_msg_id)++; 606 541 curr_msg_id = cmd_info->cmdq_msg_id; 607 - cmdq_set_db(cmdq, HINIC3_CMDQ_SYNC, next_prod_idx); 542 + cmdq_set_db(cmdq, cmdq->cmdq_type, next_prod_idx); 608 543 spin_unlock_bh(&cmdq->cmdq_lock); 609 544 610 545 err = wait_cmdq_sync_cmd_completion(cmdq, cmd_info, &saved_cmd_info, 611 546 curr_msg_id, curr_prod_idx, 612 547 curr_wqe, CMDQ_CMD_TIMEOUT); 613 - if (err) { 548 + if (err) 614 549 dev_err(cmdq->hwdev->dev, 615 550 "Cmdq sync command timeout, mod: %u, cmd: %u, prod idx: 0x%x\n", 616 551 mod, cmd, curr_prod_idx); 617 - err = -ETIMEDOUT; 618 - } 619 552 620 553 if (cmpt_code == CMDQ_FORCE_STOP_CMPT_CODE) { 621 554 dev_dbg(cmdq->hwdev->dev, ··· 632 557 return err ? err : errcode; 633 558 } 634 559 560 + static int cmdq_sync_cmd_direct_resp(struct hinic3_cmdq *cmdq, u8 mod, u8 cmd, 561 + struct hinic3_cmd_buf *buf_in, 562 + __le64 *out_param) 563 + { 564 + return cmdq_sync_cmd_exec(cmdq, mod, cmd, buf_in, NULL, out_param, 565 + HINIC3_CMD_TYPE_DIRECT_RESP, 566 + CMDQ_CMD_DIRECT_RESP); 567 + } 568 + 569 + static int cmdq_sync_cmd_detail_resp(struct hinic3_cmdq *cmdq, u8 mod, u8 cmd, 570 + struct hinic3_cmd_buf *buf_in, 571 + struct hinic3_cmd_buf *buf_out, 572 + __le64 *out_param) 573 + { 574 + return cmdq_sync_cmd_exec(cmdq, mod, cmd, buf_in, buf_out, out_param, 575 + HINIC3_CMD_TYPE_SGE_RESP, 576 + CMDQ_CMD_SGE_RESP); 577 + } 578 + 579 + int hinic3_cmd_buf_pair_init(struct hinic3_hwdev *hwdev, 580 + struct hinic3_cmd_buf_pair *pair) 581 + { 582 + pair->in = hinic3_alloc_cmd_buf(hwdev); 583 + if (!pair->in) 584 + goto err_out; 585 + 586 + pair->out = hinic3_alloc_cmd_buf(hwdev); 587 + if (!pair->out) 588 + goto err_free_cmd_buf_in; 589 + 590 + return 0; 591 + 592 + err_free_cmd_buf_in: 593 + hinic3_free_cmd_buf(hwdev, pair->in); 594 + err_out: 595 + return -ENOMEM; 596 + } 597 + 598 + void hinic3_cmd_buf_pair_uninit(struct hinic3_hwdev *hwdev, 599 + struct hinic3_cmd_buf_pair *pair) 600 + { 601 + hinic3_free_cmd_buf(hwdev, pair->in); 602 + hinic3_free_cmd_buf(hwdev, pair->out); 603 + } 604 + 635 605 int hinic3_cmdq_direct_resp(struct hinic3_hwdev *hwdev, u8 mod, u8 cmd, 636 606 struct hinic3_cmd_buf *buf_in, __le64 *out_param) 637 607 { 638 608 struct hinic3_cmdqs *cmdqs; 639 609 int err; 640 610 611 + if (!hwdev->chip_present_flag) 612 + return -ETIMEDOUT; 613 + 614 + err = cmdq_params_valid(hwdev, buf_in); 615 + if (err) { 616 + dev_err(hwdev->dev, "Invalid CMDQ parameters\n"); 617 + goto err_out; 618 + } 619 + 641 620 cmdqs = hwdev->cmdqs; 642 621 err = wait_cmdqs_enable(cmdqs); 643 622 if (err) { 644 623 dev_err(hwdev->dev, "Cmdq is disabled\n"); 645 - return err; 624 + goto err_out; 646 625 } 647 626 648 627 err = cmdq_sync_cmd_direct_resp(&cmdqs->cmdq[HINIC3_CMDQ_SYNC], 649 628 mod, cmd, buf_in, out_param); 629 + if (err) 630 + goto err_out; 650 631 632 + return 0; 633 + 634 + err_out: 635 + return err; 636 + } 637 + 638 + int hinic3_cmdq_detail_resp(struct hinic3_hwdev *hwdev, u8 mod, u8 cmd, 639 + struct hinic3_cmd_buf *buf_in, 640 + struct hinic3_cmd_buf *buf_out, __le64 *out_param) 641 + { 642 + struct hinic3_cmdqs *cmdqs; 643 + int err; 644 + 645 + if (!hwdev->chip_present_flag) 646 + return -ETIMEDOUT; 647 + 648 + err = cmdq_params_valid(hwdev, buf_in); 649 + if (err) 650 + goto err_out; 651 + 652 + cmdqs = hwdev->cmdqs; 653 + 654 + err = wait_cmdqs_enable(cmdqs); 655 + if (err) { 656 + dev_err(hwdev->dev, "Cmdq is disabled\n"); 657 + goto err_out; 658 + } 659 + 660 + err = cmdq_sync_cmd_detail_resp(&cmdqs->cmdq[HINIC3_CMDQ_SYNC], 661 + mod, cmd, buf_in, buf_out, out_param); 662 + if (err) 663 + goto err_out; 664 + 665 + return 0; 666 + 667 + err_out: 651 668 return err; 652 669 } 653 670 ··· 925 758 926 759 static void cmdq_flush_sync_cmd(struct hinic3_cmdq_cmd_info *cmd_info) 927 760 { 928 - if (cmd_info->cmd_type != HINIC3_CMD_TYPE_DIRECT_RESP) 761 + if (cmd_info->cmd_type != HINIC3_CMD_TYPE_DIRECT_RESP && 762 + cmd_info->cmd_type != HINIC3_CMD_TYPE_SGE_RESP) 929 763 return; 930 764 931 765 cmd_info->cmd_type = HINIC3_CMD_TYPE_FORCE_STOP; ··· 953 785 while (cmdq_read_wqe(&cmdq->wq, &ci)) { 954 786 hinic3_wq_put_wqebbs(&cmdq->wq, CMDQ_WQE_NUM_WQEBBS); 955 787 cmd_info = &cmdq->cmd_infos[ci]; 956 - if (cmd_info->cmd_type == HINIC3_CMD_TYPE_DIRECT_RESP) 788 + if (cmd_info->cmd_type == HINIC3_CMD_TYPE_DIRECT_RESP || 789 + cmd_info->cmd_type == HINIC3_CMD_TYPE_SGE_RESP) 957 790 cmdq_flush_sync_cmd(cmd_info); 958 791 } 959 792 spin_unlock_bh(&cmdq->cmdq_lock);
+15
drivers/net/ethernet/huawei/hinic3/hinic3_cmdq.h
··· 85 85 86 86 enum hinic3_cmdq_cmd_type { 87 87 HINIC3_CMD_TYPE_NONE, 88 + HINIC3_CMD_TYPE_SET_ARM, 88 89 HINIC3_CMD_TYPE_DIRECT_RESP, 90 + HINIC3_CMD_TYPE_SGE_RESP, 89 91 HINIC3_CMD_TYPE_FAKE_TIMEOUT, 90 92 HINIC3_CMD_TYPE_TIMEOUT, 91 93 HINIC3_CMD_TYPE_FORCE_STOP, ··· 100 98 refcount_t ref_cnt; 101 99 }; 102 100 101 + struct hinic3_cmd_buf_pair { 102 + struct hinic3_cmd_buf *in; 103 + struct hinic3_cmd_buf *out; 104 + }; 105 + 103 106 struct hinic3_cmdq_cmd_info { 104 107 enum hinic3_cmdq_cmd_type cmd_type; 105 108 struct completion *done; ··· 114 107 __le64 *direct_resp; 115 108 u64 cmdq_msg_id; 116 109 struct hinic3_cmd_buf *buf_in; 110 + struct hinic3_cmd_buf *buf_out; 117 111 }; 118 112 119 113 struct hinic3_cmdq { ··· 154 146 struct hinic3_cmd_buf *cmd_buf); 155 147 void hinic3_cmdq_ceq_handler(struct hinic3_hwdev *hwdev, __le32 ceqe_data); 156 148 149 + int hinic3_cmd_buf_pair_init(struct hinic3_hwdev *hwdev, 150 + struct hinic3_cmd_buf_pair *pair); 151 + void hinic3_cmd_buf_pair_uninit(struct hinic3_hwdev *hwdev, 152 + struct hinic3_cmd_buf_pair *pair); 157 153 int hinic3_cmdq_direct_resp(struct hinic3_hwdev *hwdev, u8 mod, u8 cmd, 158 154 struct hinic3_cmd_buf *buf_in, __le64 *out_param); 155 + int hinic3_cmdq_detail_resp(struct hinic3_hwdev *hwdev, u8 mod, u8 cmd, 156 + struct hinic3_cmd_buf *buf_in, 157 + struct hinic3_cmd_buf *buf_out, __le64 *out_param); 159 158 160 159 void hinic3_cmdq_flush_sync_cmd(struct hinic3_hwdev *hwdev); 161 160 int hinic3_reinit_cmdq_ctxts(struct hinic3_hwdev *hwdev);
+5 -1
drivers/net/ethernet/huawei/hinic3/hinic3_common.c
··· 59 59 enum hinic3_wait_return ret; 60 60 int err; 61 61 62 - err = read_poll_timeout(handler, ret, ret == HINIC3_WAIT_PROCESS_CPL, 62 + err = read_poll_timeout(handler, ret, 63 + !(ret & HINIC3_WAIT_PROCESS_WAITING), 63 64 wait_once_us, wait_total_ms * USEC_PER_MSEC, 64 65 false, priv_data); 66 + 67 + if (ret == HINIC3_WAIT_PROCESS_ERR) 68 + return -EIO; 65 69 66 70 return err; 67 71 }
+1
drivers/net/ethernet/huawei/hinic3/hinic3_common.h
··· 21 21 enum hinic3_wait_return { 22 22 HINIC3_WAIT_PROCESS_CPL = 0, 23 23 HINIC3_WAIT_PROCESS_WAITING = 1, 24 + HINIC3_WAIT_PROCESS_ERR = 2, 24 25 }; 25 26 26 27 struct hinic3_sge {
+2
drivers/net/ethernet/huawei/hinic3/hinic3_csr.h
··· 76 76 77 77 #define HINIC3_CSR_AEQ_CTRL_0_ADDR (HINIC3_CFG_REGS_FLAG + 0x200) 78 78 #define HINIC3_CSR_AEQ_CTRL_1_ADDR (HINIC3_CFG_REGS_FLAG + 0x204) 79 + #define HINIC3_CSR_AEQ_CONS_IDX_ADDR (HINIC3_CFG_REGS_FLAG + 0x208) 79 80 #define HINIC3_CSR_AEQ_PROD_IDX_ADDR (HINIC3_CFG_REGS_FLAG + 0x20C) 80 81 #define HINIC3_CSR_AEQ_CI_SIMPLE_INDIR_ADDR (HINIC3_CFG_REGS_FLAG + 0x50) 81 82 83 + #define HINIC3_CSR_CEQ_CONS_IDX_ADDR (HINIC3_CFG_REGS_FLAG + 0x288) 82 84 #define HINIC3_CSR_CEQ_PROD_IDX_ADDR (HINIC3_CFG_REGS_FLAG + 0x28c) 83 85 #define HINIC3_CSR_CEQ_CI_SIMPLE_INDIR_ADDR (HINIC3_CFG_REGS_FLAG + 0x54) 84 86
+65
drivers/net/ethernet/huawei/hinic3/hinic3_eqs.c
··· 56 56 #define EQ_CI_SIMPLE_INDIR_SET(val, member) \ 57 57 FIELD_PREP(EQ_CI_SIMPLE_INDIR_##member##_MASK, val) 58 58 59 + #define EQ_CONS_IDX_REG_ADDR(eq) \ 60 + (((eq)->type == HINIC3_AEQ) ? \ 61 + HINIC3_CSR_AEQ_CONS_IDX_ADDR : HINIC3_CSR_CEQ_CONS_IDX_ADDR) 62 + 59 63 #define EQ_CI_SIMPLE_INDIR_REG_ADDR(eq) \ 60 64 (((eq)->type == HINIC3_AEQ) ? \ 61 65 HINIC3_CSR_AEQ_CI_SIMPLE_INDIR_ADDR : \ ··· 357 353 struct hinic3_eq *ceq = data; 358 354 int err; 359 355 356 + ceq->soft_intr_jif = jiffies; 360 357 /* clear resend timer counters */ 361 358 hinic3_msix_intr_clear_resend_bit(ceq->hwdev, ceq->msix_entry_idx, 362 359 EQ_MSIX_RESEND_TIMER_CLEAR); ··· 718 713 kfree(aeqs); 719 714 } 720 715 716 + void hinic3_dump_aeq_info(struct hinic3_hwdev *hwdev) 717 + { 718 + const struct hinic3_aeq_elem *aeqe_pos; 719 + u32 addr, ci, pi, ctrl0, idx; 720 + struct hinic3_eq *eq; 721 + int q_id; 722 + 723 + for (q_id = 0; q_id < hwdev->aeqs->num_aeqs; q_id++) { 724 + eq = &hwdev->aeqs->aeq[q_id]; 725 + /* Indirect access should set q_id first */ 726 + hinic3_hwif_write_reg(eq->hwdev->hwif, 727 + HINIC3_EQ_INDIR_IDX_ADDR(eq->type), 728 + eq->q_id); 729 + 730 + addr = HINIC3_CSR_AEQ_CTRL_0_ADDR; 731 + 732 + ctrl0 = hinic3_hwif_read_reg(hwdev->hwif, addr); 733 + 734 + idx = hinic3_hwif_read_reg(hwdev->hwif, 735 + HINIC3_EQ_INDIR_IDX_ADDR(eq->type)); 736 + 737 + addr = EQ_CONS_IDX_REG_ADDR(eq); 738 + ci = hinic3_hwif_read_reg(hwdev->hwif, addr); 739 + addr = EQ_PROD_IDX_REG_ADDR(eq); 740 + pi = hinic3_hwif_read_reg(hwdev->hwif, addr); 741 + aeqe_pos = get_curr_aeq_elem(eq); 742 + dev_err(hwdev->dev, 743 + "Aeq id: %d, idx: %u, ctrl0: 0x%08x, ci: 0x%08x, pi: 0x%x, work_state: 0x%x, wrap: %u, desc: 0x%x swci:0x%x\n", 744 + q_id, idx, ctrl0, ci, pi, work_busy(&eq->aeq_work), 745 + eq->wrapped, be32_to_cpu(aeqe_pos->desc), eq->cons_idx); 746 + } 747 + } 748 + 721 749 int hinic3_ceqs_init(struct hinic3_hwdev *hwdev, u16 num_ceqs, 722 750 struct msix_entry *msix_entries) 723 751 { ··· 810 772 hinic3_ceq_unregister_cb(hwdev, ceq_event); 811 773 812 774 kfree(ceqs); 775 + } 776 + 777 + void hinic3_dump_ceq_info(struct hinic3_hwdev *hwdev) 778 + { 779 + struct hinic3_eq *eq; 780 + u32 addr, ci, pi; 781 + int q_id; 782 + 783 + for (q_id = 0; q_id < hwdev->ceqs->num_ceqs; q_id++) { 784 + eq = &hwdev->ceqs->ceq[q_id]; 785 + /* Indirect access should set q_id first */ 786 + hinic3_hwif_write_reg(eq->hwdev->hwif, 787 + HINIC3_EQ_INDIR_IDX_ADDR(eq->type), 788 + eq->q_id); 789 + 790 + addr = EQ_CONS_IDX_REG_ADDR(eq); 791 + ci = hinic3_hwif_read_reg(hwdev->hwif, addr); 792 + addr = EQ_PROD_IDX_REG_ADDR(eq); 793 + pi = hinic3_hwif_read_reg(hwdev->hwif, addr); 794 + dev_err(hwdev->dev, 795 + "Ceq id: %d, ci: 0x%08x, sw_ci: 0x%08x, pi: 0x%x, wrap: %u, ceqe: 0x%x\n", 796 + q_id, ci, eq->cons_idx, pi, 797 + eq->wrapped, be32_to_cpu(*get_curr_ceq_elem(eq))); 798 + 799 + dev_err(hwdev->dev, "Ceq last response soft interrupt time: %u\n", 800 + jiffies_to_msecs(jiffies - eq->soft_intr_jif)); 801 + } 813 802 }
+5
drivers/net/ethernet/huawei/hinic3/hinic3_eqs.h
··· 56 56 u16 msix_entry_idx; 57 57 char irq_name[HINIC3_EQ_IRQ_NAME_LEN]; 58 58 struct work_struct aeq_work; 59 + 60 + u64 soft_intr_jif; 59 61 }; 60 62 61 63 struct hinic3_aeq_elem { ··· 112 110 hinic3_aeq_event_cb hwe_cb); 113 111 void hinic3_aeq_unregister_cb(struct hinic3_hwdev *hwdev, 114 112 enum hinic3_aeq_type event); 113 + void hinic3_dump_aeq_info(struct hinic3_hwdev *hwdev); 114 + 115 115 int hinic3_ceqs_init(struct hinic3_hwdev *hwdev, u16 num_ceqs, 116 116 struct msix_entry *msix_entries); 117 117 void hinic3_ceqs_free(struct hinic3_hwdev *hwdev); ··· 122 118 hinic3_ceq_event_cb callback); 123 119 void hinic3_ceq_unregister_cb(struct hinic3_hwdev *hwdev, 124 120 enum hinic3_ceq_event event); 121 + void hinic3_dump_ceq_info(struct hinic3_hwdev *hwdev); 125 122 126 123 #endif
+425
drivers/net/ethernet/huawei/hinic3/hinic3_ethtool.c
··· 1 + // SPDX-License-Identifier: GPL-2.0 2 + // Copyright (c) Huawei Technologies Co., Ltd. 2026. All rights reserved. 3 + 4 + #include <linux/kernel.h> 5 + #include <linux/pci.h> 6 + #include <linux/device.h> 7 + #include <linux/module.h> 8 + #include <linux/types.h> 9 + #include <linux/errno.h> 10 + #include <linux/etherdevice.h> 11 + #include <linux/netdevice.h> 12 + #include <linux/ethtool.h> 13 + 14 + #include "hinic3_lld.h" 15 + #include "hinic3_hw_comm.h" 16 + #include "hinic3_nic_dev.h" 17 + #include "hinic3_nic_cfg.h" 18 + 19 + #define HINIC3_MGMT_VERSION_MAX_LEN 32 20 + 21 + static void hinic3_get_drvinfo(struct net_device *netdev, 22 + struct ethtool_drvinfo *info) 23 + { 24 + struct hinic3_nic_dev *nic_dev = netdev_priv(netdev); 25 + u8 mgmt_ver[HINIC3_MGMT_VERSION_MAX_LEN]; 26 + struct pci_dev *pdev = nic_dev->pdev; 27 + int err; 28 + 29 + strscpy(info->driver, HINIC3_NIC_DRV_NAME, sizeof(info->driver)); 30 + strscpy(info->bus_info, pci_name(pdev), sizeof(info->bus_info)); 31 + 32 + err = hinic3_get_mgmt_version(nic_dev->hwdev, mgmt_ver, 33 + HINIC3_MGMT_VERSION_MAX_LEN); 34 + if (err) { 35 + netdev_err(netdev, "Failed to get fw version\n"); 36 + return; 37 + } 38 + 39 + snprintf(info->fw_version, sizeof(info->fw_version), "%s", mgmt_ver); 40 + } 41 + 42 + static u32 hinic3_get_msglevel(struct net_device *netdev) 43 + { 44 + struct hinic3_nic_dev *nic_dev = netdev_priv(netdev); 45 + 46 + return nic_dev->msg_enable; 47 + } 48 + 49 + static void hinic3_set_msglevel(struct net_device *netdev, u32 data) 50 + { 51 + struct hinic3_nic_dev *nic_dev = netdev_priv(netdev); 52 + 53 + nic_dev->msg_enable = data; 54 + 55 + netdev_dbg(netdev, "Set message level: 0x%x\n", data); 56 + } 57 + 58 + static const u32 hinic3_link_mode_ge[] = { 59 + ETHTOOL_LINK_MODE_1000baseT_Full_BIT, 60 + ETHTOOL_LINK_MODE_1000baseKX_Full_BIT, 61 + ETHTOOL_LINK_MODE_1000baseX_Full_BIT, 62 + }; 63 + 64 + static const u32 hinic3_link_mode_10ge_base_r[] = { 65 + ETHTOOL_LINK_MODE_10000baseKR_Full_BIT, 66 + ETHTOOL_LINK_MODE_10000baseR_FEC_BIT, 67 + ETHTOOL_LINK_MODE_10000baseCR_Full_BIT, 68 + ETHTOOL_LINK_MODE_10000baseSR_Full_BIT, 69 + ETHTOOL_LINK_MODE_10000baseLR_Full_BIT, 70 + ETHTOOL_LINK_MODE_10000baseLRM_Full_BIT, 71 + }; 72 + 73 + static const u32 hinic3_link_mode_25ge_base_r[] = { 74 + ETHTOOL_LINK_MODE_25000baseCR_Full_BIT, 75 + ETHTOOL_LINK_MODE_25000baseKR_Full_BIT, 76 + ETHTOOL_LINK_MODE_25000baseSR_Full_BIT, 77 + }; 78 + 79 + static const u32 hinic3_link_mode_40ge_base_r4[] = { 80 + ETHTOOL_LINK_MODE_40000baseKR4_Full_BIT, 81 + ETHTOOL_LINK_MODE_40000baseCR4_Full_BIT, 82 + ETHTOOL_LINK_MODE_40000baseSR4_Full_BIT, 83 + ETHTOOL_LINK_MODE_40000baseLR4_Full_BIT, 84 + }; 85 + 86 + static const u32 hinic3_link_mode_50ge_base_r[] = { 87 + ETHTOOL_LINK_MODE_50000baseKR_Full_BIT, 88 + ETHTOOL_LINK_MODE_50000baseSR_Full_BIT, 89 + ETHTOOL_LINK_MODE_50000baseCR_Full_BIT, 90 + }; 91 + 92 + static const u32 hinic3_link_mode_50ge_base_r2[] = { 93 + ETHTOOL_LINK_MODE_50000baseCR2_Full_BIT, 94 + ETHTOOL_LINK_MODE_50000baseKR2_Full_BIT, 95 + ETHTOOL_LINK_MODE_50000baseSR2_Full_BIT, 96 + }; 97 + 98 + static const u32 hinic3_link_mode_100ge_base_r[] = { 99 + ETHTOOL_LINK_MODE_100000baseKR_Full_BIT, 100 + ETHTOOL_LINK_MODE_100000baseSR_Full_BIT, 101 + ETHTOOL_LINK_MODE_100000baseCR_Full_BIT, 102 + }; 103 + 104 + static const u32 hinic3_link_mode_100ge_base_r2[] = { 105 + ETHTOOL_LINK_MODE_100000baseKR2_Full_BIT, 106 + ETHTOOL_LINK_MODE_100000baseSR2_Full_BIT, 107 + ETHTOOL_LINK_MODE_100000baseCR2_Full_BIT, 108 + }; 109 + 110 + static const u32 hinic3_link_mode_100ge_base_r4[] = { 111 + ETHTOOL_LINK_MODE_100000baseKR4_Full_BIT, 112 + ETHTOOL_LINK_MODE_100000baseSR4_Full_BIT, 113 + ETHTOOL_LINK_MODE_100000baseCR4_Full_BIT, 114 + ETHTOOL_LINK_MODE_100000baseLR4_ER4_Full_BIT, 115 + }; 116 + 117 + static const u32 hinic3_link_mode_200ge_base_r2[] = { 118 + ETHTOOL_LINK_MODE_200000baseKR2_Full_BIT, 119 + ETHTOOL_LINK_MODE_200000baseSR2_Full_BIT, 120 + ETHTOOL_LINK_MODE_200000baseCR2_Full_BIT, 121 + }; 122 + 123 + static const u32 hinic3_link_mode_200ge_base_r4[] = { 124 + ETHTOOL_LINK_MODE_200000baseKR4_Full_BIT, 125 + ETHTOOL_LINK_MODE_200000baseSR4_Full_BIT, 126 + ETHTOOL_LINK_MODE_200000baseCR4_Full_BIT, 127 + }; 128 + 129 + struct hw2ethtool_link_mode { 130 + const u32 *link_mode_bit_arr; 131 + u32 arr_size; 132 + u32 speed; 133 + }; 134 + 135 + static const struct hw2ethtool_link_mode 136 + hw2ethtool_link_mode_table[LINK_MODE_MAX_NUMBERS] = { 137 + [LINK_MODE_GE] = { 138 + .link_mode_bit_arr = hinic3_link_mode_ge, 139 + .arr_size = ARRAY_SIZE(hinic3_link_mode_ge), 140 + .speed = SPEED_1000, 141 + }, 142 + [LINK_MODE_10GE_BASE_R] = { 143 + .link_mode_bit_arr = hinic3_link_mode_10ge_base_r, 144 + .arr_size = ARRAY_SIZE(hinic3_link_mode_10ge_base_r), 145 + .speed = SPEED_10000, 146 + }, 147 + [LINK_MODE_25GE_BASE_R] = { 148 + .link_mode_bit_arr = hinic3_link_mode_25ge_base_r, 149 + .arr_size = ARRAY_SIZE(hinic3_link_mode_25ge_base_r), 150 + .speed = SPEED_25000, 151 + }, 152 + [LINK_MODE_40GE_BASE_R4] = { 153 + .link_mode_bit_arr = hinic3_link_mode_40ge_base_r4, 154 + .arr_size = ARRAY_SIZE(hinic3_link_mode_40ge_base_r4), 155 + .speed = SPEED_40000, 156 + }, 157 + [LINK_MODE_50GE_BASE_R] = { 158 + .link_mode_bit_arr = hinic3_link_mode_50ge_base_r, 159 + .arr_size = ARRAY_SIZE(hinic3_link_mode_50ge_base_r), 160 + .speed = SPEED_50000, 161 + }, 162 + [LINK_MODE_50GE_BASE_R2] = { 163 + .link_mode_bit_arr = hinic3_link_mode_50ge_base_r2, 164 + .arr_size = ARRAY_SIZE(hinic3_link_mode_50ge_base_r2), 165 + .speed = SPEED_50000, 166 + }, 167 + [LINK_MODE_100GE_BASE_R] = { 168 + .link_mode_bit_arr = hinic3_link_mode_100ge_base_r, 169 + .arr_size = ARRAY_SIZE(hinic3_link_mode_100ge_base_r), 170 + .speed = SPEED_100000, 171 + }, 172 + [LINK_MODE_100GE_BASE_R2] = { 173 + .link_mode_bit_arr = hinic3_link_mode_100ge_base_r2, 174 + .arr_size = ARRAY_SIZE(hinic3_link_mode_100ge_base_r2), 175 + .speed = SPEED_100000, 176 + }, 177 + [LINK_MODE_100GE_BASE_R4] = { 178 + .link_mode_bit_arr = hinic3_link_mode_100ge_base_r4, 179 + .arr_size = ARRAY_SIZE(hinic3_link_mode_100ge_base_r4), 180 + .speed = SPEED_100000, 181 + }, 182 + [LINK_MODE_200GE_BASE_R2] = { 183 + .link_mode_bit_arr = hinic3_link_mode_200ge_base_r2, 184 + .arr_size = ARRAY_SIZE(hinic3_link_mode_200ge_base_r2), 185 + .speed = SPEED_200000, 186 + }, 187 + [LINK_MODE_200GE_BASE_R4] = { 188 + .link_mode_bit_arr = hinic3_link_mode_200ge_base_r4, 189 + .arr_size = ARRAY_SIZE(hinic3_link_mode_200ge_base_r4), 190 + .speed = SPEED_200000, 191 + }, 192 + }; 193 + 194 + #define GET_SUPPORTED_MODE 0 195 + #define GET_ADVERTISED_MODE 1 196 + 197 + struct hinic3_link_settings { 198 + __ETHTOOL_DECLARE_LINK_MODE_MASK(supported); 199 + __ETHTOOL_DECLARE_LINK_MODE_MASK(advertising); 200 + 201 + u32 speed; 202 + u8 duplex; 203 + u8 port; 204 + u8 autoneg; 205 + }; 206 + 207 + #define HINIC3_ADD_SUPPORTED_LINK_MODE(ecmd, mode) \ 208 + set_bit(ETHTOOL_LINK_##mode##_BIT, (ecmd)->supported) 209 + #define HINIC3_ADD_ADVERTISED_LINK_MODE(ecmd, mode) \ 210 + set_bit(ETHTOOL_LINK_##mode##_BIT, (ecmd)->advertising) 211 + 212 + static void hinic3_add_speed_link_mode(unsigned long *bitmap, u32 mode) 213 + { 214 + u32 i; 215 + 216 + for (i = 0; i < hw2ethtool_link_mode_table[mode].arr_size; i++) { 217 + if (hw2ethtool_link_mode_table[mode].link_mode_bit_arr[i] >= 218 + __ETHTOOL_LINK_MODE_MASK_NBITS) 219 + continue; 220 + 221 + set_bit(hw2ethtool_link_mode_table[mode].link_mode_bit_arr[i], 222 + bitmap); 223 + } 224 + } 225 + 226 + /* Related to enum mag_cmd_port_speed */ 227 + static const u32 hw_to_ethtool_speed[] = { 228 + (u32)SPEED_UNKNOWN, SPEED_10, SPEED_100, SPEED_1000, SPEED_10000, 229 + SPEED_25000, SPEED_40000, SPEED_50000, SPEED_100000, SPEED_200000 230 + }; 231 + 232 + static void 233 + hinic3_add_ethtool_link_mode(struct hinic3_link_settings *link_settings, 234 + u32 hw_link_mode, u32 name) 235 + { 236 + unsigned long *advertising_mask = link_settings->advertising; 237 + unsigned long *supported_mask = link_settings->supported; 238 + u32 link_mode; 239 + 240 + for (link_mode = 0; link_mode < LINK_MODE_MAX_NUMBERS; link_mode++) { 241 + if (hw_link_mode & BIT(link_mode)) { 242 + if (name == GET_SUPPORTED_MODE) 243 + hinic3_add_speed_link_mode(supported_mask, 244 + link_mode); 245 + else 246 + hinic3_add_speed_link_mode(advertising_mask, 247 + link_mode); 248 + } 249 + } 250 + } 251 + 252 + static void 253 + hinic3_link_speed_set(struct net_device *netdev, 254 + struct hinic3_link_settings *link_settings, 255 + struct hinic3_nic_port_info *port_info) 256 + { 257 + struct hinic3_nic_dev *nic_dev = netdev_priv(netdev); 258 + bool link_status_up; 259 + int err; 260 + 261 + if (port_info->supported_mode != LINK_MODE_UNKNOWN) 262 + hinic3_add_ethtool_link_mode(link_settings, 263 + port_info->supported_mode, 264 + GET_SUPPORTED_MODE); 265 + if (port_info->advertised_mode != LINK_MODE_UNKNOWN) 266 + hinic3_add_ethtool_link_mode(link_settings, 267 + port_info->advertised_mode, 268 + GET_ADVERTISED_MODE); 269 + 270 + err = hinic3_get_link_status(nic_dev->hwdev, &link_status_up); 271 + if (!err && link_status_up) { 272 + link_settings->speed = 273 + port_info->speed < ARRAY_SIZE(hw_to_ethtool_speed) ? 274 + hw_to_ethtool_speed[port_info->speed] : 275 + (u32)SPEED_UNKNOWN; 276 + 277 + link_settings->duplex = port_info->duplex; 278 + } else { 279 + link_settings->speed = (u32)SPEED_UNKNOWN; 280 + link_settings->duplex = DUPLEX_UNKNOWN; 281 + } 282 + } 283 + 284 + static void 285 + hinic3_link_port_type_set(struct hinic3_link_settings *link_settings, 286 + u8 port_type) 287 + { 288 + switch (port_type) { 289 + case MAG_CMD_WIRE_TYPE_ELECTRIC: 290 + HINIC3_ADD_SUPPORTED_LINK_MODE(link_settings, MODE_TP); 291 + HINIC3_ADD_ADVERTISED_LINK_MODE(link_settings, MODE_TP); 292 + link_settings->port = PORT_TP; 293 + break; 294 + 295 + case MAG_CMD_WIRE_TYPE_AOC: 296 + case MAG_CMD_WIRE_TYPE_MM: 297 + case MAG_CMD_WIRE_TYPE_SM: 298 + HINIC3_ADD_SUPPORTED_LINK_MODE(link_settings, MODE_FIBRE); 299 + HINIC3_ADD_ADVERTISED_LINK_MODE(link_settings, MODE_FIBRE); 300 + link_settings->port = PORT_FIBRE; 301 + break; 302 + 303 + case MAG_CMD_WIRE_TYPE_COPPER: 304 + HINIC3_ADD_SUPPORTED_LINK_MODE(link_settings, MODE_FIBRE); 305 + HINIC3_ADD_ADVERTISED_LINK_MODE(link_settings, MODE_FIBRE); 306 + link_settings->port = PORT_DA; 307 + break; 308 + 309 + case MAG_CMD_WIRE_TYPE_BACKPLANE: 310 + HINIC3_ADD_SUPPORTED_LINK_MODE(link_settings, MODE_Backplane); 311 + HINIC3_ADD_ADVERTISED_LINK_MODE(link_settings, MODE_Backplane); 312 + link_settings->port = PORT_NONE; 313 + break; 314 + 315 + default: 316 + link_settings->port = PORT_OTHER; 317 + break; 318 + } 319 + } 320 + 321 + static int 322 + hinic3_get_link_pause_settings(struct net_device *netdev, 323 + struct hinic3_link_settings *link_settings) 324 + { 325 + struct hinic3_nic_dev *nic_dev = netdev_priv(netdev); 326 + struct hinic3_nic_pause_config nic_pause = {}; 327 + int err; 328 + 329 + err = hinic3_get_pause_info(nic_dev, &nic_pause); 330 + if (err) { 331 + netdev_err(netdev, "Failed to get pause param from hw\n"); 332 + return err; 333 + } 334 + 335 + HINIC3_ADD_SUPPORTED_LINK_MODE(link_settings, MODE_Pause); 336 + if (nic_pause.rx_pause && nic_pause.tx_pause) { 337 + HINIC3_ADD_ADVERTISED_LINK_MODE(link_settings, MODE_Pause); 338 + } else if (nic_pause.tx_pause) { 339 + HINIC3_ADD_ADVERTISED_LINK_MODE(link_settings, 340 + MODE_Asym_Pause); 341 + } else if (nic_pause.rx_pause) { 342 + HINIC3_ADD_ADVERTISED_LINK_MODE(link_settings, MODE_Pause); 343 + HINIC3_ADD_ADVERTISED_LINK_MODE(link_settings, 344 + MODE_Asym_Pause); 345 + } 346 + 347 + return 0; 348 + } 349 + 350 + static int 351 + hinic3_get_link_settings(struct net_device *netdev, 352 + struct hinic3_link_settings *link_settings) 353 + { 354 + struct hinic3_nic_dev *nic_dev = netdev_priv(netdev); 355 + struct hinic3_nic_port_info port_info = {}; 356 + int err; 357 + 358 + err = hinic3_get_port_info(nic_dev->hwdev, &port_info); 359 + if (err) { 360 + netdev_err(netdev, "Failed to get port info\n"); 361 + return err; 362 + } 363 + 364 + hinic3_link_speed_set(netdev, link_settings, &port_info); 365 + 366 + hinic3_link_port_type_set(link_settings, port_info.port_type); 367 + 368 + link_settings->autoneg = port_info.autoneg_state == PORT_CFG_AN_ON ? 369 + AUTONEG_ENABLE : AUTONEG_DISABLE; 370 + if (port_info.autoneg_cap) 371 + HINIC3_ADD_SUPPORTED_LINK_MODE(link_settings, MODE_Autoneg); 372 + if (port_info.autoneg_state == PORT_CFG_AN_ON) 373 + HINIC3_ADD_ADVERTISED_LINK_MODE(link_settings, MODE_Autoneg); 374 + 375 + if (!HINIC3_IS_VF(nic_dev->hwdev)) { 376 + err = hinic3_get_link_pause_settings(netdev, link_settings); 377 + if (err) 378 + return err; 379 + } 380 + 381 + return 0; 382 + } 383 + 384 + static int 385 + hinic3_get_link_ksettings(struct net_device *netdev, 386 + struct ethtool_link_ksettings *link_settings) 387 + { 388 + struct ethtool_link_settings *base = &link_settings->base; 389 + struct hinic3_link_settings settings = {}; 390 + int err; 391 + 392 + ethtool_link_ksettings_zero_link_mode(link_settings, supported); 393 + ethtool_link_ksettings_zero_link_mode(link_settings, advertising); 394 + 395 + err = hinic3_get_link_settings(netdev, &settings); 396 + if (err) 397 + return err; 398 + 399 + bitmap_copy(link_settings->link_modes.supported, settings.supported, 400 + __ETHTOOL_LINK_MODE_MASK_NBITS); 401 + bitmap_copy(link_settings->link_modes.advertising, settings.advertising, 402 + __ETHTOOL_LINK_MODE_MASK_NBITS); 403 + 404 + base->autoneg = settings.autoneg; 405 + base->speed = settings.speed; 406 + base->duplex = settings.duplex; 407 + base->port = settings.port; 408 + 409 + return 0; 410 + } 411 + 412 + static const struct ethtool_ops hinic3_ethtool_ops = { 413 + .supported_coalesce_params = ETHTOOL_COALESCE_USECS | 414 + ETHTOOL_COALESCE_PKT_RATE_RX_USECS, 415 + .get_link_ksettings = hinic3_get_link_ksettings, 416 + .get_drvinfo = hinic3_get_drvinfo, 417 + .get_msglevel = hinic3_get_msglevel, 418 + .set_msglevel = hinic3_set_msglevel, 419 + .get_link = ethtool_op_get_link, 420 + }; 421 + 422 + void hinic3_set_ethtool_ops(struct net_device *netdev) 423 + { 424 + netdev->ethtool_ops = &hinic3_ethtool_ops; 425 + }
+44 -3
drivers/net/ethernet/huawei/hinic3/hinic3_hw_cfg.c
··· 17 17 { 18 18 cap->port_id = dev_cap->port_id; 19 19 cap->supp_svcs_bitmap = dev_cap->svc_cap_en; 20 + 21 + cap->cos_valid_bitmap = dev_cap->valid_cos_bitmap; 22 + cap->port_cos_valid_bitmap = dev_cap->port_cos_valid_bitmap; 23 + 24 + if (type != HINIC3_FUNC_TYPE_VF) 25 + cap->max_vf = dev_cap->max_vf; 26 + else 27 + cap->max_vf = 0; 28 + 29 + dev_dbg(hwdev->dev, "Port_id: 0x%x, cos_bitmap: 0x%x, Max_vf: 0x%x\n", 30 + cap->port_id, cap->cos_valid_bitmap, cap->max_vf); 20 31 } 21 32 22 33 static void hinic3_parse_l2nic_res_cap(struct hinic3_hwdev *hwdev, ··· 39 28 40 29 nic_svc_cap->max_sqs = min(dev_cap->nic_max_sq_id + 1, 41 30 HINIC3_CFG_MAX_QP); 31 + 32 + nic_svc_cap->max_rqs = min(dev_cap->nic_max_rq_id + 1, 33 + HINIC3_CFG_MAX_QP); 34 + nic_svc_cap->default_num_queues = dev_cap->nic_default_num_queues; 35 + 36 + dev_dbg(hwdev->dev, "L2nic resource capbility, max_sqs: 0x%x, max_rqs: 0x%x\n", 37 + nic_svc_cap->max_sqs, nic_svc_cap->max_rqs); 42 38 } 43 39 44 40 static void hinic3_parse_dev_cap(struct hinic3_hwdev *hwdev, ··· 62 44 hinic3_parse_l2nic_res_cap(hwdev, cap, dev_cap, type); 63 45 } 64 46 65 - static int get_cap_from_fw(struct hinic3_hwdev *hwdev, 66 - enum hinic3_func_type type) 47 + static int hinic3_get_cap_from_fw(struct hinic3_hwdev *hwdev, 48 + enum hinic3_func_type type) 67 49 { 68 50 struct mgmt_msg_params msg_params = {}; 69 51 struct cfg_cmd_dev_cap dev_cap = {}; ··· 83 65 } 84 66 85 67 hinic3_parse_dev_cap(hwdev, &dev_cap, type); 68 + 69 + return 0; 70 + } 71 + 72 + static int hinic3_get_dev_cap(struct hinic3_hwdev *hwdev) 73 + { 74 + enum hinic3_func_type type = HINIC3_FUNC_TYPE(hwdev); 75 + int err; 76 + 77 + switch (type) { 78 + case HINIC3_FUNC_TYPE_PF: 79 + case HINIC3_FUNC_TYPE_VF: 80 + err = hinic3_get_cap_from_fw(hwdev, type); 81 + if (err) { 82 + dev_err(hwdev->dev, "Failed to get FW capability\n"); 83 + return err; 84 + } 85 + break; 86 + default: 87 + dev_err(hwdev->dev, "Unsupported PCI Function type: %d\n", 88 + type); 89 + return -EINVAL; 90 + } 86 91 87 92 return 0; 88 93 } ··· 256 215 257 216 int hinic3_init_capability(struct hinic3_hwdev *hwdev) 258 217 { 259 - return get_cap_from_fw(hwdev, HINIC3_FUNC_TYPE_VF); 218 + return hinic3_get_dev_cap(hwdev); 260 219 } 261 220 262 221 bool hinic3_support_nic(struct hinic3_hwdev *hwdev)
+8
drivers/net/ethernet/huawei/hinic3/hinic3_hw_cfg.h
··· 26 26 27 27 struct hinic3_nic_service_cap { 28 28 u16 max_sqs; 29 + u16 max_rqs; 30 + u16 default_num_queues; 29 31 }; 30 32 31 33 /* Device capabilities */ ··· 36 34 u16 supp_svcs_bitmap; 37 35 /* Physical port */ 38 36 u8 port_id; 37 + 38 + u8 cos_valid_bitmap; 39 + u8 port_cos_valid_bitmap; 40 + /* max number of VFs that PF supports */ 41 + u16 max_vf; 42 + 39 43 struct hinic3_nic_service_cap nic_svc_cap; 40 44 }; 41 45
+69
drivers/net/ethernet/huawei/hinic3/hinic3_hw_comm.c
··· 292 292 return 0; 293 293 } 294 294 295 + #define HINIC3_FLR_TIMEOUT 1000 296 + 297 + static enum hinic3_wait_return hinic3_check_flr_finish_handler(void *priv_data) 298 + { 299 + struct hinic3_hwdev *hwdev = priv_data; 300 + struct hinic3_hwif *hwif = hwdev->hwif; 301 + enum hinic3_pf_status status; 302 + 303 + if (!hwdev->chip_present_flag) 304 + return HINIC3_WAIT_PROCESS_ERR; 305 + 306 + status = hinic3_get_pf_status(hwif); 307 + if (status == HINIC3_PF_STATUS_FLR_FINISH_FLAG) { 308 + hinic3_set_pf_status(hwif, HINIC3_PF_STATUS_ACTIVE_FLAG); 309 + return HINIC3_WAIT_PROCESS_CPL; 310 + } 311 + 312 + return HINIC3_WAIT_PROCESS_WAITING; 313 + } 314 + 315 + static int hinic3_wait_for_flr_finish(struct hinic3_hwdev *hwdev) 316 + { 317 + return hinic3_wait_for_timeout(hwdev, hinic3_check_flr_finish_handler, 318 + HINIC3_FLR_TIMEOUT, 0xa * USEC_PER_MSEC); 319 + } 320 + 295 321 #define HINIC3_WAIT_CMDQ_IDLE_TIMEOUT 5000 296 322 297 323 static enum hinic3_wait_return check_cmdq_stop_handler(void *priv_data) ··· 325 299 struct hinic3_hwdev *hwdev = priv_data; 326 300 enum hinic3_cmdq_type cmdq_type; 327 301 struct hinic3_cmdqs *cmdqs; 302 + 303 + /* Stop waiting when card unpresent */ 304 + if (!hwdev->chip_present_flag) 305 + return HINIC3_WAIT_PROCESS_ERR; 328 306 329 307 cmdqs = hwdev->cmdqs; 330 308 for (cmdq_type = 0; cmdq_type < cmdqs->cmdq_num; cmdq_type++) { ··· 377 347 int ret = 0; 378 348 int err; 379 349 350 + if (!hwdev->chip_present_flag) 351 + return 0; 352 + 380 353 err = wait_cmdq_stop(hwdev); 381 354 if (err) { 382 355 dev_warn(hwdev->dev, "CMDQ is still working, CMDQ timeout value is unreasonable\n"); ··· 413 380 dev_warn(hwdev->dev, "Failed to notice flush message, err: %d\n", 414 381 err); 415 382 ret = err; 383 + } 384 + 385 + if (HINIC3_FUNC_TYPE(hwdev) != HINIC3_FUNC_TYPE_VF) { 386 + err = hinic3_wait_for_flr_finish(hwdev); 387 + if (err) { 388 + dev_warn(hwdev->dev, "Wait firmware FLR timeout\n"); 389 + ret = err; 390 + } 416 391 } 417 392 418 393 hinic3_toggle_doorbell(hwif, ENABLE_DOORBELL); ··· 577 536 err, root_ctxt.head.status); 578 537 return -EFAULT; 579 538 } 539 + 540 + return 0; 541 + } 542 + 543 + #define HINIC3_FW_VER_TYPE_MPU 1 544 + 545 + int hinic3_get_mgmt_version(struct hinic3_hwdev *hwdev, u8 *mgmt_ver, 546 + u8 version_size) 547 + { 548 + struct comm_cmd_get_fw_version fw_ver = {}; 549 + struct mgmt_msg_params msg_params = {}; 550 + int err; 551 + 552 + fw_ver.fw_type = HINIC3_FW_VER_TYPE_MPU; 553 + 554 + mgmt_msg_params_init_default(&msg_params, &fw_ver, sizeof(fw_ver)); 555 + 556 + err = hinic3_send_mbox_to_mgmt(hwdev, MGMT_MOD_COMM, 557 + COMM_CMD_GET_FW_VERSION, &msg_params); 558 + 559 + if (err || fw_ver.head.status) { 560 + dev_err(hwdev->dev, 561 + "Failed to get fw version, err: %d, status: 0x%x\n", 562 + err, fw_ver.head.status); 563 + return -EFAULT; 564 + } 565 + 566 + snprintf(mgmt_ver, version_size, "%s", fw_ver.ver); 580 567 581 568 return 0; 582 569 }
+2
drivers/net/ethernet/huawei/hinic3/hinic3_hw_comm.h
··· 49 49 int hinic3_set_root_ctxt(struct hinic3_hwdev *hwdev, u32 rq_depth, u32 sq_depth, 50 50 int rx_buf_sz); 51 51 int hinic3_clean_root_ctxt(struct hinic3_hwdev *hwdev); 52 + int hinic3_get_mgmt_version(struct hinic3_hwdev *hwdev, u8 *mgmt_ver, 53 + u8 version_size); 52 54 53 55 #endif
+12
drivers/net/ethernet/huawei/hinic3/hinic3_hw_intf.h
··· 114 114 COMM_CMD_SET_DMA_ATTR = 25, 115 115 116 116 /* Commands for obtaining information */ 117 + COMM_CMD_GET_FW_VERSION = 60, 117 118 COMM_CMD_SYNC_TIME = 62, 118 119 COMM_CMD_SEND_BDF_INFO = 64, 119 120 }; ··· 274 273 u8 device; 275 274 u8 function; 276 275 u8 rsvd2[5]; 276 + }; 277 + 278 + #define COMM_FW_VERSION_LEN 16 279 + #define COMM_FW_COMPILE_TIME_LEN 20 280 + struct comm_cmd_get_fw_version { 281 + struct mgmt_msg_head head; 282 + 283 + u16 fw_type; 284 + u16 rsvd1; 285 + u8 ver[COMM_FW_VERSION_LEN]; 286 + u8 time[COMM_FW_COMPILE_TIME_LEN]; 277 287 }; 278 288 279 289 /* Services supported by HW. HW uses these values when delivering events.
+9
drivers/net/ethernet/huawei/hinic3/hinic3_hwdev.c
··· 32 32 #define HINIC3_PCIE_PH_DISABLE 0 33 33 #define HINIC3_PCIE_MSIX_ATTR_ENTRY 0 34 34 35 + #define HINIC3_CHIP_PRESENT 1 36 + #define HINIC3_CHIP_ABSENT 0 37 + 35 38 #define HINIC3_DEFAULT_EQ_MSIX_PENDING_LIMIT 0 36 39 #define HINIC3_DEFAULT_EQ_MSIX_COALESC_TIMER_CFG 0xFF 37 40 #define HINIC3_DEFAULT_EQ_MSIX_RESEND_TIMER_CFG 7 ··· 434 431 static void hinic3_free_cmdqs_channel(struct hinic3_hwdev *hwdev) 435 432 { 436 433 hinic3_comm_cmdqs_free(hwdev); 434 + 435 + hinic3_set_wq_page_size(hwdev, hinic3_global_func_id(hwdev), 436 + HINIC3_MIN_PAGE_SIZE); 437 + 437 438 hinic3_ceqs_free(hwdev); 438 439 } 439 440 ··· 552 545 dev_err(hwdev->dev, "Failed to init hwif\n"); 553 546 goto err_free_hwdev; 554 547 } 548 + hwdev->chip_present_flag = HINIC3_CHIP_PRESENT; 555 549 556 550 hwdev->workq = alloc_workqueue(HINIC3_HWDEV_WQ_NAME, WQ_MEM_RECLAIM | WQ_PERCPU, 557 551 HINIC3_WQ_MAX_REQ); ··· 629 621 struct hinic3_recv_msg *recv_resp_msg; 630 622 struct hinic3_mbox *mbox; 631 623 624 + hwdev->chip_present_flag = HINIC3_CHIP_ABSENT; 632 625 spin_lock_bh(&hwdev->channel_lock); 633 626 if (HINIC3_IS_PF(hwdev) && 634 627 test_bit(HINIC3_HWDEV_MGMT_INITED, &hwdev->func_state)) {
+1
drivers/net/ethernet/huawei/hinic3/hinic3_hwdev.h
··· 76 76 u32 wq_page_size; 77 77 u8 max_cmdq; 78 78 ulong func_state; 79 + int chip_present_flag; 79 80 }; 80 81 81 82 struct hinic3_event_info {
+21 -2
drivers/net/ethernet/huawei/hinic3/hinic3_hwif.c
··· 70 70 #define HINIC3_PPF_ELECTION_GET(val, member) \ 71 71 FIELD_GET(HINIC3_PPF_ELECTION_##member##_MASK, val) 72 72 73 + #define HINIC3_GET_REG_FLAG(reg) ((reg) & (~(HINIC3_REGS_FLAG_MASK))) 73 74 #define HINIC3_GET_REG_ADDR(reg) ((reg) & (HINIC3_REGS_FLAG_MASK)) 74 75 75 76 static void __iomem *hinic3_reg_addr(struct hinic3_hwif *hwif, u32 reg) 76 77 { 77 - return hwif->cfg_regs_base + HINIC3_GET_REG_ADDR(reg); 78 + void __iomem *addr; 79 + 80 + if (HINIC3_GET_REG_FLAG(reg) == HINIC3_MGMT_REGS_FLAG) 81 + addr = hwif->mgmt_regs_base + HINIC3_GET_REG_ADDR(reg); 82 + else 83 + addr = hwif->cfg_regs_base + HINIC3_GET_REG_ADDR(reg); 84 + 85 + return addr; 78 86 } 79 87 80 88 u32 hinic3_hwif_read_reg(struct hinic3_hwif *hwif, u32 reg) ··· 105 97 u32 attr1; 106 98 107 99 attr1 = hinic3_hwif_read_reg(hwdev->hwif, HINIC3_CSR_FUNC_ATTR1_ADDR); 100 + if (attr1 == HINIC3_PCIE_LINK_DOWN) 101 + return HINIC3_WAIT_PROCESS_ERR; 108 102 109 103 return HINIC3_AF1_GET(attr1, MGMT_INIT_STATUS) ? 110 104 HINIC3_WAIT_PROCESS_CPL : HINIC3_WAIT_PROCESS_WAITING; ··· 145 135 static int init_hwif_attr(struct hinic3_hwdev *hwdev) 146 136 { 147 137 u32 attr0, attr1, attr2, attr3, attr6; 138 + struct hinic3_func_attr *attr; 148 139 struct hinic3_hwif *hwif; 149 140 150 141 hwif = hwdev->hwif; ··· 169 158 if (attr6 == HINIC3_PCIE_LINK_DOWN) 170 159 return -EFAULT; 171 160 172 - set_hwif_attr(&hwif->attr, attr0, attr1, attr2, attr3, attr6); 161 + attr = &hwif->attr; 162 + set_hwif_attr(attr, attr0, attr1, attr2, attr3, attr6); 163 + 164 + if (attr->func_type != HINIC3_FUNC_TYPE_VF && 165 + attr->func_type != HINIC3_FUNC_TYPE_PF) { 166 + dev_err(hwdev->dev, "unexpected func_type %u\n", 167 + attr->func_type); 168 + return -EINVAL; 169 + } 173 170 174 171 if (!hwif->attr.num_ceqs) { 175 172 dev_err(hwdev->dev, "Ceq num cfg in fw is zero\n");
+1
drivers/net/ethernet/huawei/hinic3/hinic3_lld.c
··· 426 426 } 427 427 428 428 static const struct pci_device_id hinic3_pci_table[] = { 429 + {PCI_VDEVICE(HUAWEI, PCI_DEV_ID_HINIC3_PF), 0}, 429 430 {PCI_VDEVICE(HUAWEI, PCI_DEV_ID_HINIC3_VF), 0}, 430 431 {0, 0} 431 432
+3
drivers/net/ethernet/huawei/hinic3/hinic3_main.c
··· 18 18 19 19 #define HINIC3_NIC_DRV_DESC "Intelligent Network Interface Card Driver" 20 20 21 + #define HINIC3_DEFAULT_MSG_ENABLE (NETIF_MSG_DRV | NETIF_MSG_LINK) 21 22 #define HINIC3_RX_BUF_LEN 2048 22 23 #define HINIC3_LRO_REPLENISH_THLD 256 23 24 #define HINIC3_NIC_DEV_WQ_NAME "hinic3_nic_dev_wq" ··· 144 143 nic_dev->hwdev = hwdev; 145 144 nic_dev->pdev = pdev; 146 145 146 + nic_dev->msg_enable = HINIC3_DEFAULT_MSG_ENABLE; 147 147 nic_dev->rx_buf_len = HINIC3_RX_BUF_LEN; 148 148 nic_dev->lro_replenish_thld = HINIC3_LRO_REPLENISH_THLD; 149 149 nic_dev->vlan_bitmap = kzalloc(HINIC3_VLAN_BITMAP_SIZE(nic_dev), ··· 243 241 static void hinic3_assign_netdev_ops(struct net_device *netdev) 244 242 { 245 243 hinic3_set_netdev_ops(netdev); 244 + hinic3_set_ethtool_ops(netdev); 246 245 } 247 246 248 247 static void netdev_feature_init(struct net_device *netdev)
+36 -3
drivers/net/ethernet/huawei/hinic3/hinic3_mbox.c
··· 5 5 6 6 #include "hinic3_common.h" 7 7 #include "hinic3_csr.h" 8 + #include "hinic3_eqs.h" 8 9 #include "hinic3_hwdev.h" 9 10 #include "hinic3_hwif.h" 10 11 #include "hinic3_mbox.h" ··· 51 50 #define MBOX_WB_STATUS_NOT_FINISHED 0x00 52 51 53 52 #define MBOX_STATUS_FINISHED(wb) \ 54 - ((FIELD_PREP(MBOX_WB_STATUS_MASK, (wb))) != MBOX_WB_STATUS_NOT_FINISHED) 53 + ((FIELD_GET(MBOX_WB_STATUS_MASK, (wb))) != MBOX_WB_STATUS_NOT_FINISHED) 55 54 #define MBOX_STATUS_SUCCESS(wb) \ 56 - ((FIELD_PREP(MBOX_WB_STATUS_MASK, (wb))) == \ 55 + ((FIELD_GET(MBOX_WB_STATUS_MASK, (wb))) == \ 57 56 MBOX_WB_STATUS_FINISHED_SUCCESS) 58 57 #define MBOX_STATUS_ERRCODE(wb) \ 59 58 ((wb) & MBOX_WB_ERROR_CODE_MASK) ··· 396 395 { 397 396 mbox->hwdev = hwdev; 398 397 mutex_init(&mbox->mbox_send_lock); 398 + mutex_init(&mbox->mbox_seg_send_lock); 399 399 spin_lock_init(&mbox->mbox_lock); 400 400 401 401 mbox->workq = create_singlethread_workqueue(HINIC3_MBOX_WQ_NAME); ··· 462 460 463 461 destroy_workqueue(mbox->workq); 464 462 free_mbox_wb_status(mbox); 465 - hinic3_uninit_func_mbox_msg_channel(hwdev); 463 + if (HINIC3_IS_VF(hwdev)) 464 + hinic3_uninit_func_mbox_msg_channel(hwdev); 466 465 uninit_mgmt_msg_channel(mbox); 467 466 kfree(mbox); 468 467 } ··· 619 616 mbox_ctrl); 620 617 } 621 618 619 + static void hinic3_dump_mbox_reg(struct hinic3_hwdev *hwdev) 620 + { 621 + u32 val; 622 + 623 + val = hinic3_hwif_read_reg(hwdev->hwif, 624 + HINIC3_FUNC_CSR_MAILBOX_CONTROL_OFF); 625 + dev_err(hwdev->dev, "Mailbox control reg: 0x%x\n", val); 626 + val = hinic3_hwif_read_reg(hwdev->hwif, 627 + HINIC3_FUNC_CSR_MAILBOX_INT_OFF); 628 + dev_err(hwdev->dev, "Mailbox interrupt offset: 0x%x\n", val); 629 + } 630 + 622 631 static u16 get_mbox_status(const struct hinic3_send_mbox *mbox) 623 632 { 624 633 __be64 *wb_status = mbox->wb_vaddr; ··· 647 632 { 648 633 struct hinic3_mbox *mbox = priv_data; 649 634 u16 wb_status; 635 + 636 + if (!mbox->hwdev->chip_present_flag) 637 + return HINIC3_WAIT_PROCESS_ERR; 650 638 651 639 wb_status = get_mbox_status(&mbox->send_mbox); 652 640 ··· 688 670 if (err) { 689 671 dev_err(hwdev->dev, "Send mailbox segment timeout, wb status: 0x%x\n", 690 672 wb_status); 673 + hinic3_dump_mbox_reg(hwdev); 691 674 return err; 692 675 } 693 676 ··· 724 705 rsp_aeq_id = MBOX_MSG_AEQ_FOR_MBOX; 725 706 else 726 707 rsp_aeq_id = 0; 708 + 709 + mutex_lock(&mbox->mbox_seg_send_lock); 727 710 728 711 if (dst_func == MBOX_MGMT_FUNC_ID && 729 712 !(hwdev->features[0] & MBOX_COMM_F_MBOX_SEGMENT)) { ··· 780 759 } 781 760 782 761 err_send: 762 + mutex_unlock(&mbox->mbox_seg_send_lock); 763 + 783 764 return err; 784 765 } 785 766 ··· 796 773 static enum hinic3_wait_return check_mbox_msg_finish(void *priv_data) 797 774 { 798 775 struct hinic3_mbox *mbox = priv_data; 776 + 777 + if (!mbox->hwdev->chip_present_flag) 778 + return HINIC3_WAIT_PROCESS_ERR; 799 779 800 780 return (mbox->event_flag == MBOX_EVENT_SUCCESS) ? 801 781 HINIC3_WAIT_PROCESS_CPL : HINIC3_WAIT_PROCESS_WAITING; ··· 831 805 u32 msg_len; 832 806 int err; 833 807 808 + if (!hwdev->chip_present_flag) 809 + return -EPERM; 810 + 834 811 /* expect response message */ 835 812 msg_desc = get_mbox_msg_desc(mbox, MBOX_MSG_RESP, MBOX_MGMT_FUNC_ID); 836 813 mutex_lock(&mbox->mbox_send_lock); ··· 854 825 if (wait_mbox_msg_completion(mbox, msg_params->timeout_ms)) { 855 826 dev_err(hwdev->dev, 856 827 "Send mbox msg timeout, msg_id: %u\n", msg_info.msg_id); 828 + hinic3_dump_aeq_info(mbox->hwdev); 857 829 err = -ETIMEDOUT; 858 830 goto err_send; 859 831 } ··· 911 881 struct hinic3_mbox *mbox = hwdev->mbox; 912 882 struct mbox_msg_info msg_info = {}; 913 883 int err; 884 + 885 + if (!hwdev->chip_present_flag) 886 + return -EPERM; 914 887 915 888 mutex_lock(&mbox->mbox_send_lock); 916 889 err = send_mbox_msg(mbox, mod, cmd, msg_params->buf_in,
+4
drivers/net/ethernet/huawei/hinic3/hinic3_mbox.h
··· 114 114 struct hinic3_hwdev *hwdev; 115 115 /* lock for send mbox message and ack message */ 116 116 struct mutex mbox_send_lock; 117 + /* lock for send message transmission. 118 + * The lock hierarchy is mbox_send_lock -> mbox_seg_send_lock. 119 + */ 120 + struct mutex mbox_seg_send_lock; 117 121 struct hinic3_send_mbox send_mbox; 118 122 struct mbox_dma_queue sync_msg_queue; 119 123 struct mbox_dma_queue async_msg_queue;
+15 -1
drivers/net/ethernet/huawei/hinic3/hinic3_mgmt_interface.h
··· 183 183 /* IEEE 802.1Qaz std */ 184 184 #define L2NIC_DCB_COS_MAX 0x8 185 185 186 - struct l2nic_cmd_set_rss_ctx_tbl { 186 + struct l2nic_cmd_pause_config { 187 + struct mgmt_msg_head msg_head; 188 + u8 port_id; 189 + u8 opcode; 190 + u16 rsvd1; 191 + u8 auto_neg; 192 + u8 rx_pause; 193 + u8 tx_pause; 194 + u8 rsvd2[5]; 195 + }; 196 + 197 + struct l2nic_cmd_rss_ctx_tbl { 187 198 struct mgmt_msg_head msg_head; 188 199 u16 func_id; 189 200 u16 rsvd1; ··· 249 238 L2NIC_CMD_CFG_RSS_HASH_KEY = 63, 250 239 L2NIC_CMD_CFG_RSS_HASH_ENGINE = 64, 251 240 L2NIC_CMD_SET_RSS_CTX_TBL = 65, 241 + L2NIC_CMD_CFG_PAUSE_INFO = 101, 252 242 L2NIC_CMD_QOS_DCB_STATE = 110, 253 243 L2NIC_CMD_FORCE_PKT_DROP = 113, 254 244 L2NIC_CMD_MAX = 256, ··· 271 259 enum mag_cmd { 272 260 MAG_CMD_SET_PORT_ENABLE = 6, 273 261 MAG_CMD_GET_LINK_STATUS = 7, 262 + 263 + MAG_CMD_GET_PORT_INFO = 153, 274 264 }; 275 265 276 266 /* firmware also use this cmd report link event to driver */
+10 -6
drivers/net/ethernet/huawei/hinic3/hinic3_netdev_ops.c
··· 415 415 netif_carrier_off(netdev); 416 416 netif_tx_disable(netdev); 417 417 418 - glb_func_id = hinic3_global_func_id(nic_dev->hwdev); 419 - hinic3_set_vport_enable(nic_dev->hwdev, glb_func_id, false); 418 + if (nic_dev->hwdev->chip_present_flag) { 419 + hinic3_maybe_set_port_state(netdev, false); 420 420 421 - hinic3_flush_txqs(netdev); 422 - /* wait to guarantee that no packets will be sent to host */ 423 - msleep(100); 424 - hinic3_flush_qps_res(nic_dev->hwdev); 421 + glb_func_id = hinic3_global_func_id(nic_dev->hwdev); 422 + hinic3_set_vport_enable(nic_dev->hwdev, glb_func_id, false); 423 + 424 + hinic3_flush_txqs(netdev); 425 + /* wait to guarantee that no packets will be sent to host */ 426 + msleep(100); 427 + hinic3_flush_qps_res(nic_dev->hwdev); 428 + } 425 429 } 426 430 427 431 static int hinic3_open(struct net_device *netdev)
+77
drivers/net/ethernet/huawei/hinic3/hinic3_nic_cfg.c
··· 639 639 return 0; 640 640 } 641 641 642 + int hinic3_get_port_info(struct hinic3_hwdev *hwdev, 643 + struct hinic3_nic_port_info *port_info) 644 + { 645 + struct mag_cmd_get_port_info port_msg = {}; 646 + struct mgmt_msg_params msg_params = {}; 647 + int err; 648 + 649 + port_msg.port_id = hinic3_physical_port_id(hwdev); 650 + 651 + mgmt_msg_params_init_default(&msg_params, &port_msg, sizeof(port_msg)); 652 + 653 + err = hinic3_send_mbox_to_mgmt(hwdev, MGMT_MOD_HILINK, 654 + MAG_CMD_GET_PORT_INFO, &msg_params); 655 + 656 + if (err || port_msg.head.status) { 657 + dev_err(hwdev->dev, 658 + "Failed to get port info, err: %d, status: 0x%x\n", 659 + err, port_msg.head.status); 660 + return -EFAULT; 661 + } 662 + 663 + port_info->autoneg_cap = port_msg.an_support; 664 + port_info->autoneg_state = port_msg.an_en; 665 + port_info->duplex = port_msg.duplex; 666 + port_info->port_type = port_msg.wire_type; 667 + port_info->speed = port_msg.speed; 668 + port_info->fec = port_msg.fec; 669 + port_info->supported_mode = port_msg.supported_mode; 670 + port_info->advertised_mode = port_msg.advertised_mode; 671 + 672 + return 0; 673 + } 674 + 642 675 int hinic3_set_vport_enable(struct hinic3_hwdev *hwdev, u16 func_id, 643 676 bool enable) 644 677 { ··· 693 660 } 694 661 695 662 return 0; 663 + } 664 + 665 + static int hinic3_cfg_hw_pause(struct hinic3_hwdev *hwdev, u8 opcode, 666 + struct hinic3_nic_pause_config *nic_pause) 667 + { 668 + struct l2nic_cmd_pause_config pause_info = {}; 669 + struct mgmt_msg_params msg_params = {}; 670 + int err; 671 + 672 + pause_info.port_id = hinic3_physical_port_id(hwdev); 673 + pause_info.opcode = opcode; 674 + if (opcode == MGMT_MSG_CMD_OP_SET) { 675 + pause_info.auto_neg = nic_pause->auto_neg; 676 + pause_info.rx_pause = nic_pause->rx_pause; 677 + pause_info.tx_pause = nic_pause->tx_pause; 678 + } 679 + 680 + mgmt_msg_params_init_default(&msg_params, &pause_info, 681 + sizeof(pause_info)); 682 + 683 + err = hinic3_send_mbox_to_mgmt(hwdev, MGMT_MOD_L2NIC, 684 + L2NIC_CMD_CFG_PAUSE_INFO, &msg_params); 685 + 686 + if (err || pause_info.msg_head.status) { 687 + dev_err(hwdev->dev, "Failed to %s pause info, err: %d, status: 0x%x\n", 688 + opcode == MGMT_MSG_CMD_OP_SET ? "set" : "get", 689 + err, pause_info.msg_head.status); 690 + return -EFAULT; 691 + } 692 + 693 + if (opcode == MGMT_MSG_CMD_OP_GET) { 694 + nic_pause->auto_neg = pause_info.auto_neg; 695 + nic_pause->rx_pause = pause_info.rx_pause; 696 + nic_pause->tx_pause = pause_info.tx_pause; 697 + } 698 + 699 + return 0; 700 + } 701 + 702 + int hinic3_get_pause_info(struct hinic3_nic_dev *nic_dev, 703 + struct hinic3_nic_pause_config *nic_pause) 704 + { 705 + return hinic3_cfg_hw_pause(nic_dev->hwdev, MGMT_MSG_CMD_OP_GET, 706 + nic_pause); 696 707 }
+110
drivers/net/ethernet/huawei/hinic3/hinic3_nic_cfg.h
··· 6 6 7 7 #include <linux/types.h> 8 8 9 + #include "hinic3_hwif.h" 9 10 #include "hinic3_hw_intf.h" 10 11 #include "hinic3_mgmt_interface.h" 11 12 ··· 36 35 u64 ci_dma_base; 37 36 }; 38 37 38 + enum mag_cmd_port_an { 39 + PORT_CFG_AN_ON = 1, 40 + }; 41 + 42 + /* mag supported/advertised link mode bitmap */ 43 + enum mag_cmd_link_mode { 44 + LINK_MODE_GE = 0, 45 + LINK_MODE_10GE_BASE_R = 1, 46 + LINK_MODE_25GE_BASE_R = 2, 47 + LINK_MODE_40GE_BASE_R4 = 3, 48 + LINK_MODE_50GE_BASE_R = 4, 49 + LINK_MODE_50GE_BASE_R2 = 5, 50 + LINK_MODE_100GE_BASE_R = 6, 51 + LINK_MODE_100GE_BASE_R2 = 7, 52 + LINK_MODE_100GE_BASE_R4 = 8, 53 + LINK_MODE_200GE_BASE_R2 = 9, 54 + LINK_MODE_200GE_BASE_R4 = 10, 55 + LINK_MODE_MAX_NUMBERS, 56 + 57 + LINK_MODE_UNKNOWN = 0xFFFF 58 + }; 59 + 60 + struct mag_cmd_get_port_info { 61 + struct mgmt_msg_head head; 62 + 63 + u8 port_id; 64 + u8 rsvd0[3]; 65 + 66 + u8 wire_type; 67 + u8 an_support; 68 + u8 an_en; 69 + u8 duplex; 70 + 71 + u8 speed; 72 + u8 fec; 73 + u8 lanes; 74 + u8 rsvd1; 75 + 76 + u32 supported_mode; 77 + u32 advertised_mode; 78 + u8 rsvd2[8]; 79 + }; 80 + 39 81 #define MAG_CMD_PORT_DISABLE 0x0 40 82 #define MAG_CMD_TX_ENABLE 0x1 41 83 #define MAG_CMD_RX_ENABLE 0x2 ··· 96 52 u8 rsvd1[3]; 97 53 }; 98 54 55 + /* xsfp wire type, refers to cmis protocol definition */ 56 + enum mag_wire_type { 57 + MAG_CMD_WIRE_TYPE_UNKNOWN = 0x0, 58 + MAG_CMD_WIRE_TYPE_MM = 0x1, 59 + MAG_CMD_WIRE_TYPE_SM = 0x2, 60 + MAG_CMD_WIRE_TYPE_COPPER = 0x3, 61 + MAG_CMD_WIRE_TYPE_ACC = 0x4, 62 + MAG_CMD_WIRE_TYPE_BASET = 0x5, 63 + MAG_CMD_WIRE_TYPE_AOC = 0x40, 64 + MAG_CMD_WIRE_TYPE_ELECTRIC = 0x41, 65 + MAG_CMD_WIRE_TYPE_BACKPLANE = 0x42 66 + }; 67 + 68 + #define XSFP_INFO_MAX_SIZE 640 69 + struct mag_cmd_get_xsfp_info { 70 + struct mgmt_msg_head head; 71 + 72 + u8 port_id; 73 + u8 wire_type; 74 + u16 out_len; 75 + u32 rsvd; 76 + u8 sfp_info[XSFP_INFO_MAX_SIZE]; 77 + }; 78 + 79 + struct mag_cmd_get_xsfp_present { 80 + struct mgmt_msg_head head; 81 + 82 + u8 port_id; 83 + /* 0:present, 1:absent */ 84 + u8 abs_status; 85 + u8 rsvd[2]; 86 + }; 87 + 99 88 enum link_err_type { 100 89 LINK_ERR_MODULE_UNRECOGENIZED, 101 90 LINK_ERR_NUM, ··· 144 67 struct hinic3_port_module_event { 145 68 enum port_module_event_type type; 146 69 enum link_err_type err_type; 70 + }; 71 + 72 + struct hinic3_nic_port_info { 73 + u8 port_type; 74 + u8 autoneg_cap; 75 + u8 autoneg_state; 76 + u8 duplex; 77 + u8 speed; 78 + u8 fec; 79 + u32 supported_mode; 80 + u32 advertised_mode; 81 + }; 82 + 83 + struct hinic3_nic_pause_config { 84 + u8 auto_neg; 85 + u8 rx_pause; 86 + u8 tx_pause; 87 + }; 88 + 89 + struct hinic3_nic_cfg { 90 + /* Valid when pfc is disabled */ 91 + bool pause_set; 92 + struct hinic3_nic_pause_config nic_pause; 93 + 94 + u8 pfc_en; 95 + u8 pfc_bitmap; 96 + 97 + struct hinic3_nic_port_info port_info; 147 98 }; 148 99 149 100 int hinic3_get_nic_feature_from_hw(struct hinic3_nic_dev *nic_dev); ··· 205 100 int hinic3_sync_dcb_state(struct hinic3_hwdev *hwdev, u8 op_code, u8 state); 206 101 int hinic3_set_port_enable(struct hinic3_hwdev *hwdev, bool enable); 207 102 int hinic3_get_link_status(struct hinic3_hwdev *hwdev, bool *link_status_up); 103 + int hinic3_get_port_info(struct hinic3_hwdev *hwdev, 104 + struct hinic3_nic_port_info *port_info); 208 105 int hinic3_set_vport_enable(struct hinic3_hwdev *hwdev, u16 func_id, 209 106 bool enable); 210 107 int hinic3_add_vlan(struct hinic3_hwdev *hwdev, u16 vlan_id, u16 func_id); 211 108 int hinic3_del_vlan(struct hinic3_hwdev *hwdev, u16 vlan_id, u16 func_id); 109 + 110 + int hinic3_get_pause_info(struct hinic3_nic_dev *nic_dev, 111 + struct hinic3_nic_pause_config *nic_pause); 212 112 213 113 #endif
+3
drivers/net/ethernet/huawei/hinic3/hinic3_nic_dev.h
··· 101 101 struct hinic3_hwdev *hwdev; 102 102 struct hinic3_nic_io *nic_io; 103 103 104 + u32 msg_enable; 104 105 u16 max_qps; 105 106 u16 rx_buf_len; 106 107 u32 lro_replenish_thld; ··· 148 147 149 148 void hinic3_set_rx_mode_work(struct work_struct *work); 150 149 void hinic3_clean_mac_list_filter(struct net_device *netdev); 150 + 151 + void hinic3_set_ethtool_ops(struct net_device *netdev); 151 152 152 153 #endif
+1
drivers/net/ethernet/huawei/hinic3/hinic3_pci_id_tbl.h
··· 4 4 #ifndef _HINIC3_PCI_ID_TBL_H_ 5 5 #define _HINIC3_PCI_ID_TBL_H_ 6 6 7 + #define PCI_DEV_ID_HINIC3_PF 0x0222 7 8 #define PCI_DEV_ID_HINIC3_VF 0x375F 8 9 9 10 #endif
+1 -1
drivers/net/ethernet/huawei/hinic3/hinic3_rss.c
··· 132 132 static int hinic3_set_rss_type(struct hinic3_hwdev *hwdev, 133 133 struct hinic3_rss_type rss_type) 134 134 { 135 - struct l2nic_cmd_set_rss_ctx_tbl ctx_tbl = {}; 135 + struct l2nic_cmd_rss_ctx_tbl ctx_tbl = {}; 136 136 struct mgmt_msg_params msg_params = {}; 137 137 u32 ctx; 138 138 int err;
+15
drivers/net/ethernet/huawei/hinic3/hinic3_rx.c
··· 328 328 u32 ip_type = RQ_CQE_OFFOLAD_TYPE_GET(offload_type, IP_TYPE); 329 329 u32 csum_err = RQ_CQE_STATUS_GET(status, CSUM_ERR); 330 330 struct net_device *netdev = rxq->netdev; 331 + bool l2_tunnel; 331 332 332 333 if (!(netdev->features & NETIF_F_RXCSUM)) 333 334 return; ··· 351 350 case HINIC3_RX_UDP_PKT: 352 351 case HINIC3_RX_SCTP_PKT: 353 352 skb->ip_summed = CHECKSUM_UNNECESSARY; 353 + l2_tunnel = HINIC3_GET_RX_TUNNEL_PKT_FORMAT(offload_type) == 354 + HINIC3_RX_PKT_FORMAT_VXLAN ? 1 : 0; 355 + if (l2_tunnel) { 356 + /* If we checked the outer header let the stack know */ 357 + skb->csum_level = 1; 358 + } 354 359 break; 355 360 default: 356 361 skb->ip_summed = CHECKSUM_NONE; ··· 396 389 397 390 offload_type = le32_to_cpu(rx_cqe->offload_type); 398 391 hinic3_rx_csum(rxq, offload_type, status, skb); 392 + 393 + if ((netdev->features & NETIF_F_HW_VLAN_CTAG_RX) && 394 + RQ_CQE_OFFOLAD_TYPE_GET(offload_type, VLAN_EN)) { 395 + u16 vid = RQ_CQE_SGE_GET(vlan_len, VLAN); 396 + 397 + /* if the packet is a vlan pkt, the vid may be 0 */ 398 + __vlan_hwaccel_put_tag(skb, htons(ETH_P_8021Q), vid); 399 + } 399 400 400 401 num_lro = RQ_CQE_STATUS_GET(status, NUM_LRO); 401 402 if (num_lro)
+3
drivers/net/ethernet/huawei/hinic3/hinic3_rx.h
··· 15 15 #define RQ_CQE_OFFOLAD_TYPE_GET(val, member) \ 16 16 FIELD_GET(RQ_CQE_OFFOLAD_TYPE_##member##_MASK, val) 17 17 18 + #define HINIC3_GET_RX_TUNNEL_PKT_FORMAT(offload_type) \ 19 + RQ_CQE_OFFOLAD_TYPE_GET(offload_type, TUNNEL_PKT_FORMAT) 20 + 18 21 #define RQ_CQE_SGE_VLAN_MASK GENMASK(15, 0) 19 22 #define RQ_CQE_SGE_LEN_MASK GENMASK(31, 16) 20 23 #define RQ_CQE_SGE_GET(val, member) \