History

Merge branch 'ethtool-rssh-fixes' of git://git.kernel.org/pub/scm/linux/kernel/git/bwh/net-next

Ben Hutchings says: ==================== Pull request: Fixes for new ethtool RSS commands This addresses several problems I previously identified with the new ETHTOOL_{G,S}RSSH commands: 1. Missing validation of reserved parameters 2. Vague documentation 3. Use of unnamed magic number 4. No consolidation with existing driver operations I don't currently have access to suitable network hardware, but have tested these changes with a dummy driver that can support various combinations of operations and sizes, together with (a) Debian's ethtool 3.13 (b) ethtool 3.14 with the submitted patch to use ETHTOOL_{G,S}RSSH and minor adjustment for fixes 1 and 3. v2: Update RSS operations in vmxnet3 too ====================

David S. Miller committed 12 years ago

Commit 014b2012 parents a68ab98 f062a3814 files · +120 −129Browse files

Unified · Split

14 files
  1. drivers/net/ethernet/broadcom/bnx2x/bnx2x_ethtool.c +8 −7
  2. drivers/net/ethernet/broadcom/tg3.c +4 −4
  3. drivers/net/ethernet/chelsio/cxgb4/cxgb4_main.c +4 −4
  4. drivers/net/ethernet/emulex/benet/be_cmds.c +1 −1
  5. drivers/net/ethernet/emulex/benet/be_cmds.h +1 −1
  6. drivers/net/ethernet/emulex/benet/be_ethtool.c +2 −1
  7. drivers/net/ethernet/intel/i40evf/i40evf_ethtool.c +9 −6
  8. drivers/net/ethernet/intel/igb/igb_ethtool.c +5 −4
  9. drivers/net/ethernet/mellanox/mlx4/en_ethtool.c +5 −5
  10. drivers/net/ethernet/sfc/ethtool.c +5 −5
  11. drivers/net/vmxnet3/vmxnet3_ethtool.c +4 −4
  12. include/linux/ethtool.h +10 −14
  13. include/uapi/linux/ethtool.h +14 −11
  14. net/core/ethtool.c +48 −62
