Skip to content

Commit

Permalink
Merge branch 'ethtool-rssh-fixes' of git://git.kernel.org/pub/scm/lin…
Browse files Browse the repository at this point in the history
…ux/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
====================

Signed-off-by: David S. Miller <davem@davemloft.net>
  • Loading branch information
David S. Miller committed Jun 3, 2014
2 parents a68ab98 + f062a38 commit 014b201
Show file tree
Hide file tree
Showing 14 changed files with 120 additions and 129 deletions.
15 changes: 8 additions & 7 deletions drivers/net/ethernet/broadcom/bnx2x/bnx2x_ethtool.c
Original file line number Diff line number Diff line change
Expand Up @@ -3316,7 +3316,7 @@ static u32 bnx2x_get_rxfh_indir_size(struct net_device *dev)
return T_ETH_INDIRECTION_TABLE_SIZE;
}

static int bnx2x_get_rxfh_indir(struct net_device *dev, u32 *indir)
static int bnx2x_get_rxfh(struct net_device *dev, u32 *indir, u8 *key)
{
struct bnx2x *bp = netdev_priv(dev);
u8 ind_table[T_ETH_INDIRECTION_TABLE_SIZE] = {0};
Expand All @@ -3340,14 +3340,15 @@ static int bnx2x_get_rxfh_indir(struct net_device *dev, u32 *indir)
return 0;
}

