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 ==================== Signed-off-by: David S. Miller <davem@davemloft.net>
This commit is contained in:
@@ -3316,7 +3316,7 @@ static u32 bnx2x_get_rxfh_indir_size(struct net_device *dev)
|
|||||||
return T_ETH_INDIRECTION_TABLE_SIZE;
|
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);
|
struct bnx2x *bp = netdev_priv(dev);
|
||||||
u8 ind_table[T_ETH_INDIRECTION_TABLE_SIZE] = {0};
|
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)
|
|||||||
return 0;
|
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);
|
struct bnx2x *bp = netdev_priv(dev);
|
||||||
size_t i;
|
size_t i;
|
||||||
|
|
||||||
for (i = 0; i < T_ETH_INDIRECTION_TABLE_SIZE; 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
|
* as an internal storage of an indirection table is a u8 array
|
||||||
* while indir->ring_index points to an array of u32.
|
* while indir->ring_index points to an array of u32.
|
||||||
*
|
*
|
||||||
@@ -3471,8 +3472,8 @@ static const struct ethtool_ops bnx2x_ethtool_ops = {
|
|||||||
.get_rxnfc = bnx2x_get_rxnfc,
|
.get_rxnfc = bnx2x_get_rxnfc,
|
||||||
.set_rxnfc = bnx2x_set_rxnfc,
|
.set_rxnfc = bnx2x_set_rxnfc,
|
||||||
.get_rxfh_indir_size = bnx2x_get_rxfh_indir_size,
|
.get_rxfh_indir_size = bnx2x_get_rxfh_indir_size,
|
||||||
.get_rxfh_indir = bnx2x_get_rxfh_indir,
|
.get_rxfh = bnx2x_get_rxfh,
|
||||||
.set_rxfh_indir = bnx2x_set_rxfh_indir,
|
.set_rxfh = bnx2x_set_rxfh,
|
||||||
.get_channels = bnx2x_get_channels,
|
.get_channels = bnx2x_get_channels,
|
||||||
.set_channels = bnx2x_set_channels,
|
.set_channels = bnx2x_set_channels,
|
||||||
.get_module_info = bnx2x_get_module_info,
|
.get_module_info = bnx2x_get_module_info,
|
||||||
@@ -3498,8 +3499,8 @@ static const struct ethtool_ops bnx2x_vf_ethtool_ops = {
|
|||||||
.get_rxnfc = bnx2x_get_rxnfc,
|
.get_rxnfc = bnx2x_get_rxnfc,
|
||||||
.set_rxnfc = bnx2x_set_rxnfc,
|
.set_rxnfc = bnx2x_set_rxnfc,
|
||||||
.get_rxfh_indir_size = bnx2x_get_rxfh_indir_size,
|
.get_rxfh_indir_size = bnx2x_get_rxfh_indir_size,
|
||||||
.get_rxfh_indir = bnx2x_get_rxfh_indir,
|
.get_rxfh = bnx2x_get_rxfh,
|
||||||
.set_rxfh_indir = bnx2x_set_rxfh_indir,
|
.set_rxfh = bnx2x_set_rxfh,
|
||||||
.get_channels = bnx2x_get_channels,
|
.get_channels = bnx2x_get_channels,
|
||||||
.set_channels = bnx2x_set_channels,
|
.set_channels = bnx2x_set_channels,
|
||||||
};
|
};
|
||||||
|
@@ -12532,7 +12532,7 @@ static u32 tg3_get_rxfh_indir_size(struct net_device *dev)
|
|||||||
return size;
|
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);
|
struct tg3 *tp = netdev_priv(dev);
|
||||||
int i;
|
int i;
|
||||||
@@ -12543,7 +12543,7 @@ static int tg3_get_rxfh_indir(struct net_device *dev, u32 *indir)
|
|||||||
return 0;
|
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);
|
struct tg3 *tp = netdev_priv(dev);
|
||||||
size_t i;
|
size_t i;
|
||||||
@@ -14075,8 +14075,8 @@ static const struct ethtool_ops tg3_ethtool_ops = {
|
|||||||
.get_sset_count = tg3_get_sset_count,
|
.get_sset_count = tg3_get_sset_count,
|
||||||
.get_rxnfc = tg3_get_rxnfc,
|
.get_rxnfc = tg3_get_rxnfc,
|
||||||
.get_rxfh_indir_size = tg3_get_rxfh_indir_size,
|
.get_rxfh_indir_size = tg3_get_rxfh_indir_size,
|
||||||
.get_rxfh_indir = tg3_get_rxfh_indir,
|
.get_rxfh = tg3_get_rxfh,
|
||||||
.set_rxfh_indir = tg3_set_rxfh_indir,
|
.set_rxfh = tg3_set_rxfh,
|
||||||
.get_channels = tg3_get_channels,
|
.get_channels = tg3_get_channels,
|
||||||
.set_channels = tg3_set_channels,
|
.set_channels = tg3_set_channels,
|
||||||
.get_ts_info = tg3_get_ts_info,
|
.get_ts_info = tg3_get_ts_info,
|
||||||
|
@@ -2739,7 +2739,7 @@ static u32 get_rss_table_size(struct net_device *dev)
|
|||||||
return pi->rss_size;
|
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);
|
const struct port_info *pi = netdev_priv(dev);
|
||||||
unsigned int n = pi->rss_size;
|
unsigned int n = pi->rss_size;
|
||||||
@@ -2749,7 +2749,7 @@ static int get_rss_table(struct net_device *dev, u32 *p)
|
|||||||
return 0;
|
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;
|
unsigned int i;
|
||||||
struct port_info *pi = netdev_priv(dev);
|
struct port_info *pi = netdev_priv(dev);
|
||||||
@@ -2851,8 +2851,8 @@ static const struct ethtool_ops cxgb_ethtool_ops = {
|
|||||||
.set_wol = set_wol,
|
.set_wol = set_wol,
|
||||||
.get_rxnfc = get_rxnfc,
|
.get_rxnfc = get_rxnfc,
|
||||||
.get_rxfh_indir_size = get_rss_table_size,
|
.get_rxfh_indir_size = get_rss_table_size,
|
||||||
.get_rxfh_indir = get_rss_table,
|
.get_rxfh = get_rss_table,
|
||||||
.set_rxfh_indir = set_rss_table,
|
.set_rxfh = set_rss_table,
|
||||||
.flash_device = set_flash,
|
.flash_device = set_flash,
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@@ -2065,7 +2065,7 @@ int be_cmd_reset_function(struct be_adapter *adapter)
|
|||||||
}
|
}
|
||||||
|
|
||||||
int be_cmd_rss_config(struct be_adapter *adapter, u8 *rsstable,
|
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_mcc_wrb *wrb;
|
||||||
struct be_cmd_req_rss_config *req;
|
struct be_cmd_req_rss_config *req;
|
||||||
|
@@ -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);
|
u32 *function_mode, u32 *function_caps, u16 *asic_rev);
|
||||||
int be_cmd_reset_function(struct be_adapter *adapter);
|
int be_cmd_reset_function(struct be_adapter *adapter);
|
||||||
int be_cmd_rss_config(struct be_adapter *adapter, u8 *rsstable,
|
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_process_mcc(struct be_adapter *adapter);
|
||||||
int be_cmd_set_beacon_state(struct be_adapter *adapter, u8 port_num, u8 beacon,
|
int be_cmd_set_beacon_state(struct be_adapter *adapter, u8 port_num, u8 beacon,
|
||||||
u8 status, u8 state);
|
u8 status, u8 state);
|
||||||
|
@@ -1117,7 +1117,8 @@ static int be_get_rxfh(struct net_device *netdev, u32 *indir, u8 *hkey)
|
|||||||
return 0;
|
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;
|
int rc = 0, i, j;
|
||||||
struct be_adapter *adapter = netdev_priv(netdev);
|
struct be_adapter *adapter = netdev_priv(netdev);
|
||||||
|
@@ -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
|
* @netdev: network interface device structure
|
||||||
* @indir: indirection table
|
* @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.
|
* 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 i40evf_adapter *adapter = netdev_priv(netdev);
|
||||||
struct i40e_hw *hw = &adapter->hw;
|
struct i40e_hw *hw = &adapter->hw;
|
||||||
@@ -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
|
* @netdev: network interface device structure
|
||||||
* @indir: indirection table
|
* @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 -EINVAL if the table specifies an inavlid queue id, otherwise
|
||||||
* returns 0 after programming the table.
|
* 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 i40evf_adapter *adapter = netdev_priv(netdev);
|
||||||
struct i40e_hw *hw = &adapter->hw;
|
struct i40e_hw *hw = &adapter->hw;
|
||||||
@@ -689,8 +692,8 @@ static const struct ethtool_ops i40evf_ethtool_ops = {
|
|||||||
.get_rxnfc = i40evf_get_rxnfc,
|
.get_rxnfc = i40evf_get_rxnfc,
|
||||||
.set_rxnfc = i40evf_set_rxnfc,
|
.set_rxnfc = i40evf_set_rxnfc,
|
||||||
.get_rxfh_indir_size = i40evf_get_rxfh_indir_size,
|
.get_rxfh_indir_size = i40evf_get_rxfh_indir_size,
|
||||||
.get_rxfh_indir = i40evf_get_rxfh_indir,
|
.get_rxfh = i40evf_get_rxfh,
|
||||||
.set_rxfh_indir = i40evf_set_rxfh_indir,
|
.set_rxfh = i40evf_set_rxfh,
|
||||||
.get_channels = i40evf_get_channels,
|
.get_channels = i40evf_get_channels,
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@@ -2830,7 +2830,7 @@ static u32 igb_get_rxfh_indir_size(struct net_device *netdev)
|
|||||||
return IGB_RETA_SIZE;
|
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);
|
struct igb_adapter *adapter = netdev_priv(netdev);
|
||||||
int i;
|
int i;
|
||||||
@@ -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 igb_adapter *adapter = netdev_priv(netdev);
|
||||||
struct e1000_hw *hw = &adapter->hw;
|
struct e1000_hw *hw = &adapter->hw;
|
||||||
@@ -3025,8 +3026,8 @@ static const struct ethtool_ops igb_ethtool_ops = {
|
|||||||
.get_module_info = igb_get_module_info,
|
.get_module_info = igb_get_module_info,
|
||||||
.get_module_eeprom = igb_get_module_eeprom,
|
.get_module_eeprom = igb_get_module_eeprom,
|
||||||
.get_rxfh_indir_size = igb_get_rxfh_indir_size,
|
.get_rxfh_indir_size = igb_get_rxfh_indir_size,
|
||||||
.get_rxfh_indir = igb_get_rxfh_indir,
|
.get_rxfh = igb_get_rxfh,
|
||||||
.set_rxfh_indir = igb_set_rxfh_indir,
|
.set_rxfh = igb_set_rxfh,
|
||||||
.get_channels = igb_get_channels,
|
.get_channels = igb_get_channels,
|
||||||
.set_channels = igb_set_channels,
|
.set_channels = igb_set_channels,
|
||||||
.begin = igb_ethtool_begin,
|
.begin = igb_ethtool_begin,
|
||||||
|
@@ -564,7 +564,7 @@ static u32 mlx4_en_get_rxfh_indir_size(struct net_device *dev)
|
|||||||
return priv->rx_ring_num;
|
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_priv *priv = netdev_priv(dev);
|
||||||
struct mlx4_en_rss_map *rss_map = &priv->rss_map;
|
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)
|
|||||||
return err;
|
return err;
|
||||||
}
|
}
|
||||||
|
|
||||||
static int mlx4_en_set_rxfh_indir(struct net_device *dev,
|
static int mlx4_en_set_rxfh(struct net_device *dev, const u32 *ring_index,
|
||||||
const u32 *ring_index)
|
const u8 *key)
|
||||||
{
|
{
|
||||||
struct mlx4_en_priv *priv = netdev_priv(dev);
|
struct mlx4_en_priv *priv = netdev_priv(dev);
|
||||||
struct mlx4_en_dev *mdev = priv->mdev;
|
struct mlx4_en_dev *mdev = priv->mdev;
|
||||||
@@ -1224,8 +1224,8 @@ const struct ethtool_ops mlx4_en_ethtool_ops = {
|
|||||||
.get_rxnfc = mlx4_en_get_rxnfc,
|
.get_rxnfc = mlx4_en_get_rxnfc,
|
||||||
.set_rxnfc = mlx4_en_set_rxnfc,
|
.set_rxnfc = mlx4_en_set_rxnfc,
|
||||||
.get_rxfh_indir_size = mlx4_en_get_rxfh_indir_size,
|
.get_rxfh_indir_size = mlx4_en_get_rxfh_indir_size,
|
||||||
.get_rxfh_indir = mlx4_en_get_rxfh_indir,
|
.get_rxfh = mlx4_en_get_rxfh,
|
||||||
.set_rxfh_indir = mlx4_en_set_rxfh_indir,
|
.set_rxfh = mlx4_en_set_rxfh,
|
||||||
.get_channels = mlx4_en_get_channels,
|
.get_channels = mlx4_en_get_channels,
|
||||||
.set_channels = mlx4_en_set_channels,
|
.set_channels = mlx4_en_set_channels,
|
||||||
.get_ts_info = mlx4_en_get_ts_info,
|
.get_ts_info = mlx4_en_get_ts_info,
|
||||||
|
@@ -1033,7 +1033,7 @@ static u32 efx_ethtool_get_rxfh_indir_size(struct net_device *net_dev)
|
|||||||
0 : ARRAY_SIZE(efx->rx_indir_table));
|
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);
|
struct efx_nic *efx = netdev_priv(net_dev);
|
||||||
|
|
||||||
@@ -1041,8 +1041,8 @@ static int efx_ethtool_get_rxfh_indir(struct net_device *net_dev, u32 *indir)
|
|||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
static int efx_ethtool_set_rxfh_indir(struct net_device *net_dev,
|
static int efx_ethtool_set_rxfh(struct net_device *net_dev,
|
||||||
const u32 *indir)
|
const u32 *indir, const u8 *key)
|
||||||
{
|
{
|
||||||
struct efx_nic *efx = netdev_priv(net_dev);
|
struct efx_nic *efx = netdev_priv(net_dev);
|
||||||
|
|
||||||
@@ -1125,8 +1125,8 @@ const struct ethtool_ops efx_ethtool_ops = {
|
|||||||
.get_rxnfc = efx_ethtool_get_rxnfc,
|
.get_rxnfc = efx_ethtool_get_rxnfc,
|
||||||
.set_rxnfc = efx_ethtool_set_rxnfc,
|
.set_rxnfc = efx_ethtool_set_rxnfc,
|
||||||
.get_rxfh_indir_size = efx_ethtool_get_rxfh_indir_size,
|
.get_rxfh_indir_size = efx_ethtool_get_rxfh_indir_size,
|
||||||
.get_rxfh_indir = efx_ethtool_get_rxfh_indir,
|
.get_rxfh = efx_ethtool_get_rxfh,
|
||||||
.set_rxfh_indir = efx_ethtool_set_rxfh_indir,
|
.set_rxfh = efx_ethtool_set_rxfh,
|
||||||
.get_ts_info = efx_ethtool_get_ts_info,
|
.get_ts_info = efx_ethtool_get_ts_info,
|
||||||
.get_module_info = efx_ethtool_get_module_info,
|
.get_module_info = efx_ethtool_get_module_info,
|
||||||
.get_module_eeprom = efx_ethtool_get_module_eeprom,
|
.get_module_eeprom = efx_ethtool_get_module_eeprom,
|
||||||
|
@@ -579,7 +579,7 @@ vmxnet3_get_rss_indir_size(struct net_device *netdev)
|
|||||||
}
|
}
|
||||||
|
|
||||||
static int
|
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 vmxnet3_adapter *adapter = netdev_priv(netdev);
|
||||||
struct UPT1_RSSConf *rssConf = adapter->rss_conf;
|
struct UPT1_RSSConf *rssConf = adapter->rss_conf;
|
||||||
@@ -592,7 +592,7 @@ vmxnet3_get_rss_indir(struct net_device *netdev, u32 *p)
|
|||||||
}
|
}
|
||||||
|
|
||||||
static int
|
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 int i;
|
||||||
unsigned long flags;
|
unsigned long flags;
|
||||||
@@ -628,8 +628,8 @@ static const struct ethtool_ops vmxnet3_ethtool_ops = {
|
|||||||
.get_rxnfc = vmxnet3_get_rxnfc,
|
.get_rxnfc = vmxnet3_get_rxnfc,
|
||||||
#ifdef VMXNET3_RSS
|
#ifdef VMXNET3_RSS
|
||||||
.get_rxfh_indir_size = vmxnet3_get_rss_indir_size,
|
.get_rxfh_indir_size = vmxnet3_get_rss_indir_size,
|
||||||
.get_rxfh_indir = vmxnet3_get_rss_indir,
|
.get_rxfh = vmxnet3_get_rss,
|
||||||
.set_rxfh_indir = vmxnet3_set_rss_indir,
|
.set_rxfh = vmxnet3_set_rss,
|
||||||
#endif
|
#endif
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@@ -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.
|
* Returns zero if not supported for this specific device.
|
||||||
* @get_rxfh_indir_size: Get the size of the RX flow hash indirection table.
|
* @get_rxfh_indir_size: Get the size of the RX flow hash indirection table.
|
||||||
* Returns zero if not supported for this specific device.
|
* 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
|
* @get_rxfh: Get the contents of the RX flow hash indirection table and hash
|
||||||
* key.
|
* key.
|
||||||
* Will not be called if @get_rxfh_indir_size and @get_rxfh_key_size
|
* Will only be called if one or both of @get_rxfh_indir_size and
|
||||||
* returns zero.
|
* @get_rxfh_key_size are implemented and return non-zero.
|
||||||
* Returns a negative error code or zero.
|
* Returns a negative error code or zero.
|
||||||
* @set_rxfh_indir: Set the contents of the RX flow hash indirection table.
|
* @set_rxfh: Set the contents of the RX flow hash indirection table and/or
|
||||||
* Will not be called if @get_rxfh_indir_size returns zero.
|
* hash key. In case only the indirection table or hash key is to be
|
||||||
* @set_rxfh: Set the contents of the RX flow hash indirection table and
|
* changed, the other argument will be %NULL.
|
||||||
* hash key.
|
* Will only be called if one or both of @get_rxfh_indir_size and
|
||||||
* Will not be called if @get_rxfh_indir_size and @get_rxfh_key_size
|
* @get_rxfh_key_size are implemented and return non-zero.
|
||||||
* returns zero.
|
|
||||||
* Returns a negative error code or zero.
|
* Returns a negative error code or zero.
|
||||||
* @get_channels: Get number of channels.
|
* @get_channels: Get number of channels.
|
||||||
* @set_channels: Set number of channels. Returns a negative error code or
|
* @set_channels: Set number of channels. Returns a negative error code or
|
||||||
@@ -244,10 +241,9 @@ struct ethtool_ops {
|
|||||||
int (*reset)(struct net_device *, u32 *);
|
int (*reset)(struct net_device *, u32 *);
|
||||||
u32 (*get_rxfh_key_size)(struct net_device *);
|
u32 (*get_rxfh_key_size)(struct net_device *);
|
||||||
u32 (*get_rxfh_indir_size)(struct net_device *);
|
u32 (*get_rxfh_indir_size)(struct net_device *);
|
||||||
int (*get_rxfh)(struct net_device *, u32 *, u8 *);
|
int (*get_rxfh)(struct net_device *, u32 *indir, u8 *key);
|
||||||
int (*set_rxfh)(struct net_device *, u32 *, u8 *);
|
int (*set_rxfh)(struct net_device *, const u32 *indir,
|
||||||
int (*get_rxfh_indir)(struct net_device *, u32 *);
|
const u8 *key);
|
||||||
int (*set_rxfh_indir)(struct net_device *, const u32 *);
|
|
||||||
void (*get_channels)(struct net_device *, struct ethtool_channels *);
|
void (*get_channels)(struct net_device *, struct ethtool_channels *);
|
||||||
int (*set_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 *);
|
int (*get_dump_flag)(struct net_device *, struct ethtool_dump *);
|
||||||
|
@@ -850,21 +850,23 @@ struct ethtool_rxfh_indir {
|
|||||||
* struct ethtool_rxfh - command to get/set RX flow hash indir or/and hash key.
|
* struct ethtool_rxfh - command to get/set RX flow hash indir or/and hash key.
|
||||||
* @cmd: Specific command number - %ETHTOOL_GRSSH or %ETHTOOL_SRSSH
|
* @cmd: Specific command number - %ETHTOOL_GRSSH or %ETHTOOL_SRSSH
|
||||||
* @rss_context: RSS context identifier.
|
* @rss_context: RSS context identifier.
|
||||||
* @indir_size: On entry, the array size of the user buffer, which may be zero.
|
* @indir_size: On entry, the array size of the user buffer for the
|
||||||
* On return from %ETHTOOL_GRSSH, the array size of the hardware
|
* indirection table, which may be zero, or (for %ETHTOOL_SRSSH),
|
||||||
* indirection table.
|
* %ETH_RXFH_INDIR_NO_CHANGE. On return from %ETHTOOL_GRSSH,
|
||||||
* @key_size: On entry, the array size of the user buffer in bytes,
|
* the array size of the hardware indirection table.
|
||||||
* which may be zero.
|
* @key_size: On entry, the array size of the user buffer for the hash key,
|
||||||
* On return from %ETHTOOL_GRSSH, the size of the RSS hash key.
|
* which may be zero. On return from %ETHTOOL_GRSSH, the size of the
|
||||||
|
* hardware hash key.
|
||||||
* @rsvd: Reserved for future extensions.
|
* @rsvd: Reserved for future extensions.
|
||||||
* @rss_config: RX ring/queue index for each hash value i.e., indirection table
|
* @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
|
* 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
|
* size should be returned. For %ETHTOOL_SRSSH, an @indir_size of
|
||||||
* means that indir table setting is not requested and a @indir_size of zero
|
* %ETH_RXFH_INDIR_NO_CHANGE means that indir table setting is not requested
|
||||||
* means the indir table should be reset to default values. This last feature
|
* and a @indir_size of zero means the indir table should be reset to default
|
||||||
* is not supported by the original implementations.
|
* values.
|
||||||
*/
|
*/
|
||||||
struct ethtool_rxfh {
|
struct ethtool_rxfh {
|
||||||
__u32 cmd;
|
__u32 cmd;
|
||||||
@@ -874,6 +876,7 @@ struct ethtool_rxfh {
|
|||||||
__u32 rsvd[2];
|
__u32 rsvd[2];
|
||||||
__u32 rss_config[0];
|
__u32 rss_config[0];
|
||||||
};
|
};
|
||||||
|
#define ETH_RXFH_INDIR_NO_CHANGE 0xffffffff
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* struct ethtool_rx_ntuple_flow_spec - specification for RX flow filter
|
* struct ethtool_rx_ntuple_flow_spec - specification for RX flow filter
|
||||||
|
@@ -561,19 +561,17 @@ static int ethtool_copy_validate_indir(u32 *indir, void __user *useraddr,
|
|||||||
struct ethtool_rxnfc *rx_rings,
|
struct ethtool_rxnfc *rx_rings,
|
||||||
u32 size)
|
u32 size)
|
||||||
{
|
{
|
||||||
int ret = 0, i;
|
int i;
|
||||||
|
|
||||||
if (copy_from_user(indir, useraddr, size * sizeof(indir[0])))
|
if (copy_from_user(indir, useraddr, size * sizeof(indir[0])))
|
||||||
ret = -EFAULT;
|
return -EFAULT;
|
||||||
|
|
||||||
/* Validate ring indices */
|
/* Validate ring indices */
|
||||||
for (i = 0; i < size; i++) {
|
for (i = 0; i < size; i++)
|
||||||
if (indir[i] >= rx_rings->data) {
|
if (indir[i] >= rx_rings->data)
|
||||||
ret = -EINVAL;
|
return -EINVAL;
|
||||||
break;
|
|
||||||
}
|
return 0;
|
||||||
}
|
|
||||||
return ret;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
static noinline_for_stack int ethtool_get_rxfh_indir(struct net_device *dev,
|
static 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,
|
|||||||
int ret;
|
int ret;
|
||||||
|
|
||||||
if (!dev->ethtool_ops->get_rxfh_indir_size ||
|
if (!dev->ethtool_ops->get_rxfh_indir_size ||
|
||||||
!dev->ethtool_ops->get_rxfh_indir)
|
!dev->ethtool_ops->get_rxfh)
|
||||||
return -EOPNOTSUPP;
|
return -EOPNOTSUPP;
|
||||||
dev_size = dev->ethtool_ops->get_rxfh_indir_size(dev);
|
dev_size = dev->ethtool_ops->get_rxfh_indir_size(dev);
|
||||||
if (dev_size == 0)
|
if (dev_size == 0)
|
||||||
@@ -610,7 +608,7 @@ static noinline_for_stack int ethtool_get_rxfh_indir(struct net_device *dev,
|
|||||||
if (!indir)
|
if (!indir)
|
||||||
return -ENOMEM;
|
return -ENOMEM;
|
||||||
|
|
||||||
ret = dev->ethtool_ops->get_rxfh_indir(dev, indir);
|
ret = dev->ethtool_ops->get_rxfh(dev, indir, NULL);
|
||||||
if (ret)
|
if (ret)
|
||||||
goto out;
|
goto out;
|
||||||
|
|
||||||
@@ -634,7 +632,7 @@ static noinline_for_stack int ethtool_set_rxfh_indir(struct net_device *dev,
|
|||||||
int ret;
|
int ret;
|
||||||
u32 ringidx_offset = offsetof(struct ethtool_rxfh_indir, ring_index[0]);
|
u32 ringidx_offset = offsetof(struct ethtool_rxfh_indir, ring_index[0]);
|
||||||
|
|
||||||
if (!ops->get_rxfh_indir_size || !ops->set_rxfh_indir ||
|
if (!ops->get_rxfh_indir_size || !ops->set_rxfh ||
|
||||||
!ops->get_rxnfc)
|
!ops->get_rxnfc)
|
||||||
return -EOPNOTSUPP;
|
return -EOPNOTSUPP;
|
||||||
|
|
||||||
@@ -671,7 +669,7 @@ static noinline_for_stack int ethtool_set_rxfh_indir(struct net_device *dev,
|
|||||||
goto out;
|
goto out;
|
||||||
}
|
}
|
||||||
|
|
||||||
ret = ops->set_rxfh_indir(dev, indir);
|
ret = ops->set_rxfh(dev, indir, NULL);
|
||||||
|
|
||||||
out:
|
out:
|
||||||
kfree(indir);
|
kfree(indir);
|
||||||
@@ -683,11 +681,11 @@ static noinline_for_stack int ethtool_get_rxfh(struct net_device *dev,
|
|||||||
{
|
{
|
||||||
int ret;
|
int ret;
|
||||||
const struct ethtool_ops *ops = dev->ethtool_ops;
|
const struct ethtool_ops *ops = dev->ethtool_ops;
|
||||||
u32 user_indir_size = 0, user_key_size = 0;
|
u32 user_indir_size, user_key_size;
|
||||||
u32 dev_indir_size = 0, dev_key_size = 0;
|
u32 dev_indir_size = 0, dev_key_size = 0;
|
||||||
|
struct ethtool_rxfh rxfh;
|
||||||
u32 total_size;
|
u32 total_size;
|
||||||
u32 indir_offset, indir_bytes;
|
u32 indir_bytes;
|
||||||
u32 key_offset;
|
|
||||||
u32 *indir = NULL;
|
u32 *indir = NULL;
|
||||||
u8 *hkey = NULL;
|
u8 *hkey = NULL;
|
||||||
u8 *rss_config;
|
u8 *rss_config;
|
||||||
@@ -699,33 +697,24 @@ static noinline_for_stack int ethtool_get_rxfh(struct net_device *dev,
|
|||||||
|
|
||||||
if (ops->get_rxfh_indir_size)
|
if (ops->get_rxfh_indir_size)
|
||||||
dev_indir_size = ops->get_rxfh_indir_size(dev);
|
dev_indir_size = ops->get_rxfh_indir_size(dev);
|
||||||
|
|
||||||
indir_offset = offsetof(struct ethtool_rxfh, indir_size);
|
|
||||||
|
|
||||||
if (copy_from_user(&user_indir_size,
|
|
||||||
useraddr + indir_offset,
|
|
||||||
sizeof(user_indir_size)))
|
|
||||||
return -EFAULT;
|
|
||||||
|
|
||||||
if (copy_to_user(useraddr + indir_offset,
|
|
||||||
&dev_indir_size, sizeof(dev_indir_size)))
|
|
||||||
return -EFAULT;
|
|
||||||
|
|
||||||
if (ops->get_rxfh_key_size)
|
if (ops->get_rxfh_key_size)
|
||||||
dev_key_size = ops->get_rxfh_key_size(dev);
|
dev_key_size = ops->get_rxfh_key_size(dev);
|
||||||
|
|
||||||
if ((dev_key_size + dev_indir_size) == 0)
|
if ((dev_key_size + dev_indir_size) == 0)
|
||||||
return -EOPNOTSUPP;
|
return -EOPNOTSUPP;
|
||||||
|
|
||||||
key_offset = offsetof(struct ethtool_rxfh, key_size);
|
if (copy_from_user(&rxfh, useraddr, sizeof(rxfh)))
|
||||||
|
|
||||||
if (copy_from_user(&user_key_size,
|
|
||||||
useraddr + key_offset,
|
|
||||||
sizeof(user_key_size)))
|
|
||||||
return -EFAULT;
|
return -EFAULT;
|
||||||
|
user_indir_size = rxfh.indir_size;
|
||||||
|
user_key_size = rxfh.key_size;
|
||||||
|
|
||||||
if (copy_to_user(useraddr + key_offset,
|
/* Check that reserved fields are 0 for now */
|
||||||
&dev_key_size, sizeof(dev_key_size)))
|
if (rxfh.rss_context || rxfh.rsvd[0] || rxfh.rsvd[1])
|
||||||
|
return -EINVAL;
|
||||||
|
|
||||||
|
rxfh.indir_size = dev_indir_size;
|
||||||
|
rxfh.key_size = dev_key_size;
|
||||||
|
if (copy_to_user(useraddr, &rxfh, sizeof(rxfh)))
|
||||||
return -EFAULT;
|
return -EFAULT;
|
||||||
|
|
||||||
/* If the user buffer size is 0, this is just a query for the
|
/* 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,
|
|||||||
int ret;
|
int ret;
|
||||||
const struct ethtool_ops *ops = dev->ethtool_ops;
|
const struct ethtool_ops *ops = dev->ethtool_ops;
|
||||||
struct ethtool_rxnfc rx_rings;
|
struct ethtool_rxnfc rx_rings;
|
||||||
u32 user_indir_size = 0, dev_indir_size = 0, i;
|
struct ethtool_rxfh rxfh;
|
||||||
u32 user_key_size = 0, dev_key_size = 0;
|
u32 dev_indir_size = 0, dev_key_size = 0, i;
|
||||||
u32 *indir = NULL, indir_bytes = 0;
|
u32 *indir = NULL, indir_bytes = 0;
|
||||||
u8 *hkey = NULL;
|
u8 *hkey = NULL;
|
||||||
u8 *rss_config;
|
u8 *rss_config;
|
||||||
u32 indir_offset, key_offset;
|
|
||||||
u32 rss_cfg_offset = offsetof(struct ethtool_rxfh, rss_config[0]);
|
u32 rss_cfg_offset = offsetof(struct ethtool_rxfh, rss_config[0]);
|
||||||
|
|
||||||
if (!(ops->get_rxfh_indir_size || ops->get_rxfh_key_size) ||
|
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,
|
|||||||
|
|
||||||
if (ops->get_rxfh_indir_size)
|
if (ops->get_rxfh_indir_size)
|
||||||
dev_indir_size = ops->get_rxfh_indir_size(dev);
|
dev_indir_size = ops->get_rxfh_indir_size(dev);
|
||||||
|
|
||||||
indir_offset = offsetof(struct ethtool_rxfh, indir_size);
|
|
||||||
if (copy_from_user(&user_indir_size,
|
|
||||||
useraddr + indir_offset,
|
|
||||||
sizeof(user_indir_size)))
|
|
||||||
return -EFAULT;
|
|
||||||
|
|
||||||
if (ops->get_rxfh_key_size)
|
if (ops->get_rxfh_key_size)
|
||||||
dev_key_size = dev->ethtool_ops->get_rxfh_key_size(dev);
|
dev_key_size = dev->ethtool_ops->get_rxfh_key_size(dev);
|
||||||
|
|
||||||
if ((dev_key_size + dev_indir_size) == 0)
|
if ((dev_key_size + dev_indir_size) == 0)
|
||||||
return -EOPNOTSUPP;
|
return -EOPNOTSUPP;
|
||||||
|
|
||||||
key_offset = offsetof(struct ethtool_rxfh, key_size);
|
if (copy_from_user(&rxfh, useraddr, sizeof(rxfh)))
|
||||||
if (copy_from_user(&user_key_size,
|
|
||||||
useraddr + key_offset,
|
|
||||||
sizeof(user_key_size)))
|
|
||||||
return -EFAULT;
|
return -EFAULT;
|
||||||
|
|
||||||
/* If either indir or hash key is valid, proceed further.
|
/* Check that reserved fields are 0 for now */
|
||||||
*/
|
if (rxfh.rss_context || rxfh.rsvd[0] || rxfh.rsvd[1])
|
||||||
if ((user_indir_size && ((user_indir_size != 0xDEADBEEF) &&
|
|
||||||
user_indir_size != dev_indir_size)) ||
|
|
||||||
(user_key_size && (user_key_size != dev_key_size)))
|
|
||||||
return -EINVAL;
|
return -EINVAL;
|
||||||
|
|
||||||
if (user_indir_size != 0xDEADBEEF)
|
/* If either indir or hash key is valid, proceed further.
|
||||||
|
* It is not valid to request that both be unchanged.
|
||||||
|
*/
|
||||||
|
if ((rxfh.indir_size &&
|
||||||
|
rxfh.indir_size != ETH_RXFH_INDIR_NO_CHANGE &&
|
||||||
|
rxfh.indir_size != dev_indir_size) ||
|
||||||
|
(rxfh.key_size && (rxfh.key_size != dev_key_size)) ||
|
||||||
|
(rxfh.indir_size == ETH_RXFH_INDIR_NO_CHANGE &&
|
||||||
|
rxfh.key_size == 0))
|
||||||
|
return -EINVAL;
|
||||||
|
|
||||||
|
if (rxfh.indir_size != ETH_RXFH_INDIR_NO_CHANGE)
|
||||||
indir_bytes = dev_indir_size * sizeof(indir[0]);
|
indir_bytes = dev_indir_size * sizeof(indir[0]);
|
||||||
|
|
||||||
rss_config = kzalloc(indir_bytes + user_key_size, GFP_USER);
|
rss_config = kzalloc(indir_bytes + rxfh.key_size, GFP_USER);
|
||||||
if (!rss_config)
|
if (!rss_config)
|
||||||
return -ENOMEM;
|
return -ENOMEM;
|
||||||
|
|
||||||
@@ -822,28 +807,29 @@ static noinline_for_stack int ethtool_set_rxfh(struct net_device *dev,
|
|||||||
if (ret)
|
if (ret)
|
||||||
goto out;
|
goto out;
|
||||||
|
|
||||||
/* user_indir_size == 0 means reset the indir table to default.
|
/* rxfh.indir_size == 0 means reset the indir table to default.
|
||||||
* user_indir_size == 0xDEADBEEF means indir setting is not requested.
|
* rxfh.indir_size == ETH_RXFH_INDIR_NO_CHANGE means leave it unchanged.
|
||||||
*/
|
*/
|
||||||
if (user_indir_size && user_indir_size != 0xDEADBEEF) {
|
if (rxfh.indir_size &&
|
||||||
|
rxfh.indir_size != ETH_RXFH_INDIR_NO_CHANGE) {
|
||||||
indir = (u32 *)rss_config;
|
indir = (u32 *)rss_config;
|
||||||
ret = ethtool_copy_validate_indir(indir,
|
ret = ethtool_copy_validate_indir(indir,
|
||||||
useraddr + rss_cfg_offset,
|
useraddr + rss_cfg_offset,
|
||||||
&rx_rings,
|
&rx_rings,
|
||||||
user_indir_size);
|
rxfh.indir_size);
|
||||||
if (ret)
|
if (ret)
|
||||||
goto out;
|
goto out;
|
||||||
} else if (user_indir_size == 0) {
|
} else if (rxfh.indir_size == 0) {
|
||||||
indir = (u32 *)rss_config;
|
indir = (u32 *)rss_config;
|
||||||
for (i = 0; i < dev_indir_size; i++)
|
for (i = 0; i < dev_indir_size; i++)
|
||||||
indir[i] = ethtool_rxfh_indir_default(i, rx_rings.data);
|
indir[i] = ethtool_rxfh_indir_default(i, rx_rings.data);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (user_key_size) {
|
if (rxfh.key_size) {
|
||||||
hkey = rss_config + indir_bytes;
|
hkey = rss_config + indir_bytes;
|
||||||
if (copy_from_user(hkey,
|
if (copy_from_user(hkey,
|
||||||
useraddr + rss_cfg_offset + indir_bytes,
|
useraddr + rss_cfg_offset + indir_bytes,
|
||||||
user_key_size)) {
|
rxfh.key_size)) {
|
||||||
ret = -EFAULT;
|
ret = -EFAULT;
|
||||||
goto out;
|
goto out;
|
||||||
}
|
}
|
||||||
|
Reference in New Issue
Block a user