diff options
Diffstat (limited to 'drivers/net/ethernet/sfc/ethtool.c')
-rw-r--r-- | drivers/net/ethernet/sfc/ethtool.c | 104 |
1 files changed, 68 insertions, 36 deletions
diff --git a/drivers/net/ethernet/sfc/ethtool.c b/drivers/net/ethernet/sfc/ethtool.c index 445ccdb6bc67..3747b5644110 100644 --- a/drivers/net/ethernet/sfc/ethtool.c +++ b/drivers/net/ethernet/sfc/ethtool.c @@ -69,12 +69,19 @@ static const struct efx_sw_stat_desc efx_sw_stat_desc[] = { EFX_ETHTOOL_UINT_TXQ_STAT(tso_bursts), EFX_ETHTOOL_UINT_TXQ_STAT(tso_long_headers), EFX_ETHTOOL_UINT_TXQ_STAT(tso_packets), + EFX_ETHTOOL_UINT_TXQ_STAT(tso_fallbacks), EFX_ETHTOOL_UINT_TXQ_STAT(pushes), EFX_ETHTOOL_UINT_TXQ_STAT(pio_packets), + EFX_ETHTOOL_UINT_TXQ_STAT(cb_packets), EFX_ETHTOOL_ATOMIC_NIC_ERROR_STAT(rx_reset), EFX_ETHTOOL_UINT_CHANNEL_STAT(rx_tobe_disc), EFX_ETHTOOL_UINT_CHANNEL_STAT(rx_ip_hdr_chksum_err), EFX_ETHTOOL_UINT_CHANNEL_STAT(rx_tcp_udp_chksum_err), + EFX_ETHTOOL_UINT_CHANNEL_STAT(rx_inner_ip_hdr_chksum_err), + EFX_ETHTOOL_UINT_CHANNEL_STAT(rx_inner_tcp_udp_chksum_err), + EFX_ETHTOOL_UINT_CHANNEL_STAT(rx_outer_ip_hdr_chksum_err), + EFX_ETHTOOL_UINT_CHANNEL_STAT(rx_outer_tcp_udp_chksum_err), + EFX_ETHTOOL_UINT_CHANNEL_STAT(rx_eth_crc_err), EFX_ETHTOOL_UINT_CHANNEL_STAT(rx_mcast_mismatch), EFX_ETHTOOL_UINT_CHANNEL_STAT(rx_frm_trunc), EFX_ETHTOOL_UINT_CHANNEL_STAT(rx_merge_events), @@ -118,44 +125,53 @@ static int efx_ethtool_phys_id(struct net_device *net_dev, } /* This must be called with rtnl_lock held. */ -static int efx_ethtool_get_settings(struct net_device *net_dev, - struct ethtool_cmd *ecmd) +static int +efx_ethtool_get_link_ksettings(struct net_device *net_dev, + struct ethtool_link_ksettings *cmd) { struct efx_nic *efx = netdev_priv(net_dev); struct efx_link_state *link_state = &efx->link_state; + u32 supported; mutex_lock(&efx->mac_lock); - efx->phy_op->get_settings(efx, ecmd); + efx->phy_op->get_link_ksettings(efx, cmd); mutex_unlock(&efx->mac_lock); /* Both MACs support pause frames (bidirectional and respond-only) */ - ecmd->supported |= SUPPORTED_Pause | SUPPORTED_Asym_Pause; + ethtool_convert_link_mode_to_legacy_u32(&supported, + cmd->link_modes.supported); + + supported |= SUPPORTED_Pause | SUPPORTED_Asym_Pause; + + ethtool_convert_legacy_u32_to_link_mode(cmd->link_modes.supported, + supported); if (LOOPBACK_INTERNAL(efx)) { - ethtool_cmd_speed_set(ecmd, link_state->speed); - ecmd->duplex = link_state->fd ? DUPLEX_FULL : DUPLEX_HALF; + cmd->base.speed = link_state->speed; + cmd->base.duplex = link_state->fd ? DUPLEX_FULL : DUPLEX_HALF; } return 0; } /* This must be called with rtnl_lock held. */ -static int efx_ethtool_set_settings(struct net_device *net_dev, - struct ethtool_cmd *ecmd) +static int +efx_ethtool_set_link_ksettings(struct net_device *net_dev, + const struct ethtool_link_ksettings *cmd) { struct efx_nic *efx = netdev_priv(net_dev); int rc; /* GMAC does not support 1000Mbps HD */ - if ((ethtool_cmd_speed(ecmd) == SPEED_1000) && - (ecmd->duplex != DUPLEX_FULL)) { + if ((cmd->base.speed == SPEED_1000) && + (cmd->base.duplex != DUPLEX_FULL)) { netif_dbg(efx, drv, efx->net_dev, "rejecting unsupported 1000Mbps HD setting\n"); return -EINVAL; } mutex_lock(&efx->mac_lock); - rc = efx->phy_op->set_settings(efx, ecmd); + rc = efx->phy_op->set_link_ksettings(efx, cmd); mutex_unlock(&efx->mac_lock); return rc; } @@ -167,9 +183,8 @@ static void efx_ethtool_get_drvinfo(struct net_device *net_dev, strlcpy(info->driver, KBUILD_MODNAME, sizeof(info->driver)); strlcpy(info->version, EFX_DRIVER_VERSION, sizeof(info->version)); - if (efx_nic_rev(efx) >= EFX_REV_SIENA_A0) - efx_mcdi_print_fwver(efx, info->fw_version, - sizeof(info->fw_version)); + efx_mcdi_print_fwver(efx, info->fw_version, + sizeof(info->fw_version)); strlcpy(info->bus_info, pci_name(efx->pci_dev), sizeof(info->bus_info)); } @@ -332,12 +347,12 @@ static int efx_ethtool_fill_self_tests(struct efx_nic *efx, "core", 0, "registers", NULL); if (efx->phy_op->run_tests != NULL) { - EFX_BUG_ON_PARANOID(efx->phy_op->test_name == NULL); + EFX_WARN_ON_PARANOID(efx->phy_op->test_name == NULL); for (i = 0; true; ++i) { const char *name; - EFX_BUG_ON_PARANOID(i >= EFX_MAX_PHY_TESTS); + EFX_WARN_ON_PARANOID(i >= EFX_MAX_PHY_TESTS); name = efx->phy_op->test_name(efx, i); if (name == NULL) break; @@ -964,35 +979,35 @@ efx_ethtool_get_rxnfc(struct net_device *net_dev, return 0; case ETHTOOL_GRXFH: { - unsigned min_revision = 0; - info->data = 0; + if (!efx->rss_active) /* No RSS */ + return 0; switch (info->flow_type) { + case UDP_V4_FLOW: + if (efx->rx_hash_udp_4tuple) + /* fall through */ case TCP_V4_FLOW: - info->data |= RXH_L4_B_0_1 | RXH_L4_B_2_3; + info->data |= RXH_L4_B_0_1 | RXH_L4_B_2_3; /* fall through */ - case UDP_V4_FLOW: case SCTP_V4_FLOW: case AH_ESP_V4_FLOW: case IPV4_FLOW: info->data |= RXH_IP_SRC | RXH_IP_DST; - min_revision = EFX_REV_FALCON_B0; break; + case UDP_V6_FLOW: + if (efx->rx_hash_udp_4tuple) + /* fall through */ case TCP_V6_FLOW: - info->data |= RXH_L4_B_0_1 | RXH_L4_B_2_3; + info->data |= RXH_L4_B_0_1 | RXH_L4_B_2_3; /* fall through */ - case UDP_V6_FLOW: case SCTP_V6_FLOW: case AH_ESP_V6_FLOW: case IPV6_FLOW: info->data |= RXH_IP_SRC | RXH_IP_DST; - min_revision = EFX_REV_SIENA_A0; break; default: break; } - if (efx_nic_rev(efx) < min_revision) - info->data = 0; return 0; } @@ -1265,20 +1280,32 @@ static u32 efx_ethtool_get_rxfh_indir_size(struct net_device *net_dev) { struct efx_nic *efx = netdev_priv(net_dev); - return ((efx_nic_rev(efx) < EFX_REV_FALCON_B0 || - efx->n_rx_channels == 1) ? - 0 : ARRAY_SIZE(efx->rx_indir_table)); + return (efx->n_rx_channels == 1) ? 0 : ARRAY_SIZE(efx->rx_indir_table); +} + +static u32 efx_ethtool_get_rxfh_key_size(struct net_device *net_dev) +{ + struct efx_nic *efx = netdev_priv(net_dev); + + return efx->type->rx_hash_key_size; } static int efx_ethtool_get_rxfh(struct net_device *net_dev, u32 *indir, u8 *key, u8 *hfunc) { struct efx_nic *efx = netdev_priv(net_dev); + int rc; + + rc = efx->type->rx_pull_rss_config(efx); + if (rc) + return rc; if (hfunc) *hfunc = ETH_RSS_HASH_TOP; if (indir) memcpy(indir, efx->rx_indir_table, sizeof(efx->rx_indir_table)); + if (key) + memcpy(key, efx->rx_hash_key, efx->type->rx_hash_key_size); return 0; } @@ -1287,14 +1314,18 @@ static int efx_ethtool_set_rxfh(struct net_device *net_dev, const u32 *indir, { struct efx_nic *efx = netdev_priv(net_dev); - /* We do not allow change in unsupported parameters */ - if (key || - (hfunc != ETH_RSS_HASH_NO_CHANGE && hfunc != ETH_RSS_HASH_TOP)) + /* Hash function is Toeplitz, cannot be changed */ + if (hfunc != ETH_RSS_HASH_NO_CHANGE && hfunc != ETH_RSS_HASH_TOP) return -EOPNOTSUPP; - if (!indir) + if (!indir && !key) return 0; - return efx->type->rx_push_rss_config(efx, true, indir); + if (!key) + key = efx->rx_hash_key; + if (!indir) + indir = efx->rx_indir_table; + + return efx->type->rx_push_rss_config(efx, true, indir, key); } static int efx_ethtool_get_ts_info(struct net_device *net_dev, @@ -1345,8 +1376,6 @@ static int efx_ethtool_get_module_info(struct net_device *net_dev, } const struct ethtool_ops efx_ethtool_ops = { - .get_settings = efx_ethtool_get_settings, - .set_settings = efx_ethtool_set_settings, .get_drvinfo = efx_ethtool_get_drvinfo, .get_regs_len = efx_ethtool_get_regs_len, .get_regs = efx_ethtool_get_regs, @@ -1371,9 +1400,12 @@ const struct ethtool_ops efx_ethtool_ops = { .get_rxnfc = efx_ethtool_get_rxnfc, .set_rxnfc = efx_ethtool_set_rxnfc, .get_rxfh_indir_size = efx_ethtool_get_rxfh_indir_size, + .get_rxfh_key_size = efx_ethtool_get_rxfh_key_size, .get_rxfh = efx_ethtool_get_rxfh, .set_rxfh = efx_ethtool_set_rxfh, .get_ts_info = efx_ethtool_get_ts_info, .get_module_info = efx_ethtool_get_module_info, .get_module_eeprom = efx_ethtool_get_module_eeprom, + .get_link_ksettings = efx_ethtool_get_link_ksettings, + .set_link_ksettings = efx_ethtool_set_link_ksettings, }; |