| .. | .. |
|---|
| 33 | 33 | |
|---|
| 34 | 34 | static int lio_reset_queues(struct net_device *netdev, uint32_t num_qs); |
|---|
| 35 | 35 | |
|---|
| 36 | | -struct oct_intrmod_context { |
|---|
| 37 | | - int octeon_id; |
|---|
| 38 | | - wait_queue_head_t wc; |
|---|
| 39 | | - int cond; |
|---|
| 40 | | - int status; |
|---|
| 41 | | -}; |
|---|
| 42 | | - |
|---|
| 43 | 36 | struct oct_intrmod_resp { |
|---|
| 44 | 37 | u64 rh; |
|---|
| 45 | 38 | struct oct_intrmod_cfg intrmod; |
|---|
| 46 | 39 | u64 status; |
|---|
| 47 | | -}; |
|---|
| 48 | | - |
|---|
| 49 | | -struct oct_mdio_cmd_context { |
|---|
| 50 | | - int octeon_id; |
|---|
| 51 | | - wait_queue_head_t wc; |
|---|
| 52 | | - int cond; |
|---|
| 53 | 40 | }; |
|---|
| 54 | 41 | |
|---|
| 55 | 42 | struct oct_mdio_cmd_resp { |
|---|
| .. | .. |
|---|
| 124 | 111 | "mac_tx_one_collision", |
|---|
| 125 | 112 | "mac_tx_multi_collision", |
|---|
| 126 | 113 | "mac_tx_max_collision_fail", |
|---|
| 127 | | - "mac_tx_max_deferal_fail", |
|---|
| 114 | + "mac_tx_max_deferral_fail", |
|---|
| 128 | 115 | "mac_tx_fifo_err", |
|---|
| 129 | 116 | "mac_tx_runts", |
|---|
| 130 | 117 | |
|---|
| .. | .. |
|---|
| 257 | 244 | linfo->link.s.if_mode == INTERFACE_MODE_XLAUI || |
|---|
| 258 | 245 | linfo->link.s.if_mode == INTERFACE_MODE_XFI) { |
|---|
| 259 | 246 | dev_dbg(&oct->pci_dev->dev, "ecmd->base.transceiver is XCVR_EXTERNAL\n"); |
|---|
| 247 | + ecmd->base.transceiver = XCVR_EXTERNAL; |
|---|
| 260 | 248 | } else { |
|---|
| 261 | 249 | dev_err(&oct->pci_dev->dev, "Unknown link interface mode: %d\n", |
|---|
| 262 | 250 | linfo->link.s.if_mode); |
|---|
| .. | .. |
|---|
| 290 | 278 | 10000baseCR_Full); |
|---|
| 291 | 279 | } |
|---|
| 292 | 280 | |
|---|
| 293 | | - if (oct->no_speed_setting == 0) |
|---|
| 281 | + if (oct->no_speed_setting == 0) { |
|---|
| 294 | 282 | liquidio_get_speed(lio); |
|---|
| 295 | | - else |
|---|
| 283 | + liquidio_get_fec(lio); |
|---|
| 284 | + } else { |
|---|
| 296 | 285 | oct->speed_setting = 25; |
|---|
| 286 | + } |
|---|
| 297 | 287 | |
|---|
| 298 | 288 | if (oct->speed_setting == 10) { |
|---|
| 299 | 289 | ethtool_link_ksettings_add_link_mode |
|---|
| .. | .. |
|---|
| 316 | 306 | ethtool_link_ksettings_add_link_mode |
|---|
| 317 | 307 | (ecmd, advertising, |
|---|
| 318 | 308 | 25000baseCR_Full); |
|---|
| 309 | + } |
|---|
| 310 | + |
|---|
| 311 | + if (oct->no_speed_setting) |
|---|
| 312 | + break; |
|---|
| 313 | + |
|---|
| 314 | + ethtool_link_ksettings_add_link_mode |
|---|
| 315 | + (ecmd, supported, FEC_RS); |
|---|
| 316 | + ethtool_link_ksettings_add_link_mode |
|---|
| 317 | + (ecmd, supported, FEC_NONE); |
|---|
| 318 | + /*FEC_OFF*/ |
|---|
| 319 | + if (oct->props[lio->ifidx].fec == 1) { |
|---|
| 320 | + /* ETHTOOL_FEC_RS */ |
|---|
| 321 | + ethtool_link_ksettings_add_link_mode |
|---|
| 322 | + (ecmd, advertising, FEC_RS); |
|---|
| 323 | + } else { |
|---|
| 324 | + /* ETHTOOL_FEC_OFF */ |
|---|
| 325 | + ethtool_link_ksettings_add_link_mode |
|---|
| 326 | + (ecmd, advertising, FEC_NONE); |
|---|
| 319 | 327 | } |
|---|
| 320 | 328 | } else { /* VF */ |
|---|
| 321 | 329 | if (linfo->link.s.speed == 10000) { |
|---|
| .. | .. |
|---|
| 434 | 442 | |
|---|
| 435 | 443 | memset(drvinfo, 0, sizeof(struct ethtool_drvinfo)); |
|---|
| 436 | 444 | strcpy(drvinfo->driver, "liquidio"); |
|---|
| 437 | | - strcpy(drvinfo->version, LIQUIDIO_VERSION); |
|---|
| 438 | 445 | strncpy(drvinfo->fw_version, oct->fw_info.liquidio_firmware_version, |
|---|
| 439 | 446 | ETHTOOL_FWVERS_LEN); |
|---|
| 440 | 447 | strncpy(drvinfo->bus_info, pci_name(oct->pci_dev), 32); |
|---|
| .. | .. |
|---|
| 451 | 458 | |
|---|
| 452 | 459 | memset(drvinfo, 0, sizeof(struct ethtool_drvinfo)); |
|---|
| 453 | 460 | strcpy(drvinfo->driver, "liquidio_vf"); |
|---|
| 454 | | - strcpy(drvinfo->version, LIQUIDIO_VERSION); |
|---|
| 455 | 461 | strncpy(drvinfo->fw_version, oct->fw_info.liquidio_firmware_version, |
|---|
| 456 | 462 | ETHTOOL_FWVERS_LEN); |
|---|
| 457 | 463 | strncpy(drvinfo->bus_info, pci_name(oct->pci_dev), 32); |
|---|
| .. | .. |
|---|
| 472 | 478 | nctrl.ncmd.s.param1 = num_queues; |
|---|
| 473 | 479 | nctrl.ncmd.s.param2 = num_queues; |
|---|
| 474 | 480 | nctrl.iq_no = lio->linfo.txpciq[0].s.q_no; |
|---|
| 475 | | - nctrl.wait_time = 100; |
|---|
| 476 | 481 | nctrl.netpndev = (u64)netdev; |
|---|
| 477 | 482 | nctrl.cb_fn = liquidio_link_ctrl_cmd_completion; |
|---|
| 478 | 483 | |
|---|
| 479 | 484 | ret = octnet_send_nic_ctrl_pkt(lio->oct_dev, &nctrl); |
|---|
| 480 | | - if (ret < 0) { |
|---|
| 485 | + if (ret) { |
|---|
| 481 | 486 | dev_err(&oct->pci_dev->dev, "Failed to send Queue reset command (ret: 0x%x)\n", |
|---|
| 482 | 487 | ret); |
|---|
| 483 | 488 | return -1; |
|---|
| .. | .. |
|---|
| 708 | 713 | nctrl.ncmd.s.param1 = addr; |
|---|
| 709 | 714 | nctrl.ncmd.s.param2 = val; |
|---|
| 710 | 715 | nctrl.iq_no = lio->linfo.txpciq[0].s.q_no; |
|---|
| 711 | | - nctrl.wait_time = 100; |
|---|
| 712 | 716 | nctrl.netpndev = (u64)netdev; |
|---|
| 713 | 717 | nctrl.cb_fn = liquidio_link_ctrl_cmd_completion; |
|---|
| 714 | 718 | |
|---|
| 715 | 719 | ret = octnet_send_nic_ctrl_pkt(lio->oct_dev, &nctrl); |
|---|
| 716 | | - if (ret < 0) { |
|---|
| 717 | | - dev_err(&oct->pci_dev->dev, "Failed to configure gpio value\n"); |
|---|
| 720 | + if (ret) { |
|---|
| 721 | + dev_err(&oct->pci_dev->dev, |
|---|
| 722 | + "Failed to configure gpio value, ret=%d\n", ret); |
|---|
| 718 | 723 | return -EINVAL; |
|---|
| 719 | 724 | } |
|---|
| 720 | 725 | |
|---|
| .. | .. |
|---|
| 734 | 739 | nctrl.ncmd.s.cmd = OCTNET_CMD_ID_ACTIVE; |
|---|
| 735 | 740 | nctrl.ncmd.s.param1 = val; |
|---|
| 736 | 741 | nctrl.iq_no = lio->linfo.txpciq[0].s.q_no; |
|---|
| 737 | | - nctrl.wait_time = 100; |
|---|
| 738 | 742 | nctrl.netpndev = (u64)netdev; |
|---|
| 739 | 743 | nctrl.cb_fn = liquidio_link_ctrl_cmd_completion; |
|---|
| 740 | 744 | |
|---|
| 741 | 745 | ret = octnet_send_nic_ctrl_pkt(lio->oct_dev, &nctrl); |
|---|
| 742 | | - if (ret < 0) { |
|---|
| 743 | | - dev_err(&oct->pci_dev->dev, "Failed to configure gpio value\n"); |
|---|
| 746 | + if (ret) { |
|---|
| 747 | + dev_err(&oct->pci_dev->dev, |
|---|
| 748 | + "Failed to configure gpio value, ret=%d\n", ret); |
|---|
| 744 | 749 | return -EINVAL; |
|---|
| 745 | 750 | } |
|---|
| 746 | 751 | |
|---|
| 747 | 752 | return 0; |
|---|
| 748 | | -} |
|---|
| 749 | | - |
|---|
| 750 | | -/* Callback for when mdio command response arrives |
|---|
| 751 | | - */ |
|---|
| 752 | | -static void octnet_mdio_resp_callback(struct octeon_device *oct, |
|---|
| 753 | | - u32 status, |
|---|
| 754 | | - void *buf) |
|---|
| 755 | | -{ |
|---|
| 756 | | - struct oct_mdio_cmd_context *mdio_cmd_ctx; |
|---|
| 757 | | - struct octeon_soft_command *sc = (struct octeon_soft_command *)buf; |
|---|
| 758 | | - |
|---|
| 759 | | - mdio_cmd_ctx = (struct oct_mdio_cmd_context *)sc->ctxptr; |
|---|
| 760 | | - |
|---|
| 761 | | - oct = lio_get_device(mdio_cmd_ctx->octeon_id); |
|---|
| 762 | | - if (status) { |
|---|
| 763 | | - dev_err(&oct->pci_dev->dev, "MIDO instruction failed. Status: %llx\n", |
|---|
| 764 | | - CVM_CAST64(status)); |
|---|
| 765 | | - WRITE_ONCE(mdio_cmd_ctx->cond, -1); |
|---|
| 766 | | - } else { |
|---|
| 767 | | - WRITE_ONCE(mdio_cmd_ctx->cond, 1); |
|---|
| 768 | | - } |
|---|
| 769 | | - wake_up_interruptible(&mdio_cmd_ctx->wc); |
|---|
| 770 | 753 | } |
|---|
| 771 | 754 | |
|---|
| 772 | 755 | /* This routine provides PHY access routines for |
|---|
| .. | .. |
|---|
| 778 | 761 | struct octeon_device *oct_dev = lio->oct_dev; |
|---|
| 779 | 762 | struct octeon_soft_command *sc; |
|---|
| 780 | 763 | struct oct_mdio_cmd_resp *mdio_cmd_rsp; |
|---|
| 781 | | - struct oct_mdio_cmd_context *mdio_cmd_ctx; |
|---|
| 782 | 764 | struct oct_mdio_cmd *mdio_cmd; |
|---|
| 783 | 765 | int retval = 0; |
|---|
| 784 | 766 | |
|---|
| 785 | 767 | sc = (struct octeon_soft_command *) |
|---|
| 786 | 768 | octeon_alloc_soft_command(oct_dev, |
|---|
| 787 | 769 | sizeof(struct oct_mdio_cmd), |
|---|
| 788 | | - sizeof(struct oct_mdio_cmd_resp), |
|---|
| 789 | | - sizeof(struct oct_mdio_cmd_context)); |
|---|
| 770 | + sizeof(struct oct_mdio_cmd_resp), 0); |
|---|
| 790 | 771 | |
|---|
| 791 | 772 | if (!sc) |
|---|
| 792 | 773 | return -ENOMEM; |
|---|
| 793 | 774 | |
|---|
| 794 | | - mdio_cmd_ctx = (struct oct_mdio_cmd_context *)sc->ctxptr; |
|---|
| 795 | 775 | mdio_cmd_rsp = (struct oct_mdio_cmd_resp *)sc->virtrptr; |
|---|
| 796 | 776 | mdio_cmd = (struct oct_mdio_cmd *)sc->virtdptr; |
|---|
| 797 | 777 | |
|---|
| 798 | | - WRITE_ONCE(mdio_cmd_ctx->cond, 0); |
|---|
| 799 | | - mdio_cmd_ctx->octeon_id = lio_get_device_id(oct_dev); |
|---|
| 800 | 778 | mdio_cmd->op = op; |
|---|
| 801 | 779 | mdio_cmd->mdio_addr = loc; |
|---|
| 802 | 780 | if (op) |
|---|
| .. | .. |
|---|
| 808 | 786 | octeon_prepare_soft_command(oct_dev, sc, OPCODE_NIC, OPCODE_NIC_MDIO45, |
|---|
| 809 | 787 | 0, 0, 0); |
|---|
| 810 | 788 | |
|---|
| 811 | | - sc->wait_time = 1000; |
|---|
| 812 | | - sc->callback = octnet_mdio_resp_callback; |
|---|
| 813 | | - sc->callback_arg = sc; |
|---|
| 814 | | - |
|---|
| 815 | | - init_waitqueue_head(&mdio_cmd_ctx->wc); |
|---|
| 789 | + init_completion(&sc->complete); |
|---|
| 790 | + sc->sc_status = OCTEON_REQUEST_PENDING; |
|---|
| 816 | 791 | |
|---|
| 817 | 792 | retval = octeon_send_soft_command(oct_dev, sc); |
|---|
| 818 | | - |
|---|
| 819 | 793 | if (retval == IQ_SEND_FAILED) { |
|---|
| 820 | 794 | dev_err(&oct_dev->pci_dev->dev, |
|---|
| 821 | 795 | "octnet_mdio45_access instruction failed status: %x\n", |
|---|
| 822 | 796 | retval); |
|---|
| 823 | | - retval = -EBUSY; |
|---|
| 797 | + octeon_free_soft_command(oct_dev, sc); |
|---|
| 798 | + return -EBUSY; |
|---|
| 824 | 799 | } else { |
|---|
| 825 | 800 | /* Sleep on a wait queue till the cond flag indicates that the |
|---|
| 826 | 801 | * response arrived |
|---|
| 827 | 802 | */ |
|---|
| 828 | | - sleep_cond(&mdio_cmd_ctx->wc, &mdio_cmd_ctx->cond); |
|---|
| 803 | + retval = wait_for_sc_completion_timeout(oct_dev, sc, 0); |
|---|
| 804 | + if (retval) |
|---|
| 805 | + return retval; |
|---|
| 806 | + |
|---|
| 829 | 807 | retval = mdio_cmd_rsp->status; |
|---|
| 830 | 808 | if (retval) { |
|---|
| 831 | | - dev_err(&oct_dev->pci_dev->dev, "octnet mdio45 access failed\n"); |
|---|
| 832 | | - retval = -EBUSY; |
|---|
| 833 | | - } else { |
|---|
| 834 | | - octeon_swap_8B_data((u64 *)(&mdio_cmd_rsp->resp), |
|---|
| 835 | | - sizeof(struct oct_mdio_cmd) / 8); |
|---|
| 836 | | - |
|---|
| 837 | | - if (READ_ONCE(mdio_cmd_ctx->cond) == 1) { |
|---|
| 838 | | - if (!op) |
|---|
| 839 | | - *value = mdio_cmd_rsp->resp.value1; |
|---|
| 840 | | - } else { |
|---|
| 841 | | - retval = -EINVAL; |
|---|
| 842 | | - } |
|---|
| 809 | + dev_err(&oct_dev->pci_dev->dev, |
|---|
| 810 | + "octnet mdio45 access failed: %x\n", retval); |
|---|
| 811 | + WRITE_ONCE(sc->caller_is_done, true); |
|---|
| 812 | + return -EBUSY; |
|---|
| 843 | 813 | } |
|---|
| 844 | | - } |
|---|
| 845 | 814 | |
|---|
| 846 | | - octeon_free_soft_command(oct_dev, sc); |
|---|
| 815 | + octeon_swap_8B_data((u64 *)(&mdio_cmd_rsp->resp), |
|---|
| 816 | + sizeof(struct oct_mdio_cmd) / 8); |
|---|
| 817 | + |
|---|
| 818 | + if (!op) |
|---|
| 819 | + *value = mdio_cmd_rsp->resp.value1; |
|---|
| 820 | + |
|---|
| 821 | + WRITE_ONCE(sc->caller_is_done, true); |
|---|
| 822 | + } |
|---|
| 847 | 823 | |
|---|
| 848 | 824 | return retval; |
|---|
| 849 | 825 | } |
|---|
| .. | .. |
|---|
| 1007 | 983 | static int lio_23xx_reconfigure_queue_count(struct lio *lio) |
|---|
| 1008 | 984 | { |
|---|
| 1009 | 985 | struct octeon_device *oct = lio->oct_dev; |
|---|
| 1010 | | - struct liquidio_if_cfg_context *ctx; |
|---|
| 1011 | | - u32 resp_size, ctx_size, data_size; |
|---|
| 986 | + u32 resp_size, data_size; |
|---|
| 1012 | 987 | struct liquidio_if_cfg_resp *resp; |
|---|
| 1013 | 988 | struct octeon_soft_command *sc; |
|---|
| 1014 | 989 | union oct_nic_if_cfg if_cfg; |
|---|
| .. | .. |
|---|
| 1018 | 993 | int j; |
|---|
| 1019 | 994 | |
|---|
| 1020 | 995 | resp_size = sizeof(struct liquidio_if_cfg_resp); |
|---|
| 1021 | | - ctx_size = sizeof(struct liquidio_if_cfg_context); |
|---|
| 1022 | 996 | data_size = sizeof(struct lio_version); |
|---|
| 1023 | 997 | sc = (struct octeon_soft_command *) |
|---|
| 1024 | 998 | octeon_alloc_soft_command(oct, data_size, |
|---|
| 1025 | | - resp_size, ctx_size); |
|---|
| 999 | + resp_size, 0); |
|---|
| 1026 | 1000 | if (!sc) { |
|---|
| 1027 | 1001 | dev_err(&oct->pci_dev->dev, "%s: Failed to allocate soft command\n", |
|---|
| 1028 | 1002 | __func__); |
|---|
| .. | .. |
|---|
| 1030 | 1004 | } |
|---|
| 1031 | 1005 | |
|---|
| 1032 | 1006 | resp = (struct liquidio_if_cfg_resp *)sc->virtrptr; |
|---|
| 1033 | | - ctx = (struct liquidio_if_cfg_context *)sc->ctxptr; |
|---|
| 1034 | 1007 | vdata = (struct lio_version *)sc->virtdptr; |
|---|
| 1035 | 1008 | |
|---|
| 1036 | 1009 | vdata->major = (__force u16)cpu_to_be16(LIQUIDIO_BASE_MAJOR_VERSION); |
|---|
| .. | .. |
|---|
| 1038 | 1011 | vdata->micro = (__force u16)cpu_to_be16(LIQUIDIO_BASE_MICRO_VERSION); |
|---|
| 1039 | 1012 | |
|---|
| 1040 | 1013 | ifidx_or_pfnum = oct->pf_num; |
|---|
| 1041 | | - WRITE_ONCE(ctx->cond, 0); |
|---|
| 1042 | | - ctx->octeon_id = lio_get_device_id(oct); |
|---|
| 1043 | | - init_waitqueue_head(&ctx->wc); |
|---|
| 1044 | 1014 | |
|---|
| 1045 | 1015 | if_cfg.u64 = 0; |
|---|
| 1046 | 1016 | if_cfg.s.num_iqueues = oct->sriov_info.num_pf_rings; |
|---|
| .. | .. |
|---|
| 1052 | 1022 | octeon_prepare_soft_command(oct, sc, OPCODE_NIC, |
|---|
| 1053 | 1023 | OPCODE_NIC_QCOUNT_UPDATE, 0, |
|---|
| 1054 | 1024 | if_cfg.u64, 0); |
|---|
| 1055 | | - sc->callback = lio_if_cfg_callback; |
|---|
| 1056 | | - sc->callback_arg = sc; |
|---|
| 1057 | | - sc->wait_time = LIO_IFCFG_WAIT_TIME; |
|---|
| 1025 | + |
|---|
| 1026 | + init_completion(&sc->complete); |
|---|
| 1027 | + sc->sc_status = OCTEON_REQUEST_PENDING; |
|---|
| 1058 | 1028 | |
|---|
| 1059 | 1029 | retval = octeon_send_soft_command(oct, sc); |
|---|
| 1060 | 1030 | if (retval == IQ_SEND_FAILED) { |
|---|
| 1061 | 1031 | dev_err(&oct->pci_dev->dev, |
|---|
| 1062 | | - "iq/oq config failed status: %x\n", |
|---|
| 1032 | + "Sending iq/oq config failed status: %x\n", |
|---|
| 1063 | 1033 | retval); |
|---|
| 1064 | | - goto qcount_update_fail; |
|---|
| 1034 | + octeon_free_soft_command(oct, sc); |
|---|
| 1035 | + return -EIO; |
|---|
| 1065 | 1036 | } |
|---|
| 1066 | 1037 | |
|---|
| 1067 | | - if (sleep_cond(&ctx->wc, &ctx->cond) == -EINTR) { |
|---|
| 1068 | | - dev_err(&oct->pci_dev->dev, "Wait interrupted\n"); |
|---|
| 1069 | | - return -1; |
|---|
| 1070 | | - } |
|---|
| 1038 | + retval = wait_for_sc_completion_timeout(oct, sc, 0); |
|---|
| 1039 | + if (retval) |
|---|
| 1040 | + return retval; |
|---|
| 1071 | 1041 | |
|---|
| 1072 | 1042 | retval = resp->status; |
|---|
| 1073 | 1043 | if (retval) { |
|---|
| 1074 | | - dev_err(&oct->pci_dev->dev, "iq/oq config failed\n"); |
|---|
| 1075 | | - goto qcount_update_fail; |
|---|
| 1044 | + dev_err(&oct->pci_dev->dev, |
|---|
| 1045 | + "iq/oq config failed: %x\n", retval); |
|---|
| 1046 | + WRITE_ONCE(sc->caller_is_done, true); |
|---|
| 1047 | + return -1; |
|---|
| 1076 | 1048 | } |
|---|
| 1077 | 1049 | |
|---|
| 1078 | 1050 | octeon_swap_8B_data((u64 *)(&resp->cfg_info), |
|---|
| .. | .. |
|---|
| 1097 | 1069 | lio->txq = lio->linfo.txpciq[0].s.q_no; |
|---|
| 1098 | 1070 | lio->rxq = lio->linfo.rxpciq[0].s.q_no; |
|---|
| 1099 | 1071 | |
|---|
| 1100 | | - octeon_free_soft_command(oct, sc); |
|---|
| 1101 | 1072 | dev_info(&oct->pci_dev->dev, "Queue count updated to %d\n", |
|---|
| 1102 | 1073 | lio->linfo.num_rxpciq); |
|---|
| 1103 | 1074 | |
|---|
| 1075 | + WRITE_ONCE(sc->caller_is_done, true); |
|---|
| 1076 | + |
|---|
| 1104 | 1077 | return 0; |
|---|
| 1105 | | - |
|---|
| 1106 | | -qcount_update_fail: |
|---|
| 1107 | | - octeon_free_soft_command(oct, sc); |
|---|
| 1108 | | - |
|---|
| 1109 | | - return -1; |
|---|
| 1110 | 1078 | } |
|---|
| 1111 | 1079 | |
|---|
| 1112 | 1080 | static int lio_reset_queues(struct net_device *netdev, uint32_t num_qs) |
|---|
| .. | .. |
|---|
| 1166 | 1134 | * steps like updating sriov_info for the octeon device need to be done. |
|---|
| 1167 | 1135 | */ |
|---|
| 1168 | 1136 | if (queue_count_update) { |
|---|
| 1137 | + cleanup_rx_oom_poll_fn(netdev); |
|---|
| 1138 | + |
|---|
| 1169 | 1139 | lio_delete_glists(lio); |
|---|
| 1170 | 1140 | |
|---|
| 1171 | 1141 | /* Delete mbox for PF which is SRIOV disabled because sriov_info |
|---|
| .. | .. |
|---|
| 1263 | 1233 | if (lio_setup_glists(oct, lio, num_qs)) { |
|---|
| 1264 | 1234 | dev_err(&oct->pci_dev->dev, "Gather list allocation failed\n"); |
|---|
| 1265 | 1235 | return -1; |
|---|
| 1236 | + } |
|---|
| 1237 | + |
|---|
| 1238 | + if (setup_rx_oom_poll_fn(netdev)) { |
|---|
| 1239 | + dev_err(&oct->pci_dev->dev, "lio_setup_rx_oom_poll_fn failed\n"); |
|---|
| 1240 | + return 1; |
|---|
| 1266 | 1241 | } |
|---|
| 1267 | 1242 | |
|---|
| 1268 | 1243 | /* Send firmware the information about new number of queues |
|---|
| .. | .. |
|---|
| 1412 | 1387 | nctrl.ncmd.u64 = 0; |
|---|
| 1413 | 1388 | nctrl.ncmd.s.cmd = OCTNET_CMD_SET_FLOW_CTL; |
|---|
| 1414 | 1389 | nctrl.iq_no = lio->linfo.txpciq[0].s.q_no; |
|---|
| 1415 | | - nctrl.wait_time = 100; |
|---|
| 1416 | 1390 | nctrl.netpndev = (u64)netdev; |
|---|
| 1417 | 1391 | nctrl.cb_fn = liquidio_link_ctrl_cmd_completion; |
|---|
| 1418 | 1392 | |
|---|
| .. | .. |
|---|
| 1433 | 1407 | } |
|---|
| 1434 | 1408 | |
|---|
| 1435 | 1409 | ret = octnet_send_nic_ctrl_pkt(lio->oct_dev, &nctrl); |
|---|
| 1436 | | - if (ret < 0) { |
|---|
| 1437 | | - dev_err(&oct->pci_dev->dev, "Failed to set pause parameter\n"); |
|---|
| 1410 | + if (ret) { |
|---|
| 1411 | + dev_err(&oct->pci_dev->dev, |
|---|
| 1412 | + "Failed to set pause parameter, ret=%d\n", ret); |
|---|
| 1438 | 1413 | return -EINVAL; |
|---|
| 1439 | 1414 | } |
|---|
| 1440 | 1415 | |
|---|
| .. | .. |
|---|
| 1764 | 1739 | */ |
|---|
| 1765 | 1740 | data[i++] = lstats.rx_dropped; |
|---|
| 1766 | 1741 | /* sum of oct->instr_queue[iq_no]->stats.tx_dropped */ |
|---|
| 1767 | | - data[i++] = lstats.tx_dropped; |
|---|
| 1742 | + data[i++] = lstats.tx_dropped + |
|---|
| 1743 | + oct_dev->link_stats.fromhost.fw_err_drop; |
|---|
| 1768 | 1744 | |
|---|
| 1769 | 1745 | data[i++] = oct_dev->link_stats.fromwire.fw_total_mcast; |
|---|
| 1770 | 1746 | data[i++] = oct_dev->link_stats.fromhost.fw_total_mcast_sent; |
|---|
| .. | .. |
|---|
| 2013 | 1989 | } |
|---|
| 2014 | 1990 | } |
|---|
| 2015 | 1991 | |
|---|
| 2016 | | -/* Callback function for intrmod */ |
|---|
| 2017 | | -static void octnet_intrmod_callback(struct octeon_device *oct_dev, |
|---|
| 2018 | | - u32 status, |
|---|
| 2019 | | - void *ptr) |
|---|
| 2020 | | -{ |
|---|
| 2021 | | - struct octeon_soft_command *sc = (struct octeon_soft_command *)ptr; |
|---|
| 2022 | | - struct oct_intrmod_context *ctx; |
|---|
| 2023 | | - |
|---|
| 2024 | | - ctx = (struct oct_intrmod_context *)sc->ctxptr; |
|---|
| 2025 | | - |
|---|
| 2026 | | - ctx->status = status; |
|---|
| 2027 | | - |
|---|
| 2028 | | - WRITE_ONCE(ctx->cond, 1); |
|---|
| 2029 | | - |
|---|
| 2030 | | - /* This barrier is required to be sure that the response has been |
|---|
| 2031 | | - * written fully before waking up the handler |
|---|
| 2032 | | - */ |
|---|
| 2033 | | - wmb(); |
|---|
| 2034 | | - |
|---|
| 2035 | | - wake_up_interruptible(&ctx->wc); |
|---|
| 2036 | | -} |
|---|
| 2037 | | - |
|---|
| 2038 | 1992 | /* get interrupt moderation parameters */ |
|---|
| 2039 | 1993 | static int octnet_get_intrmod_cfg(struct lio *lio, |
|---|
| 2040 | 1994 | struct oct_intrmod_cfg *intr_cfg) |
|---|
| 2041 | 1995 | { |
|---|
| 2042 | 1996 | struct octeon_soft_command *sc; |
|---|
| 2043 | | - struct oct_intrmod_context *ctx; |
|---|
| 2044 | 1997 | struct oct_intrmod_resp *resp; |
|---|
| 2045 | 1998 | int retval; |
|---|
| 2046 | 1999 | struct octeon_device *oct_dev = lio->oct_dev; |
|---|
| .. | .. |
|---|
| 2049 | 2002 | sc = (struct octeon_soft_command *) |
|---|
| 2050 | 2003 | octeon_alloc_soft_command(oct_dev, |
|---|
| 2051 | 2004 | 0, |
|---|
| 2052 | | - sizeof(struct oct_intrmod_resp), |
|---|
| 2053 | | - sizeof(struct oct_intrmod_context)); |
|---|
| 2005 | + sizeof(struct oct_intrmod_resp), 0); |
|---|
| 2054 | 2006 | |
|---|
| 2055 | 2007 | if (!sc) |
|---|
| 2056 | 2008 | return -ENOMEM; |
|---|
| .. | .. |
|---|
| 2058 | 2010 | resp = (struct oct_intrmod_resp *)sc->virtrptr; |
|---|
| 2059 | 2011 | memset(resp, 0, sizeof(struct oct_intrmod_resp)); |
|---|
| 2060 | 2012 | |
|---|
| 2061 | | - ctx = (struct oct_intrmod_context *)sc->ctxptr; |
|---|
| 2062 | | - memset(ctx, 0, sizeof(struct oct_intrmod_context)); |
|---|
| 2063 | | - WRITE_ONCE(ctx->cond, 0); |
|---|
| 2064 | | - ctx->octeon_id = lio_get_device_id(oct_dev); |
|---|
| 2065 | | - init_waitqueue_head(&ctx->wc); |
|---|
| 2066 | | - |
|---|
| 2067 | 2013 | sc->iq_no = lio->linfo.txpciq[0].s.q_no; |
|---|
| 2068 | 2014 | |
|---|
| 2069 | 2015 | octeon_prepare_soft_command(oct_dev, sc, OPCODE_NIC, |
|---|
| 2070 | 2016 | OPCODE_NIC_INTRMOD_PARAMS, 0, 0, 0); |
|---|
| 2071 | 2017 | |
|---|
| 2072 | | - sc->callback = octnet_intrmod_callback; |
|---|
| 2073 | | - sc->callback_arg = sc; |
|---|
| 2074 | | - sc->wait_time = 1000; |
|---|
| 2018 | + init_completion(&sc->complete); |
|---|
| 2019 | + sc->sc_status = OCTEON_REQUEST_PENDING; |
|---|
| 2075 | 2020 | |
|---|
| 2076 | 2021 | retval = octeon_send_soft_command(oct_dev, sc); |
|---|
| 2077 | 2022 | if (retval == IQ_SEND_FAILED) { |
|---|
| .. | .. |
|---|
| 2082 | 2027 | /* Sleep on a wait queue till the cond flag indicates that the |
|---|
| 2083 | 2028 | * response arrived or timed-out. |
|---|
| 2084 | 2029 | */ |
|---|
| 2085 | | - if (sleep_cond(&ctx->wc, &ctx->cond) == -EINTR) { |
|---|
| 2086 | | - dev_err(&oct_dev->pci_dev->dev, "Wait interrupted\n"); |
|---|
| 2087 | | - goto intrmod_info_wait_intr; |
|---|
| 2088 | | - } |
|---|
| 2030 | + retval = wait_for_sc_completion_timeout(oct_dev, sc, 0); |
|---|
| 2031 | + if (retval) |
|---|
| 2032 | + return -ENODEV; |
|---|
| 2089 | 2033 | |
|---|
| 2090 | | - retval = ctx->status || resp->status; |
|---|
| 2091 | | - if (retval) { |
|---|
| 2034 | + if (resp->status) { |
|---|
| 2092 | 2035 | dev_err(&oct_dev->pci_dev->dev, |
|---|
| 2093 | 2036 | "Get interrupt moderation parameters failed\n"); |
|---|
| 2094 | | - goto intrmod_info_wait_fail; |
|---|
| 2037 | + WRITE_ONCE(sc->caller_is_done, true); |
|---|
| 2038 | + return -ENODEV; |
|---|
| 2095 | 2039 | } |
|---|
| 2096 | 2040 | |
|---|
| 2097 | 2041 | octeon_swap_8B_data((u64 *)&resp->intrmod, |
|---|
| 2098 | 2042 | (sizeof(struct oct_intrmod_cfg)) / 8); |
|---|
| 2099 | 2043 | memcpy(intr_cfg, &resp->intrmod, sizeof(struct oct_intrmod_cfg)); |
|---|
| 2100 | | - octeon_free_soft_command(oct_dev, sc); |
|---|
| 2044 | + WRITE_ONCE(sc->caller_is_done, true); |
|---|
| 2101 | 2045 | |
|---|
| 2102 | 2046 | return 0; |
|---|
| 2103 | | - |
|---|
| 2104 | | -intrmod_info_wait_fail: |
|---|
| 2105 | | - |
|---|
| 2106 | | - octeon_free_soft_command(oct_dev, sc); |
|---|
| 2107 | | - |
|---|
| 2108 | | -intrmod_info_wait_intr: |
|---|
| 2109 | | - |
|---|
| 2110 | | - return -ENODEV; |
|---|
| 2111 | 2047 | } |
|---|
| 2112 | 2048 | |
|---|
| 2113 | 2049 | /* Configure interrupt moderation parameters */ |
|---|
| .. | .. |
|---|
| 2115 | 2051 | struct oct_intrmod_cfg *intr_cfg) |
|---|
| 2116 | 2052 | { |
|---|
| 2117 | 2053 | struct octeon_soft_command *sc; |
|---|
| 2118 | | - struct oct_intrmod_context *ctx; |
|---|
| 2119 | 2054 | struct oct_intrmod_cfg *cfg; |
|---|
| 2120 | 2055 | int retval; |
|---|
| 2121 | 2056 | struct octeon_device *oct_dev = lio->oct_dev; |
|---|
| .. | .. |
|---|
| 2124 | 2059 | sc = (struct octeon_soft_command *) |
|---|
| 2125 | 2060 | octeon_alloc_soft_command(oct_dev, |
|---|
| 2126 | 2061 | sizeof(struct oct_intrmod_cfg), |
|---|
| 2127 | | - 0, |
|---|
| 2128 | | - sizeof(struct oct_intrmod_context)); |
|---|
| 2062 | + 16, 0); |
|---|
| 2129 | 2063 | |
|---|
| 2130 | 2064 | if (!sc) |
|---|
| 2131 | 2065 | return -ENOMEM; |
|---|
| 2132 | | - |
|---|
| 2133 | | - ctx = (struct oct_intrmod_context *)sc->ctxptr; |
|---|
| 2134 | | - |
|---|
| 2135 | | - WRITE_ONCE(ctx->cond, 0); |
|---|
| 2136 | | - ctx->octeon_id = lio_get_device_id(oct_dev); |
|---|
| 2137 | | - init_waitqueue_head(&ctx->wc); |
|---|
| 2138 | 2066 | |
|---|
| 2139 | 2067 | cfg = (struct oct_intrmod_cfg *)sc->virtdptr; |
|---|
| 2140 | 2068 | |
|---|
| .. | .. |
|---|
| 2146 | 2074 | octeon_prepare_soft_command(oct_dev, sc, OPCODE_NIC, |
|---|
| 2147 | 2075 | OPCODE_NIC_INTRMOD_CFG, 0, 0, 0); |
|---|
| 2148 | 2076 | |
|---|
| 2149 | | - sc->callback = octnet_intrmod_callback; |
|---|
| 2150 | | - sc->callback_arg = sc; |
|---|
| 2151 | | - sc->wait_time = 1000; |
|---|
| 2077 | + init_completion(&sc->complete); |
|---|
| 2078 | + sc->sc_status = OCTEON_REQUEST_PENDING; |
|---|
| 2152 | 2079 | |
|---|
| 2153 | 2080 | retval = octeon_send_soft_command(oct_dev, sc); |
|---|
| 2154 | 2081 | if (retval == IQ_SEND_FAILED) { |
|---|
| .. | .. |
|---|
| 2159 | 2086 | /* Sleep on a wait queue till the cond flag indicates that the |
|---|
| 2160 | 2087 | * response arrived or timed-out. |
|---|
| 2161 | 2088 | */ |
|---|
| 2162 | | - if (sleep_cond(&ctx->wc, &ctx->cond) != -EINTR) { |
|---|
| 2163 | | - retval = ctx->status; |
|---|
| 2164 | | - if (retval) |
|---|
| 2165 | | - dev_err(&oct_dev->pci_dev->dev, |
|---|
| 2166 | | - "intrmod config failed. Status: %llx\n", |
|---|
| 2167 | | - CVM_CAST64(retval)); |
|---|
| 2168 | | - else |
|---|
| 2169 | | - dev_info(&oct_dev->pci_dev->dev, |
|---|
| 2170 | | - "Rx-Adaptive Interrupt moderation %s\n", |
|---|
| 2171 | | - (intr_cfg->rx_enable) ? |
|---|
| 2172 | | - "enabled" : "disabled"); |
|---|
| 2089 | + retval = wait_for_sc_completion_timeout(oct_dev, sc, 0); |
|---|
| 2090 | + if (retval) |
|---|
| 2091 | + return retval; |
|---|
| 2173 | 2092 | |
|---|
| 2174 | | - octeon_free_soft_command(oct_dev, sc); |
|---|
| 2175 | | - |
|---|
| 2176 | | - return ((retval) ? -ENODEV : 0); |
|---|
| 2093 | + retval = sc->sc_status; |
|---|
| 2094 | + if (retval == 0) { |
|---|
| 2095 | + dev_info(&oct_dev->pci_dev->dev, |
|---|
| 2096 | + "Rx-Adaptive Interrupt moderation %s\n", |
|---|
| 2097 | + (intr_cfg->rx_enable) ? |
|---|
| 2098 | + "enabled" : "disabled"); |
|---|
| 2099 | + WRITE_ONCE(sc->caller_is_done, true); |
|---|
| 2100 | + return 0; |
|---|
| 2177 | 2101 | } |
|---|
| 2178 | 2102 | |
|---|
| 2179 | | - dev_err(&oct_dev->pci_dev->dev, "iq/oq config failed\n"); |
|---|
| 2180 | | - |
|---|
| 2181 | | - return -EINTR; |
|---|
| 2103 | + dev_err(&oct_dev->pci_dev->dev, |
|---|
| 2104 | + "intrmod config failed. Status: %x\n", retval); |
|---|
| 2105 | + WRITE_ONCE(sc->caller_is_done, true); |
|---|
| 2106 | + return -ENODEV; |
|---|
| 2182 | 2107 | } |
|---|
| 2183 | 2108 | |
|---|
| 2184 | 2109 | static int lio_get_intr_coalesce(struct net_device *netdev, |
|---|
| .. | .. |
|---|
| 3123 | 3048 | return 0; |
|---|
| 3124 | 3049 | } |
|---|
| 3125 | 3050 | |
|---|
| 3051 | +static int lio_get_fecparam(struct net_device *netdev, |
|---|
| 3052 | + struct ethtool_fecparam *fec) |
|---|
| 3053 | +{ |
|---|
| 3054 | + struct lio *lio = GET_LIO(netdev); |
|---|
| 3055 | + struct octeon_device *oct = lio->oct_dev; |
|---|
| 3056 | + |
|---|
| 3057 | + fec->active_fec = ETHTOOL_FEC_NONE; |
|---|
| 3058 | + fec->fec = ETHTOOL_FEC_NONE; |
|---|
| 3059 | + |
|---|
| 3060 | + if (oct->subsystem_id == OCTEON_CN2350_25GB_SUBSYS_ID || |
|---|
| 3061 | + oct->subsystem_id == OCTEON_CN2360_25GB_SUBSYS_ID) { |
|---|
| 3062 | + if (oct->no_speed_setting == 1) |
|---|
| 3063 | + return 0; |
|---|
| 3064 | + |
|---|
| 3065 | + liquidio_get_fec(lio); |
|---|
| 3066 | + fec->fec = (ETHTOOL_FEC_RS | ETHTOOL_FEC_OFF); |
|---|
| 3067 | + if (oct->props[lio->ifidx].fec == 1) |
|---|
| 3068 | + fec->active_fec = ETHTOOL_FEC_RS; |
|---|
| 3069 | + else |
|---|
| 3070 | + fec->active_fec = ETHTOOL_FEC_OFF; |
|---|
| 3071 | + } |
|---|
| 3072 | + |
|---|
| 3073 | + return 0; |
|---|
| 3074 | +} |
|---|
| 3075 | + |
|---|
| 3076 | +static int lio_set_fecparam(struct net_device *netdev, |
|---|
| 3077 | + struct ethtool_fecparam *fec) |
|---|
| 3078 | +{ |
|---|
| 3079 | + struct lio *lio = GET_LIO(netdev); |
|---|
| 3080 | + struct octeon_device *oct = lio->oct_dev; |
|---|
| 3081 | + |
|---|
| 3082 | + if (oct->subsystem_id == OCTEON_CN2350_25GB_SUBSYS_ID || |
|---|
| 3083 | + oct->subsystem_id == OCTEON_CN2360_25GB_SUBSYS_ID) { |
|---|
| 3084 | + if (oct->no_speed_setting == 1) |
|---|
| 3085 | + return -EOPNOTSUPP; |
|---|
| 3086 | + |
|---|
| 3087 | + if (fec->fec & ETHTOOL_FEC_OFF) |
|---|
| 3088 | + liquidio_set_fec(lio, 0); |
|---|
| 3089 | + else if (fec->fec & ETHTOOL_FEC_RS) |
|---|
| 3090 | + liquidio_set_fec(lio, 1); |
|---|
| 3091 | + else |
|---|
| 3092 | + return -EOPNOTSUPP; |
|---|
| 3093 | + } else { |
|---|
| 3094 | + return -EOPNOTSUPP; |
|---|
| 3095 | + } |
|---|
| 3096 | + |
|---|
| 3097 | + return 0; |
|---|
| 3098 | +} |
|---|
| 3099 | + |
|---|
| 3100 | +#define LIO_ETHTOOL_COALESCE (ETHTOOL_COALESCE_RX_USECS | \ |
|---|
| 3101 | + ETHTOOL_COALESCE_MAX_FRAMES | \ |
|---|
| 3102 | + ETHTOOL_COALESCE_USE_ADAPTIVE | \ |
|---|
| 3103 | + ETHTOOL_COALESCE_RX_MAX_FRAMES_LOW | \ |
|---|
| 3104 | + ETHTOOL_COALESCE_TX_MAX_FRAMES_LOW | \ |
|---|
| 3105 | + ETHTOOL_COALESCE_RX_MAX_FRAMES_HIGH | \ |
|---|
| 3106 | + ETHTOOL_COALESCE_TX_MAX_FRAMES_HIGH | \ |
|---|
| 3107 | + ETHTOOL_COALESCE_PKT_RATE_RX_USECS) |
|---|
| 3108 | + |
|---|
| 3126 | 3109 | static const struct ethtool_ops lio_ethtool_ops = { |
|---|
| 3110 | + .supported_coalesce_params = LIO_ETHTOOL_COALESCE, |
|---|
| 3127 | 3111 | .get_link_ksettings = lio_get_link_ksettings, |
|---|
| 3128 | 3112 | .set_link_ksettings = lio_set_link_ksettings, |
|---|
| 3113 | + .get_fecparam = lio_get_fecparam, |
|---|
| 3114 | + .set_fecparam = lio_set_fecparam, |
|---|
| 3129 | 3115 | .get_link = ethtool_op_get_link, |
|---|
| 3130 | 3116 | .get_drvinfo = lio_get_drvinfo, |
|---|
| 3131 | 3117 | .get_ringparam = lio_ethtool_get_ringparam, |
|---|
| .. | .. |
|---|
| 3152 | 3138 | }; |
|---|
| 3153 | 3139 | |
|---|
| 3154 | 3140 | static const struct ethtool_ops lio_vf_ethtool_ops = { |
|---|
| 3141 | + .supported_coalesce_params = LIO_ETHTOOL_COALESCE, |
|---|
| 3155 | 3142 | .get_link_ksettings = lio_get_link_ksettings, |
|---|
| 3156 | 3143 | .get_link = ethtool_op_get_link, |
|---|
| 3157 | 3144 | .get_drvinfo = lio_get_vf_drvinfo, |
|---|