static int bnx2x_set_rxfh_indir(struct net_device *dev, const u32 *indir)
static int bnx2x_set_rxfh(struct net_device *dev, const u32 *indir,
const u8 *key)
{
struct bnx2x *bp = netdev_priv(dev);
size_t i;

for (i = 0; i < T_ETH_INDIRECTION_TABLE_SIZE; i++) {
/*
* The same as in bnx2x_get_rxfh_indir: we can't use a memcpy()
* The same as in bnx2x_get_rxfh: we can't use a memcpy()
* as an internal storage of an indirection table is a u8 array
* while indir->ring_index points to an array of u32.
*
Expand Down Expand Up @@ -3471,8 +3472,8 @@ static const struct ethtool_ops bnx2x_ethtool_ops = {
.get_rxnfc = bnx2x_get_rxnfc,
.set_rxnfc = bnx2x_set_rxnfc,
.get_rxfh_indir_size = bnx2x_get_rxfh_indir_size,
.get_rxfh_indir = bnx2x_get_rxfh_indir,
.set_rxfh_indir = bnx2x_set_rxfh_indir,
.get_rxfh = bnx2x_get_rxfh,
.set_rxfh = bnx2x_set_rxfh,
.get_channels = bnx2x_get_channels,
.set_channels = bnx2x_set_channels,
.get_module_info = bnx2x_get_module_info,
Expand All @@ -3498,8 +3499,8 @@ static const struct ethtool_ops bnx2x_vf_ethtool_ops = {
.get_rxnfc = bnx2x_get_rxnfc,
.set_rxnfc = bnx2x_set_rxnfc,
.get_rxfh_indir_size = bnx2x_get_rxfh_indir_size,
.get_rxfh_indir = bnx2x_get_rxfh_indir,
.set_rxfh_indir = bnx2x_set_rxfh_indir,
.get_rxfh = bnx2x_get_rxfh,
.set_rxfh = bnx2x_set_rxfh,
.get_channels = bnx2x_get_channels,
.set_channels = bnx2x_set_channels,
};
Expand Down
8 changes: 4 additions & 4 deletions drivers/net/ethernet/broadcom/tg3.c
Original file line number Diff line number Diff line change
Expand Up @@ -12532,7 +12532,7 @@ static u32 tg3_get_rxfh_indir_size(struct net_device *dev)
return size;
}

static int tg3_get_rxfh_indir(struct net_device *dev, u32 *indir)
static int tg3_get_rxfh(struct net_device *dev, u32 *indir, u8 *key)
{
struct tg3 *tp = netdev_priv(dev);
int i;
Expand All @@ -12543,7 +12543,7 @@ static int tg3_get_rxfh_indir(struct net_device *dev, u32 *indir)
return 0;
}

static int tg3_set_rxfh_indir(struct net_device *dev, const u32 *indir)
static int tg3_set_rxfh(struct net_device *dev, const u32 *indir, const u8 *key)
{
struct tg3 *tp = netdev_priv(dev);
size_t i;
Expand Down Expand Up @@ -14075,8 +14075,8 @@ static const struct ethtool_ops tg3_ethtool_ops = {
.get_sset_count = tg3_get_sset_count,
.get_rxnfc = tg3_get_rxnfc,
.get_rxfh_indir_size = tg3_get_rxfh_indir_size,
.get_rxfh_indir = tg3_get_rxfh_indir,
.set_rxfh_indir = tg3_set_rxfh_indir,
.get_rxfh = tg3_get_rxfh,
.set_rxfh = tg3_set_rxfh,
.get_channels = tg3_get_channels,
.set_channels = tg3_set_channels,
.get_ts_info = tg3_get_ts_info,
Expand Down
8 changes: 4 additions & 4 deletions drivers/net/ethernet/chelsio/cxgb4/cxgb4_main.c
Original file line number Diff line number Diff line change
Expand Up @@ -2739,7 +2739,7 @@ static u32 get_rss_table_size(struct net_device *dev)
return pi->rss_size;
}

static int get_rss_table(struct net_device *dev, u32 *p)
static int get_rss_table(struct net_device *dev, u32 *p, u8 *key)
{
const struct port_info *pi = netdev_priv(dev);
unsigned int n = pi->rss_size;
Expand All @@ -2749,7 +2749,7 @@ static int get_rss_table(struct net_device *dev, u32 *p)
return 0;
}

static int set_rss_table(struct net_device *dev, const u32 *p)
static int set_rss_table(struct net_device *dev, const u32 *p, const u8 *key)
{
unsigned int i;
struct port_info *pi = netdev_priv(dev);
Expand Down Expand Up @@ -2851,8 +2851,8 @@ static const struct ethtool_ops cxgb_ethtool_ops = {
.set_wol = set_wol,
.get_rxnfc = get_rxnfc,
.get_rxfh_indir_size = get_rss_table_size,
.get_rxfh_indir = get_rss_table,
.set_rxfh_indir = set_rss_table,
.get_rxfh = get_rss_table,
.set_rxfh = set_rss_table,
.flash_device = set_flash,
};

Expand Down
2 changes: 1 addition & 1 deletion drivers/net/ethernet/emulex/benet/be_cmds.c
Original file line number Diff line number Diff line change
Expand Up @@ -2065,7 +2065,7 @@ int be_cmd_reset_function(struct be_adapter *adapter)
}

int be_cmd_rss_config(struct be_adapter *adapter, u8 *rsstable,
u32 rss_hash_opts, u16 table_size, u8 *rss_hkey)
u32 rss_hash_opts, u16 table_size, const u8 *rss_hkey)
{
struct be_mcc_wrb *wrb;
struct be_cmd_req_rss_config *req;
Expand Down
2 changes: 1 addition & 1 deletion drivers/net/ethernet/emulex/benet/be_cmds.h
Original file line number Diff line number Diff line change
Expand Up @@ -2082,7 +2082,7 @@ int be_cmd_query_fw_cfg(struct be_adapter *adapter, u32 *port_num,
u32 *function_mode, u32 *function_caps, u16 *asic_rev);
int be_cmd_reset_function(struct be_adapter *adapter);
int be_cmd_rss_config(struct be_adapter *adapter, u8 *rsstable,
u32 rss_hash_opts, u16 table_size, u8 *rss_hkey);
u32 rss_hash_opts, u16 table_size, const u8 *rss_hkey);
int be_process_mcc(struct be_adapter *adapter);
int be_cmd_set_beacon_state(struct be_adapter *adapter, u8 port_num, u8 beacon,
u8 status, u8 state);
Expand Down
3 changes: 2 additions & 1 deletion drivers/net/ethernet/emulex/benet/be_ethtool.c
Original file line number Diff line number Diff line change
Expand Up @@ -1117,7 +1117,8 @@ static int be_get_rxfh(struct net_device *netdev, u32 *indir, u8 *hkey)
return 0;
}

static int be_set_rxfh(struct net_device *netdev, u32 *indir, u8 *hkey)
static int be_set_rxfh(struct net_device *netdev, const u32 *indir,
const u8 *hkey)
{
int rc = 0, i, j;
struct be_adapter *adapter = netdev_priv(netdev);
Expand Down
15 changes: 9 additions & 6 deletions drivers/net/ethernet/intel/i40evf/i40evf_ethtool.c
Original file line number Diff line number Diff line change
Expand Up @@ -624,13 +624,14 @@ static u32 i40evf_get_rxfh_indir_size(struct net_device *netdev)
}

/**
* i40evf_get_rxfh_indir - get the rx flow hash indirection table
* i40evf_get_rxfh - get the rx flow hash indirection table
* @netdev: network interface device structure
* @indir: indirection table
* @key: hash key (will be %NULL until get_rxfh_key_size is implemented)
*
* Reads the indirection table directly from the hardware. Always returns 0.
**/
static int i40evf_get_rxfh_indir(struct net_device *netdev, u32 *indir)
static int i40evf_get_rxfh(struct net_device *netdev, u32 *indir, u8 *key)
{
struct i40evf_adapter *adapter = netdev_priv(netdev);
struct i40e_hw *hw = &adapter->hw;
Expand All @@ -648,14 +649,16 @@ static int i40evf_get_rxfh_indir(struct net_device *netdev, u32 *indir)
}

/**
* i40evf_set_rxfh_indir - set the rx flow hash indirection table
* i40evf_set_rxfh - set the rx flow hash indirection table
* @netdev: network interface device structure
* @indir: indirection table
* @key: hash key (will be %NULL until get_rxfh_key_size is implemented)
*
* Returns -EINVAL if the table specifies an inavlid queue id, otherwise
* returns 0 after programming the table.
**/
static int i40evf_set_rxfh_indir(struct net_device *netdev, const u32 *indir)
static int i40evf_set_rxfh(struct net_device *netdev, const u32 *indir,
const u8 *key)
{
struct i40evf_adapter *adapter = netdev_priv(netdev);
struct i40e_hw *hw = &adapter->hw;
Expand Down Expand Up @@ -689,8 +692,8 @@ static const struct ethtool_ops i40evf_ethtool_ops = {
.get_rxnfc = i40evf_get_rxnfc,
.set_rxnfc = i40evf_set_rxnfc,
.get_rxfh_indir_size = i40evf_get_rxfh_indir_size,
.get_rxfh_indir = i40evf_get_rxfh_indir,
.set_rxfh_indir = i40evf_set_rxfh_indir,
.get_rxfh = i40evf_get_rxfh,
.set_rxfh = i40evf_set_rxfh,
.get_channels = i40evf_get_channels,
};

Expand Down
9 changes: 5 additions & 4 deletions drivers/net/ethernet/intel/igb/igb_ethtool.c
Original file line number Diff line number Diff line change
Expand Up @@ -2830,7 +2830,7 @@ static u32 igb_get_rxfh_indir_size(struct net_device *netdev)
return IGB_RETA_SIZE;
}

static int igb_get_rxfh_indir(struct net_device *netdev, u32 *indir)
static int igb_get_rxfh(struct net_device *netdev, u32 *indir, u8 *key)
{
struct igb_adapter *adapter = netdev_priv(netdev);
int i;
Expand Down Expand Up @@ -2876,7 +2876,8 @@ void igb_write_rss_indir_tbl(struct igb_adapter *adapter)
}
}

static int igb_set_rxfh_indir(struct net_device *netdev, const u32 *indir)
static int igb_set_rxfh(struct net_device *netdev, const u32 *indir,
const u8 *key)
{
struct igb_adapter *adapter = netdev_priv(netdev);
struct e1000_hw *hw = &adapter->hw;
Expand Down Expand Up @@ -3025,8 +3026,8 @@ static const struct ethtool_ops igb_ethtool_ops = {
.get_module_info = igb_get_module_info,
.get_module_eeprom = igb_get_module_eeprom,
.get_rxfh_indir_size = igb_get_rxfh_indir_size,
.get_rxfh_indir = igb_get_rxfh_indir,
.set_rxfh_indir = igb_set_rxfh_indir,
.get_rxfh = igb_get_rxfh,
.set_rxfh = igb_set_rxfh,
.get_channels = igb_get_channels,
.set_channels = igb_set_channels,
.begin = igb_ethtool_begin,
Expand Down
10 changes: 5 additions & 5 deletions drivers/net/ethernet/mellanox/mlx4/en_ethtool.c
Original file line number Diff line number Diff line change
Expand Up @@ -564,7 +564,7 @@ static u32 mlx4_en_get_rxfh_indir_size(struct net_device *dev)
return priv->rx_ring_num;
}

static int mlx4_en_get_rxfh_indir(struct net_device *dev, u32 *ring_index)
static int mlx4_en_get_rxfh(struct net_device *dev, u32 *ring_index, u8 *key)
{
struct mlx4_en_priv *priv = netdev_priv(dev);
struct mlx4_en_rss_map *rss_map = &priv->rss_map;
Expand All @@ -582,8 +582,8 @@ static int mlx4_en_get_rxfh_indir(struct net_device *dev, u32 *ring_index)
return err;
}

static int mlx4_en_set_rxfh_indir(struct net_device *dev,
const u32 *ring_index)
static int mlx4_en_set_rxfh(struct net_device *dev, const u32 *ring_index,
const u8 *key)
{
struct mlx4_en_priv *priv = netdev_priv(dev);
struct mlx4_en_dev *mdev = priv->mdev;
Expand Down Expand Up @@ -1224,8 +1224,8 @@ const struct ethtool_ops mlx4_en_ethtool_ops = {
.get_rxnfc = mlx4_en_get_rxnfc,
.set_rxnfc = mlx4_en_set_rxnfc,
.get_rxfh_indir_size = mlx4_en_get_rxfh_indir_size,
.get_rxfh_indir = mlx4_en_get_rxfh_indir,
.set_rxfh_indir = mlx4_en_set_rxfh_indir,
.get_rxfh = mlx4_en_get_rxfh,
.set_rxfh = mlx4_en_set_rxfh,
.get_channels = mlx4_en_get_channels,
.set_channels = mlx4_en_set_channels,
.get_ts_info = mlx4_en_get_ts_info,
Expand Down
10 changes: 5 additions & 5 deletions drivers/net/ethernet/sfc/ethtool.c
Original file line number Diff line number Diff line change
Expand Up @@ -1033,16 +1033,16 @@ static u32 efx_ethtool_get_rxfh_indir_size(struct net_device *net_dev)
0 : ARRAY_SIZE(efx->rx_indir_table));
}

static int efx_ethtool_get_rxfh_indir(struct net_device *net_dev, u32 *indir)
static int efx_ethtool_get_rxfh(struct net_device *net_dev, u32 *indir, u8 *key)
{
struct efx_nic *efx = netdev_priv(net_dev);

memcpy(indir, efx->rx_indir_table, sizeof(efx->rx_indir_table));
return 0;
}

static int efx_ethtool_set_rxfh_indir(struct net_device *net_dev,
const u32 *indir)
static int efx_ethtool_set_rxfh(struct net_device *net_dev,
const u32 *indir, const u8 *key)
{
struct efx_nic *efx = netdev_priv(net_dev);

Expand Down Expand Up @@ -1125,8 +1125,8 @@ 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_indir = efx_ethtool_get_rxfh_indir,
.set_rxfh_indir = efx_ethtool_set_rxfh_indir,
.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,
Expand Down
8 changes: 4 additions & 4 deletions drivers/net/vmxnet3/vmxnet3_ethtool.c
Original file line number Diff line number Diff line change
Expand Up @@ -579,7 +579,7 @@ vmxnet3_get_rss_indir_size(struct net_device *netdev)
}

static int
vmxnet3_get_rss_indir(struct net_device *netdev, u32 *p)
vmxnet3_get_rss(struct net_device *netdev, u32 *p, u8 *key)
{
struct vmxnet3_adapter *adapter = netdev_priv(netdev);
struct UPT1_RSSConf *rssConf = adapter->rss_conf;
Expand All @@ -592,7 +592,7 @@ vmxnet3_get_rss_indir(struct net_device *netdev, u32 *p)
}

static int
vmxnet3_set_rss_indir(struct net_device *netdev, const u32 *p)
vmxnet3_set_rss(struct net_device *netdev, const u32 *p, const u8 *key)
{
unsigned int i;
unsigned long flags;
Expand Down Expand Up @@ -628,8 +628,8 @@ static const struct ethtool_ops vmxnet3_ethtool_ops = {
.get_rxnfc = vmxnet3_get_rxnfc,
#ifdef VMXNET3_RSS
.get_rxfh_indir_size = vmxnet3_get_rss_indir_size,
.get_rxfh_indir = vmxnet3_get_rss_indir,
.set_rxfh_indir = vmxnet3_set_rss_indir,
.get_rxfh = vmxnet3_get_rss,
.set_rxfh = vmxnet3_set_rss,
#endif
};

Expand Down
24 changes: 10 additions & 14 deletions include/linux/ethtool.h
Original file line number Diff line number Diff line change
Expand Up @@ -158,19 +158,16 @@ static inline u32 ethtool_rxfh_indir_default(u32 index, u32 n_rx_rings)
* Returns zero if not supported for this specific device.
* @get_rxfh_indir_size: Get the size of the RX flow hash indirection table.
* Returns zero if not supported for this specific device.
* @get_rxfh_indir: Get the contents of the RX flow hash indirection table.
* Will not be called if @get_rxfh_indir_size returns zero.
* @get_rxfh: Get the contents of the RX flow hash indirection table and hash
* key.
* Will not be called if @get_rxfh_indir_size and @get_rxfh_key_size
* returns zero.
* Will only be called if one or both of @get_rxfh_indir_size and
* @get_rxfh_key_size are implemented and return non-zero.
* Returns a negative error code or zero.
* @set_rxfh_indir: Set the contents of the RX flow hash indirection table.
* Will not be called if @get_rxfh_indir_size returns zero.
* @set_rxfh: Set the contents of the RX flow hash indirection table and
* hash key.
* Will not be called if @get_rxfh_indir_size and @get_rxfh_key_size
* returns zero.
* @set_rxfh: Set the contents of the RX flow hash indirection table and/or
* hash key. In case only the indirection table or hash key is to be
* changed, the other argument will be %NULL.
* Will only be called if one or both of @get_rxfh_indir_size and
* @get_rxfh_key_size are implemented and return non-zero.
* Returns a negative error code or zero.
* @get_channels: Get number of channels.
* @set_channels: Set number of channels. Returns a negative error code or
Expand Down Expand Up @@ -244,10 +241,9 @@ struct ethtool_ops {
int (*reset)(struct net_device *, u32 *);
u32 (*get_rxfh_key_size)(struct net_device *);
u32 (*get_rxfh_indir_size)(struct net_device *);
int (*get_rxfh)(struct net_device *, u32 *, u8 *);
int (*set_rxfh)(struct net_device *, u32 *, u8 *);
int (*get_rxfh_indir)(struct net_device *, u32 *);
int (*set_rxfh_indir)(struct net_device *, const u32 *);
int (*get_rxfh)(struct net_device *, u32 *indir, u8 *key);
int (*set_rxfh)(struct net_device *, const u32 *indir,
const u8 *key);
void (*get_channels)(struct net_device *, struct ethtool_channels *);
int (*set_channels)(struct net_device *, struct ethtool_channels *);
int (*get_dump_flag)(struct net_device *, struct ethtool_dump *);
Expand Down
25 changes: 14 additions & 11 deletions include/uapi/linux/ethtool.h
Original file line number Diff line number Diff line change
Expand Up @@ -850,21 +850,23 @@ struct ethtool_rxfh_indir {
* struct ethtool_rxfh - command to get/set RX flow hash indir or/and hash key.
* @cmd: Specific command number - %ETHTOOL_GRSSH or %ETHTOOL_SRSSH
* @rss_context: RSS context identifier.
* @indir_size: On entry, the array size of the user buffer, which may be zero.
* On return from %ETHTOOL_GRSSH, the array size of the hardware
* indirection table.
* @key_size: On entry, the array size of the user buffer in bytes,
* which may be zero.
* On return from %ETHTOOL_GRSSH, the size of the RSS hash key.
* @indir_size: On entry, the array size of the user buffer for the
* indirection table, which may be zero, or (for %ETHTOOL_SRSSH),
* %ETH_RXFH_INDIR_NO_CHANGE. On return from %ETHTOOL_GRSSH,
* the array size of the hardware indirection table.
* @key_size: On entry, the array size of the user buffer for the hash key,
* which may be zero. On return from %ETHTOOL_GRSSH, the size of the
* hardware hash key.
* @rsvd: Reserved for future extensions.
* @rss_config: RX ring/queue index for each hash value i.e., indirection table
* of size @indir_size followed by hash key of size @key_size.
* of @indir_size __u32 elements, followed by hash key of @key_size
* bytes.
*
* For %ETHTOOL_GRSSH, a @indir_size and key_size of zero means that only the
* size should be returned. For %ETHTOOL_SRSSH, a @indir_size of 0xDEADBEEF
* means that indir table setting is not requested and a @indir_size of zero
* means the indir table should be reset to default values. This last feature
* is not supported by the original implementations.
* size should be returned. For %ETHTOOL_SRSSH, an @indir_size of
* %ETH_RXFH_INDIR_NO_CHANGE means that indir table setting is not requested
* and a @indir_size of zero means the indir table should be reset to default
* values.
*/
struct ethtool_rxfh {
__u32 cmd;
Expand All @@ -874,6 +876,7 @@ struct ethtool_rxfh {
__u32 rsvd[2];
__u32 rss_config[0];
};
#define ETH_RXFH_INDIR_NO_CHANGE 0xffffffff

/**
* struct ethtool_rx_ntuple_flow_spec - specification for RX flow filter
Expand Down
Loading

0 comments on commit 014b201

Please sign in to comment.