aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/net/sfc/ethtool.c
diff options
context:
space:
mode:
authorBen Hutchings <bhutchings@solarflare.com>2010-06-30 01:06:28 -0400
committerDavid S. Miller <davem@davemloft.net>2010-06-30 17:10:04 -0400
commit765c9f46867c3253c02275cbb7a453f2eb56eda1 (patch)
tree42a2f70e2a9104c620849412d8f6ce91f30815f7 /drivers/net/sfc/ethtool.c
parenta5b6ee291e39e285e021cf251dbcf770c83cd74e (diff)
sfc: Add support for RX flow hash control
Allow ethtool to query the number of RX rings, the fields used in RX flow hashing and the hash indirection table. Allow ethtool to update the RX flow hash indirection table. Signed-off-by: Ben Hutchings <bhutchings@solarflare.com> Signed-off-by: David S. Miller <davem@davemloft.net>
Diffstat (limited to 'drivers/net/sfc/ethtool.c')
-rw-r--r--drivers/net/sfc/ethtool.c90
1 files changed, 90 insertions, 0 deletions
diff --git a/drivers/net/sfc/ethtool.c b/drivers/net/sfc/ethtool.c
index 23372bf5cd59..3b8b0a062749 100644
--- a/drivers/net/sfc/ethtool.c
+++ b/drivers/net/sfc/ethtool.c
@@ -868,6 +868,93 @@ extern int efx_ethtool_reset(struct net_device *net_dev, u32 *flags)
868 return efx_reset(efx, method); 868 return efx_reset(efx, method);
869} 869}
870 870
871static int
872efx_ethtool_get_rxnfc(struct net_device *net_dev,
873 struct ethtool_rxnfc *info, void *rules __always_unused)
874{
875 struct efx_nic *efx = netdev_priv(net_dev);
876
877 switch (info->cmd) {
878 case ETHTOOL_GRXRINGS:
879 info->data = efx->n_rx_channels;
880 return 0;
881
882 case ETHTOOL_GRXFH: {
883 unsigned min_revision = 0;
884
885 info->data = 0;
886 switch (info->flow_type) {
887 case TCP_V4_FLOW:
888 info->data |= RXH_L4_B_0_1 | RXH_L4_B_2_3;
889 /* fall through */
890 case UDP_V4_FLOW:
891 case SCTP_V4_FLOW:
892 case AH_ESP_V4_FLOW:
893 case IPV4_FLOW:
894 info->data |= RXH_IP_SRC | RXH_IP_DST;
895 min_revision = EFX_REV_FALCON_B0;
896 break;
897 case TCP_V6_FLOW:
898 info->data |= RXH_L4_B_0_1 | RXH_L4_B_2_3;
899 /* fall through */
900 case UDP_V6_FLOW:
901 case SCTP_V6_FLOW:
902 case AH_ESP_V6_FLOW:
903 case IPV6_FLOW:
904 info->data |= RXH_IP_SRC | RXH_IP_DST;
905 min_revision = EFX_REV_SIENA_A0;
906 break;
907 default:
908 break;
909 }
910 if (efx_nic_rev(efx) < min_revision)
911 info->data = 0;
912 return 0;
913 }
914
915 default:
916 return -EOPNOTSUPP;
917 }
918}
919
920static int efx_ethtool_get_rxfh_indir(struct net_device *net_dev,
921 struct ethtool_rxfh_indir *indir)
922{
923 struct efx_nic *efx = netdev_priv(net_dev);
924 size_t copy_size =
925 min_t(size_t, indir->size, ARRAY_SIZE(efx->rx_indir_table));
926
927 if (efx_nic_rev(efx) < EFX_REV_FALCON_B0)
928 return -EOPNOTSUPP;
929
930 indir->size = ARRAY_SIZE(efx->rx_indir_table);
931 memcpy(indir->ring_index, efx->rx_indir_table,
932 copy_size * sizeof(indir->ring_index[0]));
933 return 0;
934}
935
936static int efx_ethtool_set_rxfh_indir(struct net_device *net_dev,
937 const struct ethtool_rxfh_indir *indir)
938{
939 struct efx_nic *efx = netdev_priv(net_dev);
940 size_t i;
941
942 if (efx_nic_rev(efx) < EFX_REV_FALCON_B0)
943 return -EOPNOTSUPP;
944
945 /* Validate size and indices */
946 if (indir->size != ARRAY_SIZE(efx->rx_indir_table))
947 return -EINVAL;
948 for (i = 0; i < ARRAY_SIZE(efx->rx_indir_table); i++)
949 if (indir->ring_index[i] >= efx->n_rx_channels)
950 return -EINVAL;
951
952 memcpy(efx->rx_indir_table, indir->ring_index,
953 sizeof(efx->rx_indir_table));
954 efx_nic_push_rx_indir_table(efx);
955 return 0;
956}
957
871const struct ethtool_ops efx_ethtool_ops = { 958const struct ethtool_ops efx_ethtool_ops = {
872 .get_settings = efx_ethtool_get_settings, 959 .get_settings = efx_ethtool_get_settings,
873 .set_settings = efx_ethtool_set_settings, 960 .set_settings = efx_ethtool_set_settings,
@@ -905,4 +992,7 @@ const struct ethtool_ops efx_ethtool_ops = {
905 .get_wol = efx_ethtool_get_wol, 992 .get_wol = efx_ethtool_get_wol,
906 .set_wol = efx_ethtool_set_wol, 993 .set_wol = efx_ethtool_set_wol,
907 .reset = efx_ethtool_reset, 994 .reset = efx_ethtool_reset,
995 .get_rxnfc = efx_ethtool_get_rxnfc,
996 .get_rxfh_indir = efx_ethtool_get_rxfh_indir,
997 .set_rxfh_indir = efx_ethtool_set_rxfh_indir,
908}; 998};