]> www.infradead.org Git - users/jedix/linux-maple.git/commitdiff
ethtool: Define and apply a default policy for RX flow hash indirection
authorJoe Jin <joe.jin@oracle.com>
Mon, 27 Aug 2012 12:54:45 +0000 (20:54 +0800)
committerJoe Jin <joe.jin@oracle.com>
Tue, 28 Aug 2012 07:21:28 +0000 (15:21 +0800)
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.

(backported from upstream commit 278bc4296bd64ffd1d3913b487dc8a520e423a7a)
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>
Signed-off-by: Joe Jin <joe.jin@oracle.com>
drivers/net/bnx2x/bnx2x_cmn.c
drivers/net/cxgb4/cxgb4_main.c
drivers/net/sfc/efx.c
drivers/net/vmxnet3/vmxnet3_drv.c
include/linux/ethtool.h
net/core/ethtool.c

index e9c94b737b6c4481501e5c8c726955f3ed2cbc17..538ac51b98d64fe19214f623d38e8bdb04c0c392 100644 (file)
@@ -1528,7 +1528,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);
        }
 
        /*
index 94bc3dfda9179ab1a3ac0f1c3ab5bbcf18d91aca..898fe7416ade4718c7ebdf46829fd5335bda6ffe 100644 (file)
@@ -3450,7 +3450,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;
 }
index 7d1651bc72d34bb21a1b9f4834e8804632c8c7f2..50f9285ffe433373ab60136f2f418225a8283392 100644 (file)
@@ -1337,7 +1337,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);
index 8d995264fcbda11b5ac62376da45d36eb5fbd6d4..fc960afc5fab907a80168026e9d2dc22e35066d0 100644 (file)
@@ -2201,7 +2201,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);
index 802707584223e30c3fb808a8cd3cdfa4092c4b97..304d38162ade1eca59ad11ec41f7b12d07746727 100644 (file)
@@ -542,10 +542,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;
@@ -774,6 +779,18 @@ int ethtool_op_set_flags(struct net_device *dev, u32 data, u32 supported);
 void ethtool_ntuple_flush(struct net_device *dev);
 bool ethtool_invalid_flags(struct net_device *dev, u32 data, u32 supported);
 
+/**
+ * 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
index f99486dee3af3e47c43fbae2e81c86accdcf2dd7..b72608821d60e684ddc02ccafa0338e34e70c40f 100644 (file)
@@ -860,31 +860,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);