drivers/net/ethernet/broadcom/bnx2x/bnx2x_ethtool.c+8−7
@@ -3316,7 +3316,7 @@ static u32 bnx2x_get_rxfh_indir_size(struct net_device *dev) · 3315 unmodified lines
3316 return T_ETH_INDIRECTION_TABLE_SIZE;3316 return T_ETH_INDIRECTION_TABLE_SIZE;
3317}3317}
3318 3318
3319static int bnx2x_get_rxfh_indir(struct net_device *dev, u32 *indir)3319static int bnx2x_get_rxfh(struct net_device *dev, u32 *indir, u8 *key)
3320{3320{
3321 struct bnx2x *bp = netdev_priv(dev);3321 struct bnx2x *bp = netdev_priv(dev);
3322 u8 ind_table[T_ETH_INDIRECTION_TABLE_SIZE] = {0};3322 u8 ind_table[T_ETH_INDIRECTION_TABLE_SIZE] = {0};
@@ -3340,14 +3340,15 @@ static int bnx2x_get_rxfh_indir(struct net_device *dev, u32 *indir) · 17 unmodified lines
3340 return 0;3340 return 0;
3341}3341}
3342 3342
3343static int bnx2x_set_rxfh_indir(struct net_device *dev, const u32 *indir)3343static int bnx2x_set_rxfh(struct net_device *dev, const u32 *indir,
3344 const u8 *key)
3344{3345{
3345 struct bnx2x *bp = netdev_priv(dev);3346 struct bnx2x *bp = netdev_priv(dev);
3346 size_t i;3347 size_t i;
3347 3348
3348 for (i = 0; i < T_ETH_INDIRECTION_TABLE_SIZE; i++) {3349 for (i = 0; i < T_ETH_INDIRECTION_TABLE_SIZE; i++) {
3349 /*3350 /*
3350 * The same as in bnx2x_get_rxfh_indir: we can't use a memcpy()3351 * The same as in bnx2x_get_rxfh: we can't use a memcpy()
3351 * as an internal storage of an indirection table is a u8 array3352 * as an internal storage of an indirection table is a u8 array
3352 * while indir->ring_index points to an array of u32.3353 * while indir->ring_index points to an array of u32.
3353 *3354 *
@@ -3471,8 +3472,8 @@ static const struct ethtool_ops bnx2x_ethtool_ops = { · 117 unmodified lines
3471 .get_rxnfc = bnx2x_get_rxnfc,3472 .get_rxnfc = bnx2x_get_rxnfc,
3472 .set_rxnfc = bnx2x_set_rxnfc,3473 .set_rxnfc = bnx2x_set_rxnfc,
3473 .get_rxfh_indir_size = bnx2x_get_rxfh_indir_size,3474 .get_rxfh_indir_size = bnx2x_get_rxfh_indir_size,
3474 .get_rxfh_indir = bnx2x_get_rxfh_indir,3475 .get_rxfh = bnx2x_get_rxfh,
3475 .set_rxfh_indir = bnx2x_set_rxfh_indir,3476 .set_rxfh = bnx2x_set_rxfh,
3476 .get_channels = bnx2x_get_channels,3477 .get_channels = bnx2x_get_channels,
3477 .set_channels = bnx2x_set_channels,3478 .set_channels = bnx2x_set_channels,
3478 .get_module_info = bnx2x_get_module_info,3479 .get_module_info = bnx2x_get_module_info,
@@ -3498,8 +3499,8 @@ static const struct ethtool_ops bnx2x_vf_ethtool_ops = { · 19 unmodified lines
3498 .get_rxnfc = bnx2x_get_rxnfc,3499 .get_rxnfc = bnx2x_get_rxnfc,
3499 .set_rxnfc = bnx2x_set_rxnfc,3500 .set_rxnfc = bnx2x_set_rxnfc,
3500 .get_rxfh_indir_size = bnx2x_get_rxfh_indir_size,3501 .get_rxfh_indir_size = bnx2x_get_rxfh_indir_size,
3501 .get_rxfh_indir = bnx2x_get_rxfh_indir,3502 .get_rxfh = bnx2x_get_rxfh,
3502 .set_rxfh_indir = bnx2x_set_rxfh_indir,3503 .set_rxfh = bnx2x_set_rxfh,
3503 .get_channels = bnx2x_get_channels,3504 .get_channels = bnx2x_get_channels,
3504 .set_channels = bnx2x_set_channels,3505 .set_channels = bnx2x_set_channels,
3505};3506};
drivers/net/ethernet/broadcom/tg3.c+4−4
@@ -12532,7 +12532,7 @@ static u32 tg3_get_rxfh_indir_size(struct net_device *dev) · 12531 unmodified lines
12532 return size;12532 return size;
12533}12533}
12534 12534
12535static int tg3_get_rxfh_indir(struct net_device *dev, u32 *indir)12535static int tg3_get_rxfh(struct net_device *dev, u32 *indir, u8 *key)
12536{12536{
12537 struct tg3 *tp = netdev_priv(dev);12537 struct tg3 *tp = netdev_priv(dev);
12538 int i;12538 int i;
@@ -12543,7 +12543,7 @@ static int tg3_get_rxfh_indir(struct net_device *dev, u32 *indir) · 4 unmodified lines
12543 return 0;12543 return 0;
12544}12544}
12545 12545
12546static int tg3_set_rxfh_indir(struct net_device *dev, const u32 *indir)12546static int tg3_set_rxfh(struct net_device *dev, const u32 *indir, const u8 *key)
12547{12547{
12548 struct tg3 *tp = netdev_priv(dev);12548 struct tg3 *tp = netdev_priv(dev);
12549 size_t i;12549 size_t i;
@@ -14075,8 +14075,8 @@ static const struct ethtool_ops tg3_ethtool_ops = { · 1525 unmodified lines
14075 .get_sset_count = tg3_get_sset_count,14075 .get_sset_count = tg3_get_sset_count,
14076 .get_rxnfc = tg3_get_rxnfc,14076 .get_rxnfc = tg3_get_rxnfc,
14077 .get_rxfh_indir_size = tg3_get_rxfh_indir_size,14077 .get_rxfh_indir_size = tg3_get_rxfh_indir_size,
14078 .get_rxfh_indir = tg3_get_rxfh_indir,14078 .get_rxfh = tg3_get_rxfh,
14079 .set_rxfh_indir = tg3_set_rxfh_indir,14079 .set_rxfh = tg3_set_rxfh,
14080 .get_channels = tg3_get_channels,14080 .get_channels = tg3_get_channels,
14081 .set_channels = tg3_set_channels,14081 .set_channels = tg3_set_channels,
14082 .get_ts_info = tg3_get_ts_info,14082 .get_ts_info = tg3_get_ts_info,
drivers/net/ethernet/chelsio/cxgb4/cxgb4_main.c+4−4
@@ -2739,7 +2739,7 @@ static u32 get_rss_table_size(struct net_device *dev) · 2738 unmodified lines
2739 return pi->rss_size;2739 return pi->rss_size;
2740}2740}
2741 2741
2742static int get_rss_table(struct net_device *dev, u32 *p)2742static int get_rss_table(struct net_device *dev, u32 *p, u8 *key)
2743{2743{
2744 const struct port_info *pi = netdev_priv(dev);2744 const struct port_info *pi = netdev_priv(dev);
2745 unsigned int n = pi->rss_size;2745 unsigned int n = pi->rss_size;
@@ -2749,7 +2749,7 @@ static int get_rss_table(struct net_device *dev, u32 *p) · 3 unmodified lines
2749 return 0;2749 return 0;
2750}2750}
2751 2751
2752static int set_rss_table(struct net_device *dev, const u32 *p)2752static int set_rss_table(struct net_device *dev, const u32 *p, const u8 *key)
2753{2753{
2754 unsigned int i;2754 unsigned int i;
2755 struct port_info *pi = netdev_priv(dev);2755 struct port_info *pi = netdev_priv(dev);
@@ -2851,8 +2851,8 @@ static const struct ethtool_ops cxgb_ethtool_ops = { · 95 unmodified lines
2851 .set_wol = set_wol,2851 .set_wol = set_wol,
2852 .get_rxnfc = get_rxnfc,2852 .get_rxnfc = get_rxnfc,
2853 .get_rxfh_indir_size = get_rss_table_size,2853 .get_rxfh_indir_size = get_rss_table_size,
2854 .get_rxfh_indir = get_rss_table,2854 .get_rxfh = get_rss_table,
2855 .set_rxfh_indir = set_rss_table,2855 .set_rxfh = set_rss_table,
2856 .flash_device = set_flash,2856 .flash_device = set_flash,
2857};2857};
2858 2858
drivers/net/ethernet/emulex/benet/be_cmds.c+1−1
@@ -2065,7 +2065,7 @@ int be_cmd_reset_function(struct be_adapter *adapter) · 2064 unmodified lines
2065}2065}
2066 2066
2067int be_cmd_rss_config(struct be_adapter *adapter, u8 *rsstable,2067int be_cmd_rss_config(struct be_adapter *adapter, u8 *rsstable,
2068 u32 rss_hash_opts, u16 table_size, u8 *rss_hkey)2068 u32 rss_hash_opts, u16 table_size, const u8 *rss_hkey)
2069{2069{
2070 struct be_mcc_wrb *wrb;2070 struct be_mcc_wrb *wrb;
2071 struct be_cmd_req_rss_config *req;2071 struct be_cmd_req_rss_config *req;
drivers/net/ethernet/emulex/benet/be_cmds.h+1−1
@@ -2082,7 +2082,7 @@ int be_cmd_query_fw_cfg(struct be_adapter *adapter, u32 *port_num, · 2081 unmodified lines
2082 u32 *function_mode, u32 *function_caps, u16 *asic_rev);2082 u32 *function_mode, u32 *function_caps, u16 *asic_rev);
2083int be_cmd_reset_function(struct be_adapter *adapter);2083int be_cmd_reset_function(struct be_adapter *adapter);
2084int be_cmd_rss_config(struct be_adapter *adapter, u8 *rsstable,2084int be_cmd_rss_config(struct be_adapter *adapter, u8 *rsstable,
2085 u32 rss_hash_opts, u16 table_size, u8 *rss_hkey);2085 u32 rss_hash_opts, u16 table_size, const u8 *rss_hkey);
2086int be_process_mcc(struct be_adapter *adapter);2086int be_process_mcc(struct be_adapter *adapter);
2087int be_cmd_set_beacon_state(struct be_adapter *adapter, u8 port_num, u8 beacon,2087int be_cmd_set_beacon_state(struct be_adapter *adapter, u8 port_num, u8 beacon,
2088 u8 status, u8 state);2088 u8 status, u8 state);
drivers/net/ethernet/emulex/benet/be_ethtool.c+2−1
@@ -1117,7 +1117,8 @@ static int be_get_rxfh(struct net_device *netdev, u32 *indir, u8 *hkey) · 1116 unmodified lines
1117 return 0;1117 return 0;
1118}1118}
1119 1119
1120static int be_set_rxfh(struct net_device *netdev, u32 *indir, u8 *hkey)1120static int be_set_rxfh(struct net_device *netdev, const u32 *indir,
1121 const u8 *hkey)
1121{1122{
1122 int rc = 0, i, j;1123 int rc = 0, i, j;
1123 struct be_adapter *adapter = netdev_priv(netdev);1124 struct be_adapter *adapter = netdev_priv(netdev);
drivers/net/ethernet/intel/i40evf/i40evf_ethtool.c+9−6
@@ -624,13 +624,14 @@ static u32 i40evf_get_rxfh_indir_size(struct net_device *netdev) · 623 unmodified lines
624}624}
625 625
626/**626/**
627 * i40evf_get_rxfh_indir - get the rx flow hash indirection table627 * i40evf_get_rxfh - get the rx flow hash indirection table
628 * @netdev: network interface device structure628 * @netdev: network interface device structure
629 * @indir: indirection table629 * @indir: indirection table
630 * @key: hash key (will be %NULL until get_rxfh_key_size is implemented)
630 *631 *
631 * Reads the indirection table directly from the hardware. Always returns 0.632 * Reads the indirection table directly from the hardware. Always returns 0.
632 **/633 **/
633static int i40evf_get_rxfh_indir(struct net_device *netdev, u32 *indir)634static int i40evf_get_rxfh(struct net_device *netdev, u32 *indir, u8 *key)
634{635{
635 struct i40evf_adapter *adapter = netdev_priv(netdev);636 struct i40evf_adapter *adapter = netdev_priv(netdev);
636 struct i40e_hw *hw = &adapter->hw;637 struct i40e_hw *hw = &adapter->hw;
@@ -648,14 +649,16 @@ static int i40evf_get_rxfh_indir(struct net_device *netdev, u32 *indir) · 11 unmodified lines
648}649}
649 650
650/**651/**
651 * i40evf_set_rxfh_indir - set the rx flow hash indirection table652 * i40evf_set_rxfh - set the rx flow hash indirection table
652 * @netdev: network interface device structure653 * @netdev: network interface device structure
653 * @indir: indirection table654 * @indir: indirection table
655 * @key: hash key (will be %NULL until get_rxfh_key_size is implemented)
654 *656 *
655 * Returns -EINVAL if the table specifies an inavlid queue id, otherwise657 * Returns -EINVAL if the table specifies an inavlid queue id, otherwise
656 * returns 0 after programming the table.658 * returns 0 after programming the table.
657 **/659 **/
658static int i40evf_set_rxfh_indir(struct net_device *netdev, const u32 *indir)660static int i40evf_set_rxfh(struct net_device *netdev, const u32 *indir,
661 const u8 *key)
659{662{
660 struct i40evf_adapter *adapter = netdev_priv(netdev);663 struct i40evf_adapter *adapter = netdev_priv(netdev);
661 struct i40e_hw *hw = &adapter->hw;664 struct i40e_hw *hw = &adapter->hw;
@@ -689,8 +692,8 @@ static const struct ethtool_ops i40evf_ethtool_ops = { · 27 unmodified lines
689 .get_rxnfc = i40evf_get_rxnfc,692 .get_rxnfc = i40evf_get_rxnfc,
690 .set_rxnfc = i40evf_set_rxnfc,693 .set_rxnfc = i40evf_set_rxnfc,
691 .get_rxfh_indir_size = i40evf_get_rxfh_indir_size,694 .get_rxfh_indir_size = i40evf_get_rxfh_indir_size,
692 .get_rxfh_indir = i40evf_get_rxfh_indir,695 .get_rxfh = i40evf_get_rxfh,
693 .set_rxfh_indir = i40evf_set_rxfh_indir,696 .set_rxfh = i40evf_set_rxfh,
694 .get_channels = i40evf_get_channels,697 .get_channels = i40evf_get_channels,
695};698};
696 699
drivers/net/ethernet/intel/igb/igb_ethtool.c+5−4
@@ -2830,7 +2830,7 @@ static u32 igb_get_rxfh_indir_size(struct net_device *netdev) · 2829 unmodified lines
2830 return IGB_RETA_SIZE;2830 return IGB_RETA_SIZE;
2831}2831}
2832 2832
2833static int igb_get_rxfh_indir(struct net_device *netdev, u32 *indir)2833static int igb_get_rxfh(struct net_device *netdev, u32 *indir, u8 *key)
2834{2834{
2835 struct igb_adapter *adapter = netdev_priv(netdev);2835 struct igb_adapter *adapter = netdev_priv(netdev);
2836 int i;2836 int i;
@@ -2876,7 +2876,8 @@ void igb_write_rss_indir_tbl(struct igb_adapter *adapter) · 39 unmodified lines
2876 }2876 }
2877}2877}
2878 2878
2879static int igb_set_rxfh_indir(struct net_device *netdev, const u32 *indir)2879static int igb_set_rxfh(struct net_device *netdev, const u32 *indir,
2880 const u8 *key)
2880{2881{
2881 struct igb_adapter *adapter = netdev_priv(netdev);2882 struct igb_adapter *adapter = netdev_priv(netdev);
2882 struct e1000_hw *hw = &adapter->hw;2883 struct e1000_hw *hw = &adapter->hw;
@@ -3025,8 +3026,8 @@ static const struct ethtool_ops igb_ethtool_ops = { · 142 unmodified lines
3025 .get_module_info = igb_get_module_info,3026 .get_module_info = igb_get_module_info,
3026 .get_module_eeprom = igb_get_module_eeprom,3027 .get_module_eeprom = igb_get_module_eeprom,
3027 .get_rxfh_indir_size = igb_get_rxfh_indir_size,3028 .get_rxfh_indir_size = igb_get_rxfh_indir_size,
3028 .get_rxfh_indir = igb_get_rxfh_indir,3029 .get_rxfh = igb_get_rxfh,
3029 .set_rxfh_indir = igb_set_rxfh_indir,3030 .set_rxfh = igb_set_rxfh,
3030 .get_channels = igb_get_channels,3031 .get_channels = igb_get_channels,
3031 .set_channels = igb_set_channels,3032 .set_channels = igb_set_channels,
3032 .begin = igb_ethtool_begin,3033 .begin = igb_ethtool_begin,
drivers/net/ethernet/mellanox/mlx4/en_ethtool.c+5−5
@@ -564,7 +564,7 @@ static u32 mlx4_en_get_rxfh_indir_size(struct net_device *dev) · 563 unmodified lines
564 return priv->rx_ring_num;564 return priv->rx_ring_num;
565}565}
566 566
567static int mlx4_en_get_rxfh_indir(struct net_device *dev, u32 *ring_index)567static int mlx4_en_get_rxfh(struct net_device *dev, u32 *ring_index, u8 *key)
568{568{
569 struct mlx4_en_priv *priv = netdev_priv(dev);569 struct mlx4_en_priv *priv = netdev_priv(dev);
570 struct mlx4_en_rss_map *rss_map = &priv->rss_map;570 struct mlx4_en_rss_map *rss_map = &priv->rss_map;
@@ -582,8 +582,8 @@ static int mlx4_en_get_rxfh_indir(struct net_device *dev, u32 *ring_index) · 11 unmodified lines
582 return err;582 return err;
583}583}
584 584
585static int mlx4_en_set_rxfh_indir(struct net_device *dev,585static int mlx4_en_set_rxfh(struct net_device *dev, const u32 *ring_index,
586 const u32 *ring_index)586 const u8 *key)
587{587{
588 struct mlx4_en_priv *priv = netdev_priv(dev);588 struct mlx4_en_priv *priv = netdev_priv(dev);
589 struct mlx4_en_dev *mdev = priv->mdev;589 struct mlx4_en_dev *mdev = priv->mdev;
@@ -1224,8 +1224,8 @@ const struct ethtool_ops mlx4_en_ethtool_ops = { · 634 unmodified lines
1224 .get_rxnfc = mlx4_en_get_rxnfc,1224 .get_rxnfc = mlx4_en_get_rxnfc,
1225 .set_rxnfc = mlx4_en_set_rxnfc,1225 .set_rxnfc = mlx4_en_set_rxnfc,
1226 .get_rxfh_indir_size = mlx4_en_get_rxfh_indir_size,1226 .get_rxfh_indir_size = mlx4_en_get_rxfh_indir_size,
1227 .get_rxfh_indir = mlx4_en_get_rxfh_indir,1227 .get_rxfh = mlx4_en_get_rxfh,
1228 .set_rxfh_indir = mlx4_en_set_rxfh_indir,1228 .set_rxfh = mlx4_en_set_rxfh,
1229 .get_channels = mlx4_en_get_channels,1229 .get_channels = mlx4_en_get_channels,
1230 .set_channels = mlx4_en_set_channels,1230 .set_channels = mlx4_en_set_channels,
1231 .get_ts_info = mlx4_en_get_ts_info,1231 .get_ts_info = mlx4_en_get_ts_info,
drivers/net/ethernet/sfc/ethtool.c+5−5
@@ -1033,7 +1033,7 @@ static u32 efx_ethtool_get_rxfh_indir_size(struct net_device *net_dev) · 1032 unmodified lines
1033 0 : ARRAY_SIZE(efx->rx_indir_table));1033 0 : ARRAY_SIZE(efx->rx_indir_table));
1034}1034}
1035 1035
1036static int efx_ethtool_get_rxfh_indir(struct net_device *net_dev, u32 *indir)1036static int efx_ethtool_get_rxfh(struct net_device *net_dev, u32 *indir, u8 *key)
1037{1037{
1038 struct efx_nic *efx = netdev_priv(net_dev);1038 struct efx_nic *efx = netdev_priv(net_dev);
1039 1039
@@ -1041,8 +1041,8 @@ static int efx_ethtool_get_rxfh_indir(struct net_device *net_dev, u32 *indir) · 1 unmodified line
1041 return 0;1041 return 0;
1042}1042}
1043 1043
1044static int efx_ethtool_set_rxfh_indir(struct net_device *net_dev,1044static int efx_ethtool_set_rxfh(struct net_device *net_dev,
1045 const u32 *indir)1045 const u32 *indir, const u8 *key)
1046{1046{
1047 struct efx_nic *efx = netdev_priv(net_dev);1047 struct efx_nic *efx = netdev_priv(net_dev);
1048 1048
@@ -1125,8 +1125,8 @@ const struct ethtool_ops efx_ethtool_ops = { · 76 unmodified lines
1125 .get_rxnfc = efx_ethtool_get_rxnfc,1125 .get_rxnfc = efx_ethtool_get_rxnfc,
1126 .set_rxnfc = efx_ethtool_set_rxnfc,1126 .set_rxnfc = efx_ethtool_set_rxnfc,
1127 .get_rxfh_indir_size = efx_ethtool_get_rxfh_indir_size,1127 .get_rxfh_indir_size = efx_ethtool_get_rxfh_indir_size,
1128 .get_rxfh_indir = efx_ethtool_get_rxfh_indir,1128 .get_rxfh = efx_ethtool_get_rxfh,
1129 .set_rxfh_indir = efx_ethtool_set_rxfh_indir,1129 .set_rxfh = efx_ethtool_set_rxfh,
1130 .get_ts_info = efx_ethtool_get_ts_info,1130 .get_ts_info = efx_ethtool_get_ts_info,
1131 .get_module_info = efx_ethtool_get_module_info,1131 .get_module_info = efx_ethtool_get_module_info,
1132 .get_module_eeprom = efx_ethtool_get_module_eeprom,1132 .get_module_eeprom = efx_ethtool_get_module_eeprom,
drivers/net/vmxnet3/vmxnet3_ethtool.c+4−4
@@ -579,7 +579,7 @@ vmxnet3_get_rss_indir_size(struct net_device *netdev) · 578 unmodified lines
579}579}
580 580
581static int581static int
582vmxnet3_get_rss_indir(struct net_device *netdev, u32 *p)582vmxnet3_get_rss(struct net_device *netdev, u32 *p, u8 *key)
583{583{
584 struct vmxnet3_adapter *adapter = netdev_priv(netdev);584 struct vmxnet3_adapter *adapter = netdev_priv(netdev);
585 struct UPT1_RSSConf *rssConf = adapter->rss_conf;585 struct UPT1_RSSConf *rssConf = adapter->rss_conf;
@@ -592,7 +592,7 @@ vmxnet3_get_rss_indir(struct net_device *netdev, u32 *p) · 6 unmodified lines
592}592}
593 593
594static int594static int
595vmxnet3_set_rss_indir(struct net_device *netdev, const u32 *p)595vmxnet3_set_rss(struct net_device *netdev, const u32 *p, const u8 *key)
596{596{
597 unsigned int i;597 unsigned int i;
598 unsigned long flags;598 unsigned long flags;
@@ -628,8 +628,8 @@ static const struct ethtool_ops vmxnet3_ethtool_ops = { · 29 unmodified lines
628 .get_rxnfc = vmxnet3_get_rxnfc,628 .get_rxnfc = vmxnet3_get_rxnfc,
629#ifdef VMXNET3_RSS629#ifdef VMXNET3_RSS
630 .get_rxfh_indir_size = vmxnet3_get_rss_indir_size,630 .get_rxfh_indir_size = vmxnet3_get_rss_indir_size,
631 .get_rxfh_indir = vmxnet3_get_rss_indir,631 .get_rxfh = vmxnet3_get_rss,
632 .set_rxfh_indir = vmxnet3_set_rss_indir,632 .set_rxfh = vmxnet3_set_rss,
633#endif633#endif
634};634};
635 635
include/linux/ethtool.h+10−14
@@ -158,19 +158,16 @@ static inline u32 ethtool_rxfh_indir_default(u32 index, u32 n_rx_rings) · 157 unmodified lines
158 * Returns zero if not supported for this specific device.158 * Returns zero if not supported for this specific device.
159 * @get_rxfh_indir_size: Get the size of the RX flow hash indirection table.159 * @get_rxfh_indir_size: Get the size of the RX flow hash indirection table.
160 * Returns zero if not supported for this specific device.160 * Returns zero if not supported for this specific device.
161 * @get_rxfh_indir: Get the contents of the RX flow hash indirection table.
162 * Will not be called if @get_rxfh_indir_size returns zero.
163 * @get_rxfh: Get the contents of the RX flow hash indirection table and hash161 * @get_rxfh: Get the contents of the RX flow hash indirection table and hash
164 * key.162 * key.
165 * Will not be called if @get_rxfh_indir_size and @get_rxfh_key_size163 * Will only be called if one or both of @get_rxfh_indir_size and
166 * returns zero.164 * @get_rxfh_key_size are implemented and return non-zero.
167 * Returns a negative error code or zero.165 * Returns a negative error code or zero.
168 * @set_rxfh_indir: Set the contents of the RX flow hash indirection table.166 * @set_rxfh: Set the contents of the RX flow hash indirection table and/or
169 * Will not be called if @get_rxfh_indir_size returns zero.167 * hash key. In case only the indirection table or hash key is to be
170 * @set_rxfh: Set the contents of the RX flow hash indirection table and168 * changed, the other argument will be %NULL.
171 * hash key.169 * Will only be called if one or both of @get_rxfh_indir_size and
172 * Will not be called if @get_rxfh_indir_size and @get_rxfh_key_size170 * @get_rxfh_key_size are implemented and return non-zero.
173 * returns zero.
174 * Returns a negative error code or zero.171 * Returns a negative error code or zero.
175 * @get_channels: Get number of channels.172 * @get_channels: Get number of channels.
176 * @set_channels: Set number of channels. Returns a negative error code or173 * @set_channels: Set number of channels. Returns a negative error code or
@@ -244,10 +241,9 @@ struct ethtool_ops { · 67 unmodified lines
244 int (*reset)(struct net_device *, u32 *);241 int (*reset)(struct net_device *, u32 *);
245 u32 (*get_rxfh_key_size)(struct net_device *);242 u32 (*get_rxfh_key_size)(struct net_device *);
246 u32 (*get_rxfh_indir_size)(struct net_device *);243 u32 (*get_rxfh_indir_size)(struct net_device *);
247 int (*get_rxfh)(struct net_device *, u32 *, u8 *);244 int (*get_rxfh)(struct net_device *, u32 *indir, u8 *key);
248 int (*set_rxfh)(struct net_device *, u32 *, u8 *);245 int (*set_rxfh)(struct net_device *, const u32 *indir,
249 int (*get_rxfh_indir)(struct net_device *, u32 *);246 const u8 *key);
250 int (*set_rxfh_indir)(struct net_device *, const u32 *);
251 void (*get_channels)(struct net_device *, struct ethtool_channels *);247 void (*get_channels)(struct net_device *, struct ethtool_channels *);
252 int (*set_channels)(struct net_device *, struct ethtool_channels *);248 int (*set_channels)(struct net_device *, struct ethtool_channels *);
253 int (*get_dump_flag)(struct net_device *, struct ethtool_dump *);249 int (*get_dump_flag)(struct net_device *, struct ethtool_dump *);
include/uapi/linux/ethtool.h+14−11
@@ -850,21 +850,23 @@ struct ethtool_rxfh_indir { · 849 unmodified lines
850 * struct ethtool_rxfh - command to get/set RX flow hash indir or/and hash key.850 * struct ethtool_rxfh - command to get/set RX flow hash indir or/and hash key.
851 * @cmd: Specific command number - %ETHTOOL_GRSSH or %ETHTOOL_SRSSH851 * @cmd: Specific command number - %ETHTOOL_GRSSH or %ETHTOOL_SRSSH
852 * @rss_context: RSS context identifier.852 * @rss_context: RSS context identifier.
853 * @indir_size: On entry, the array size of the user buffer, which may be zero.853 * @indir_size: On entry, the array size of the user buffer for the
854 * On return from %ETHTOOL_GRSSH, the array size of the hardware854 * indirection table, which may be zero, or (for %ETHTOOL_SRSSH),
855 * indirection table.855 * %ETH_RXFH_INDIR_NO_CHANGE. On return from %ETHTOOL_GRSSH,
856 * @key_size: On entry, the array size of the user buffer in bytes,856 * the array size of the hardware indirection table.
857 * which may be zero.857 * @key_size: On entry, the array size of the user buffer for the hash key,
858 * On return from %ETHTOOL_GRSSH, the size of the RSS hash key.858 * which may be zero. On return from %ETHTOOL_GRSSH, the size of the
859 * hardware hash key.
859 * @rsvd: Reserved for future extensions.860 * @rsvd: Reserved for future extensions.
860 * @rss_config: RX ring/queue index for each hash value i.e., indirection table861 * @rss_config: RX ring/queue index for each hash value i.e., indirection table
861 * of size @indir_size followed by hash key of size @key_size.862 * of @indir_size __u32 elements, followed by hash key of @key_size
863 * bytes.
862 *864 *
863 * For %ETHTOOL_GRSSH, a @indir_size and key_size of zero means that only the865 * For %ETHTOOL_GRSSH, a @indir_size and key_size of zero means that only the
864 * size should be returned. For %ETHTOOL_SRSSH, a @indir_size of 0xDEADBEEF866 * size should be returned. For %ETHTOOL_SRSSH, an @indir_size of
865 * means that indir table setting is not requested and a @indir_size of zero867 * %ETH_RXFH_INDIR_NO_CHANGE means that indir table setting is not requested
866 * means the indir table should be reset to default values. This last feature868 * and a @indir_size of zero means the indir table should be reset to default
867 * is not supported by the original implementations.869 * values.
868 */870 */
869struct ethtool_rxfh {871struct ethtool_rxfh {
870 __u32 cmd;872 __u32 cmd;
@@ -874,6 +876,7 @@ struct ethtool_rxfh { · 3 unmodified lines
874 __u32 rsvd[2];876 __u32 rsvd[2];
875 __u32 rss_config[0];877 __u32 rss_config[0];
876};878};
879#define ETH_RXFH_INDIR_NO_CHANGE 0xffffffff
877 880
878/**881/**
879 * struct ethtool_rx_ntuple_flow_spec - specification for RX flow filter882 * struct ethtool_rx_ntuple_flow_spec - specification for RX flow filter
net/core/ethtool.c+48−62
@@ -561,19 +561,17 @@ static int ethtool_copy_validate_indir(u32 *indir, void __user *useraddr, · 560 unmodified lines
561 struct ethtool_rxnfc *rx_rings,561 struct ethtool_rxnfc *rx_rings,
562 u32 size)562 u32 size)
563{563{
564 int ret = 0, i;564 int i;
565 565
566 if (copy_from_user(indir, useraddr, size * sizeof(indir[0])))566 if (copy_from_user(indir, useraddr, size * sizeof(indir[0])))
567 ret = -EFAULT;567 return -EFAULT;
568 568
569 /* Validate ring indices */569 /* Validate ring indices */
570 for (i = 0; i < size; i++) {570 for (i = 0; i < size; i++)
571 if (indir[i] >= rx_rings->data) {571 if (indir[i] >= rx_rings->data)
572 ret = -EINVAL;572 return -EINVAL;
573 break;573
574 }574 return 0;
575 }
576 return ret;
577}575}
578 576
579static noinline_for_stack int ethtool_get_rxfh_indir(struct net_device *dev,577static noinline_for_stack int ethtool_get_rxfh_indir(struct net_device *dev,
@@ -584,7 +582,7 @@ static noinline_for_stack int ethtool_get_rxfh_indir(struct net_device *dev, · 4 unmodified lines
584 int ret;582 int ret;
585 583
586 if (!dev->ethtool_ops->get_rxfh_indir_size ||584 if (!dev->ethtool_ops->get_rxfh_indir_size ||
587 !dev->ethtool_ops->get_rxfh_indir)585 !dev->ethtool_ops->get_rxfh)
588 return -EOPNOTSUPP;586 return -EOPNOTSUPP;
589 dev_size = dev->ethtool_ops->get_rxfh_indir_size(dev);587 dev_size = dev->ethtool_ops->get_rxfh_indir_size(dev);
590 if (dev_size == 0)588 if (dev_size == 0)
@@ -610,7 +608,7 @@ static noinline_for_stack int ethtool_get_rxfh_indir(struct net_device *dev, · 19 unmodified lines
610 if (!indir)608 if (!indir)
611 return -ENOMEM;609 return -ENOMEM;
612 610
613 ret = dev->ethtool_ops->get_rxfh_indir(dev, indir);611 ret = dev->ethtool_ops->get_rxfh(dev, indir, NULL);
614 if (ret)612 if (ret)
615 goto out;613 goto out;
616 614
@@ -634,7 +632,7 @@ static noinline_for_stack int ethtool_set_rxfh_indir(struct net_device *dev, · 17 unmodified lines
634 int ret;632 int ret;
635 u32 ringidx_offset = offsetof(struct ethtool_rxfh_indir, ring_index[0]);633 u32 ringidx_offset = offsetof(struct ethtool_rxfh_indir, ring_index[0]);
636 634
637 if (!ops->get_rxfh_indir_size || !ops->set_rxfh_indir ||635 if (!ops->get_rxfh_indir_size || !ops->set_rxfh ||
638 !ops->get_rxnfc)636 !ops->get_rxnfc)
639 return -EOPNOTSUPP;637 return -EOPNOTSUPP;
640 638
@@ -671,7 +669,7 @@ static noinline_for_stack int ethtool_set_rxfh_indir(struct net_device *dev, · 30 unmodified lines
671 goto out;669 goto out;
672 }670 }
673 671
674 ret = ops->set_rxfh_indir(dev, indir);672 ret = ops->set_rxfh(dev, indir, NULL);
675 673
676out:674out:
677 kfree(indir);675 kfree(indir);
@@ -683,11 +681,11 @@ static noinline_for_stack int ethtool_get_rxfh(struct net_device *dev, · 5 unmodified lines
683{681{
684 int ret;682 int ret;
685 const struct ethtool_ops *ops = dev->ethtool_ops;683 const struct ethtool_ops *ops = dev->ethtool_ops;
686 u32 user_indir_size = 0, user_key_size = 0;684 u32 user_indir_size, user_key_size;
687 u32 dev_indir_size = 0, dev_key_size = 0;685 u32 dev_indir_size = 0, dev_key_size = 0;
686 struct ethtool_rxfh rxfh;
688 u32 total_size;687 u32 total_size;
689 u32 indir_offset, indir_bytes;688 u32 indir_bytes;
690 u32 key_offset;
691 u32 *indir = NULL;689 u32 *indir = NULL;
692 u8 *hkey = NULL;690 u8 *hkey = NULL;
693 u8 *rss_config;691 u8 *rss_config;
@@ -699,33 +697,24 @@ static noinline_for_stack int ethtool_get_rxfh(struct net_device *dev, · 5 unmodified lines
699 697
700 if (ops->get_rxfh_indir_size)698 if (ops->get_rxfh_indir_size)
701 dev_indir_size = ops->get_rxfh_indir_size(dev);699 dev_indir_size = ops->get_rxfh_indir_size(dev);
702
703 indir_offset = offsetof(struct ethtool_rxfh, indir_size);
704
705 if (copy_from_user(&user_indir_size,
706 useraddr + indir_offset,
707 sizeof(user_indir_size)))
708 return -EFAULT;
709
710 if (copy_to_user(useraddr + indir_offset,
711 &dev_indir_size, sizeof(dev_indir_size)))
712 return -EFAULT;
713
714 if (ops->get_rxfh_key_size)700 if (ops->get_rxfh_key_size)
715 dev_key_size = ops->get_rxfh_key_size(dev);701 dev_key_size = ops->get_rxfh_key_size(dev);
716 702
717 if ((dev_key_size + dev_indir_size) == 0)703 if ((dev_key_size + dev_indir_size) == 0)
718 return -EOPNOTSUPP;704 return -EOPNOTSUPP;
719 705
720 key_offset = offsetof(struct ethtool_rxfh, key_size);706 if (copy_from_user(&rxfh, useraddr, sizeof(rxfh)))
721
722 if (copy_from_user(&user_key_size,
723 useraddr + key_offset,
724 sizeof(user_key_size)))
725 return -EFAULT;707 return -EFAULT;
708 user_indir_size = rxfh.indir_size;
709 user_key_size = rxfh.key_size;
726 710
727 if (copy_to_user(useraddr + key_offset,711 /* Check that reserved fields are 0 for now */
728 &dev_key_size, sizeof(dev_key_size)))712 if (rxfh.rss_context || rxfh.rsvd[0] || rxfh.rsvd[1])
713 return -EINVAL;
714
715 rxfh.indir_size = dev_indir_size;
716 rxfh.key_size = dev_key_size;
717 if (copy_to_user(useraddr, &rxfh, sizeof(rxfh)))
729 return -EFAULT;718 return -EFAULT;
730 719
731 /* If the user buffer size is 0, this is just a query for the720 /* If the user buffer size is 0, this is just a query for the
@@ -770,12 +759,11 @@ static noinline_for_stack int ethtool_set_rxfh(struct net_device *dev, · 38 unmodified lines
770 int ret;759 int ret;
771 const struct ethtool_ops *ops = dev->ethtool_ops;760 const struct ethtool_ops *ops = dev->ethtool_ops;
772 struct ethtool_rxnfc rx_rings;761 struct ethtool_rxnfc rx_rings;
773 u32 user_indir_size = 0, dev_indir_size = 0, i;762 struct ethtool_rxfh rxfh;
774 u32 user_key_size = 0, dev_key_size = 0;763 u32 dev_indir_size = 0, dev_key_size = 0, i;
775 u32 *indir = NULL, indir_bytes = 0;764 u32 *indir = NULL, indir_bytes = 0;
776 u8 *hkey = NULL;765 u8 *hkey = NULL;
777 u8 *rss_config;766 u8 *rss_config;
778 u32 indir_offset, key_offset;
779 u32 rss_cfg_offset = offsetof(struct ethtool_rxfh, rss_config[0]);767 u32 rss_cfg_offset = offsetof(struct ethtool_rxfh, rss_config[0]);
780 768
781 if (!(ops->get_rxfh_indir_size || ops->get_rxfh_key_size) ||769 if (!(ops->get_rxfh_indir_size || ops->get_rxfh_key_size) ||
@@ -784,36 +772,33 @@ static noinline_for_stack int ethtool_set_rxfh(struct net_device *dev, · 2 unmodified lines
784 772
785 if (ops->get_rxfh_indir_size)773 if (ops->get_rxfh_indir_size)
786 dev_indir_size = ops->get_rxfh_indir_size(dev);774 dev_indir_size = ops->get_rxfh_indir_size(dev);
787
788 indir_offset = offsetof(struct ethtool_rxfh, indir_size);
789 if (copy_from_user(&user_indir_size,
790 useraddr + indir_offset,
791 sizeof(user_indir_size)))
792 return -EFAULT;
793
794 if (ops->get_rxfh_key_size)775 if (ops->get_rxfh_key_size)
795 dev_key_size = dev->ethtool_ops->get_rxfh_key_size(dev);776 dev_key_size = dev->ethtool_ops->get_rxfh_key_size(dev);
796
797 if ((dev_key_size + dev_indir_size) == 0)777 if ((dev_key_size + dev_indir_size) == 0)
798 return -EOPNOTSUPP;778 return -EOPNOTSUPP;
799 779
800 key_offset = offsetof(struct ethtool_rxfh, key_size);780 if (copy_from_user(&rxfh, useraddr, sizeof(rxfh)))
801 if (copy_from_user(&user_key_size,
802 useraddr + key_offset,
803 sizeof(user_key_size)))
804 return -EFAULT;781 return -EFAULT;
805 782
783 /* Check that reserved fields are 0 for now */
784 if (rxfh.rss_context || rxfh.rsvd[0] || rxfh.rsvd[1])
785 return -EINVAL;
786
806 /* If either indir or hash key is valid, proceed further.787 /* If either indir or hash key is valid, proceed further.
788 * It is not valid to request that both be unchanged.
807 */789 */
808 if ((user_indir_size && ((user_indir_size != 0xDEADBEEF) &&790 if ((rxfh.indir_size &&
809 user_indir_size != dev_indir_size)) ||791 rxfh.indir_size != ETH_RXFH_INDIR_NO_CHANGE &&
810 (user_key_size && (user_key_size != dev_key_size)))792 rxfh.indir_size != dev_indir_size) ||
793 (rxfh.key_size && (rxfh.key_size != dev_key_size)) ||
794 (rxfh.indir_size == ETH_RXFH_INDIR_NO_CHANGE &&
795 rxfh.key_size == 0))
811 return -EINVAL;796 return -EINVAL;
812 797
813 if (user_indir_size != 0xDEADBEEF)798 if (rxfh.indir_size != ETH_RXFH_INDIR_NO_CHANGE)
814 indir_bytes = dev_indir_size * sizeof(indir[0]);799 indir_bytes = dev_indir_size * sizeof(indir[0]);
815 800
816 rss_config = kzalloc(indir_bytes + user_key_size, GFP_USER);801 rss_config = kzalloc(indir_bytes + rxfh.key_size, GFP_USER);
817 if (!rss_config)802 if (!rss_config)
818 return -ENOMEM;803 return -ENOMEM;
819 804
@@ -822,28 +807,29 @@ static noinline_for_stack int ethtool_set_rxfh(struct net_device *dev, · 2 unmodified lines
822 if (ret)807 if (ret)
823 goto out;808 goto out;
824 809
825 /* user_indir_size == 0 means reset the indir table to default.810 /* rxfh.indir_size == 0 means reset the indir table to default.
826 * user_indir_size == 0xDEADBEEF means indir setting is not requested.811 * rxfh.indir_size == ETH_RXFH_INDIR_NO_CHANGE means leave it unchanged.
827 */812 */
828 if (user_indir_size && user_indir_size != 0xDEADBEEF) {813 if (rxfh.indir_size &&
814 rxfh.indir_size != ETH_RXFH_INDIR_NO_CHANGE) {
829 indir = (u32 *)rss_config;815 indir = (u32 *)rss_config;
830 ret = ethtool_copy_validate_indir(indir,816 ret = ethtool_copy_validate_indir(indir,
831 useraddr + rss_cfg_offset,817 useraddr + rss_cfg_offset,
832 &rx_rings,818 &rx_rings,
833 user_indir_size);819 rxfh.indir_size);
834 if (ret)820 if (ret)
835 goto out;821 goto out;
836 } else if (user_indir_size == 0) {822 } else if (rxfh.indir_size == 0) {
837 indir = (u32 *)rss_config;823 indir = (u32 *)rss_config;
838 for (i = 0; i < dev_indir_size; i++)824 for (i = 0; i < dev_indir_size; i++)
839 indir[i] = ethtool_rxfh_indir_default(i, rx_rings.data);825 indir[i] = ethtool_rxfh_indir_default(i, rx_rings.data);
840 }826 }
841 827
842 if (user_key_size) {828 if (rxfh.key_size) {
843 hkey = rss_config + indir_bytes;829 hkey = rss_config + indir_bytes;
844 if (copy_from_user(hkey,830 if (copy_from_user(hkey,
845 useraddr + rss_cfg_offset + indir_bytes,831 useraddr + rss_cfg_offset + indir_bytes,
846 user_key_size)) {832 rxfh.key_size)) {
847 ret = -EFAULT;833 ret = -EFAULT;
848 goto out;834 goto out;
849 }835 }