Skip to content

Commit

Permalink
ethtool: Define and apply a default policy for RX flow hash indirection
Browse files Browse the repository at this point in the history
All drivers that support modification of the RX flow hash indirection
table initialise it in the same way: RX rings are assigned to table
entries in rotation.  Make that default policy explicit by having them
call a ethtool_rxfh_indir_default() function.

In the ethtool core, add support for a zero size value for
ETHTOOL_SRXFHINDIR, which resets the table to this default.

Partly-suggested-by: Matt Carlson <mcarlson@broadcom.com>
Signed-off-by: Ben Hutchings <bhutchings@solarflare.com>
Acked-by: Shreyas N Bhatewara <sbhatewara@vmware.com>
Signed-off-by: David S. Miller <davem@davemloft.net>
  • Loading branch information
Ben Hutchings authored and David S. Miller committed Dec 16, 2011
1 parent 7850f63 commit 278bc42
Show file tree
Hide file tree
Showing 6 changed files with 47 additions and 20 deletions.
3 changes: 2 additions & 1 deletion drivers/net/ethernet/broadcom/bnx2x/bnx2x_cmn.c
Original file line number Diff line number Diff line change
Expand Up @@ -1545,7 +1545,8 @@ static inline int bnx2x_init_rss_pf(struct bnx2x *bp)
if (bp->multi_mode != ETH_RSS_MODE_DISABLED) {
for (i = 0; i < sizeof(ind_table); i++)
ind_table[i] =
bp->fp->cl_id + (i % num_eth_queues);
bp->fp->cl_id +
ethtool_rxfh_indir_default(i, num_eth_queues);
}

/*
Expand Down
2 changes: 1 addition & 1 deletion drivers/net/ethernet/chelsio/cxgb4/cxgb4_main.c
Original file line number Diff line number Diff line change
Expand Up @@ -3449,7 +3449,7 @@ static int __devinit init_rss(struct adapter *adap)
if (!pi->rss)
return -ENOMEM;
for (j = 0; j < pi->rss_size; j++)
pi->rss[j] = j % pi->nqsets;
pi->rss[j] = ethtool_rxfh_indir_default(j, pi->nqsets);
}
return 0;
}
Expand Down
3 changes: 2 additions & 1 deletion drivers/net/ethernet/sfc/efx.c
Original file line number Diff line number Diff line change
Expand Up @@ -1336,7 +1336,8 @@ static int efx_probe_nic(struct efx_nic *efx)
if (efx->n_channels > 1)
get_random_bytes(&efx->rx_hash_key, sizeof(efx->rx_hash_key));
for (i = 0; i < ARRAY_SIZE(efx->rx_indir_table); i++)
efx->rx_indir_table[i] = i % efx->n_rx_channels;
efx->rx_indir_table[i] =
ethtool_rxfh_indir_default(i, efx->n_rx_channels);

efx_set_channels(efx);
netif_set_real_num_tx_queues(efx->net_dev, efx->n_tx_channels);
Expand Down
3 changes: 2 additions & 1 deletion drivers/net/vmxnet3/vmxnet3_drv.c
Original file line number Diff line number Diff line change
Expand Up @@ -2167,7 +2167,8 @@ vmxnet3_setup_driver_shared(struct vmxnet3_adapter *adapter)
rssConf->indTableSize = VMXNET3_RSS_IND_TABLE_SIZE;
get_random_bytes(&rssConf->hashKey[0], rssConf->hashKeySize);
for (i = 0; i < rssConf->indTableSize; i++)
rssConf->indTable[i] = i % adapter->num_rx_queues;
rssConf->indTable[i] = ethtool_rxfh_indir_default(
i, adapter->num_rx_queues);

devRead->rssConfDesc.confVer = 1;
devRead->rssConfDesc.confLen = sizeof(*rssConf);
Expand Down
23 changes: 20 additions & 3 deletions include/linux/ethtool.h
Original file line number Diff line number Diff line change
Expand Up @@ -543,10 +543,15 @@ struct compat_ethtool_rxnfc {
/**
* struct ethtool_rxfh_indir - command to get or set RX flow hash indirection
* @cmd: Specific command number - %ETHTOOL_GRXFHINDIR or %ETHTOOL_SRXFHINDIR
* @size: On entry, the array size of the user buffer, which may be zero
* for %ETHTOOL_GRXFHINDIR. On return from %ETHTOOL_GRXFHINDIR, the
* array size of the hardware indirection table.
* @size: On entry, the array size of the user buffer, which may be zero.
* On return from %ETHTOOL_GRXFHINDIR, the array size of the hardware
* indirection table.
* @ring_index: RX ring/queue index for each hash value
*
* For %ETHTOOL_GRXFHINDIR, a @size of zero means that only the size
* should be returned. For %ETHTOOL_SRXFHINDIR, a @size of zero means
* the table should be reset to default values. This last feature
* is not supported by the original implementations.
*/
struct ethtool_rxfh_indir {
__u32 cmd;
Expand Down Expand Up @@ -749,6 +754,18 @@ struct net_device;
/* Some generic methods drivers may use in their ethtool_ops */
u32 ethtool_op_get_link(struct net_device *dev);

/**
* ethtool_rxfh_indir_default - get default value for RX flow hash indirection
* @index: Index in RX flow hash indirection table
* @n_rx_rings: Number of RX rings to use
*
* This function provides the default policy for RX flow hash indirection.
*/
static inline u32 ethtool_rxfh_indir_default(u32 index, u32 n_rx_rings)
{
return index % n_rx_rings;
}

/**
* struct ethtool_ops - optional netdev operations
* @get_settings: Get various device settings including Ethernet link
Expand Down
33 changes: 20 additions & 13 deletions net/core/ethtool.c
Original file line number Diff line number Diff line change
Expand Up @@ -581,31 +581,38 @@ static noinline_for_stack int ethtool_set_rxfh_indir(struct net_device *dev,
sizeof(user_size)))
return -EFAULT;

if (user_size != dev_size)
if (user_size != 0 && user_size != dev_size)
return -EINVAL;

indir = kcalloc(dev_size, sizeof(indir[0]), GFP_USER);
if (!indir)
return -ENOMEM;

if (copy_from_user(indir,
useraddr +
offsetof(struct ethtool_rxfh_indir, ring_index[0]),
dev_size * sizeof(indir[0]))) {
ret = -EFAULT;
goto out;
}

/* Validate ring indices */
rx_rings.cmd = ETHTOOL_GRXRINGS;
ret = dev->ethtool_ops->get_rxnfc(dev, &rx_rings, NULL);
if (ret)
goto out;
for (i = 0; i < dev_size; i++) {
if (indir[i] >= rx_rings.data) {
ret = -EINVAL;

if (user_size == 0) {
for (i = 0; i < dev_size; i++)
indir[i] = ethtool_rxfh_indir_default(i, rx_rings.data);
} else {
if (copy_from_user(indir,
useraddr +
offsetof(struct ethtool_rxfh_indir,
ring_index[0]),
dev_size * sizeof(indir[0]))) {
ret = -EFAULT;
goto out;
}

/* Validate ring indices */
for (i = 0; i < dev_size; i++) {
if (indir[i] >= rx_rings.data) {
ret = -EINVAL;
goto out;
}
}
}

ret = dev->ethtool_ops->set_rxfh_indir(dev, indir);
Expand Down

0 comments on commit 278bc42

Please sign in to comment.