aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--drivers/net/ethernet/broadcom/bnx2x/bnx2x_cmn.c3
-rw-r--r--drivers/net/ethernet/chelsio/cxgb4/cxgb4_main.c2
-rw-r--r--drivers/net/ethernet/sfc/efx.c3
-rw-r--r--drivers/net/vmxnet3/vmxnet3_drv.c3
-rw-r--r--include/linux/ethtool.h23
-rw-r--r--net/core/ethtool.c33
6 files changed, 47 insertions, 20 deletions
diff --git a/drivers/net/ethernet/broadcom/bnx2x/bnx2x_cmn.c b/drivers/net/ethernet/broadcom/bnx2x/bnx2x_cmn.c
index 64f5cf5c68d1..2b731b253598 100644
--- a/drivers/net/ethernet/broadcom/bnx2x/bnx2x_cmn.c
+++ b/drivers/net/ethernet/broadcom/bnx2x/bnx2x_cmn.c
@@ -1545,7 +1545,8 @@ static inline int bnx2x_init_rss_pf(struct bnx2x *bp)
1545 if (bp->multi_mode != ETH_RSS_MODE_DISABLED) { 1545 if (bp->multi_mode != ETH_RSS_MODE_DISABLED) {
1546 for (i = 0; i < sizeof(ind_table); i++) 1546 for (i = 0; i < sizeof(ind_table); i++)
1547 ind_table[i] = 1547 ind_table[i] =
1548 bp->fp->cl_id + (i % num_eth_queues); 1548 bp->fp->cl_id +
1549 ethtool_rxfh_indir_default(i, num_eth_queues);
1549 } 1550 }
1550 1551
1551 /* 1552 /*
diff --git a/drivers/net/ethernet/chelsio/cxgb4/cxgb4_main.c b/drivers/net/ethernet/chelsio/cxgb4/cxgb4_main.c
index 8ffd55bdef3d..fccbe490c7f0 100644
--- a/drivers/net/ethernet/chelsio/cxgb4/cxgb4_main.c
+++ b/drivers/net/ethernet/chelsio/cxgb4/cxgb4_main.c
@@ -3449,7 +3449,7 @@ static int __devinit init_rss(struct adapter *adap)
3449 if (!pi->rss) 3449 if (!pi->rss)
3450 return -ENOMEM; 3450 return -ENOMEM;
3451 for (j = 0; j < pi->rss_size; j++) 3451 for (j = 0; j < pi->rss_size; j++)
3452 pi->rss[j] = j % pi->nqsets; 3452 pi->rss[j] = ethtool_rxfh_indir_default(j, pi->nqsets);
3453 } 3453 }
3454 return 0; 3454 return 0;
3455} 3455}
diff --git a/drivers/net/ethernet/sfc/efx.c b/drivers/net/ethernet/sfc/efx.c
index 14e134d3b4d7..44a82c6c60a7 100644
--- a/drivers/net/ethernet/sfc/efx.c
+++ b/drivers/net/ethernet/sfc/efx.c
@@ -1336,7 +1336,8 @@ static int efx_probe_nic(struct efx_nic *efx)
1336 if (efx->n_channels > 1) 1336 if (efx->n_channels > 1)
1337 get_random_bytes(&efx->rx_hash_key, sizeof(efx->rx_hash_key)); 1337 get_random_bytes(&efx->rx_hash_key, sizeof(efx->rx_hash_key));
1338 for (i = 0; i < ARRAY_SIZE(efx->rx_indir_table); i++) 1338 for (i = 0; i < ARRAY_SIZE(efx->rx_indir_table); i++)
1339 efx->rx_indir_table[i] = i % efx->n_rx_channels; 1339 efx->rx_indir_table[i] =
1340 ethtool_rxfh_indir_default(i, efx->n_rx_channels);
1340 1341
1341 efx_set_channels(efx); 1342 efx_set_channels(efx);
1342 netif_set_real_num_tx_queues(efx->net_dev, efx->n_tx_channels); 1343 netif_set_real_num_tx_queues(efx->net_dev, efx->n_tx_channels);
diff --git a/drivers/net/vmxnet3/vmxnet3_drv.c b/drivers/net/vmxnet3/vmxnet3_drv.c
index 1c2ae11a9e35..de7fc345148a 100644
--- a/drivers/net/vmxnet3/vmxnet3_drv.c
+++ b/drivers/net/vmxnet3/vmxnet3_drv.c
@@ -2167,7 +2167,8 @@ vmxnet3_setup_driver_shared(struct vmxnet3_adapter *adapter)
2167 rssConf->indTableSize = VMXNET3_RSS_IND_TABLE_SIZE; 2167 rssConf->indTableSize = VMXNET3_RSS_IND_TABLE_SIZE;
2168 get_random_bytes(&rssConf->hashKey[0], rssConf->hashKeySize); 2168 get_random_bytes(&rssConf->hashKey[0], rssConf->hashKeySize);
2169 for (i = 0; i < rssConf->indTableSize; i++) 2169 for (i = 0; i < rssConf->indTableSize; i++)
2170 rssConf->indTable[i] = i % adapter->num_rx_queues; 2170 rssConf->indTable[i] = ethtool_rxfh_indir_default(
2171 i, adapter->num_rx_queues);
2171 2172
2172 devRead->rssConfDesc.confVer = 1; 2173 devRead->rssConfDesc.confVer = 1;
2173 devRead->rssConfDesc.confLen = sizeof(*rssConf); 2174 devRead->rssConfDesc.confLen = sizeof(*rssConf);
diff --git a/include/linux/ethtool.h b/include/linux/ethtool.h
index 3b9f09d55b5c..b38bf69310ee 100644
--- a/include/linux/ethtool.h
+++ b/include/linux/ethtool.h
@@ -543,10 +543,15 @@ struct compat_ethtool_rxnfc {
543/** 543/**
544 * struct ethtool_rxfh_indir - command to get or set RX flow hash indirection 544 * struct ethtool_rxfh_indir - command to get or set RX flow hash indirection
545 * @cmd: Specific command number - %ETHTOOL_GRXFHINDIR or %ETHTOOL_SRXFHINDIR 545 * @cmd: Specific command number - %ETHTOOL_GRXFHINDIR or %ETHTOOL_SRXFHINDIR
546 * @size: On entry, the array size of the user buffer, which may be zero 546 * @size: On entry, the array size of the user buffer, which may be zero.
547 * for %ETHTOOL_GRXFHINDIR. On return from %ETHTOOL_GRXFHINDIR, the 547 * On return from %ETHTOOL_GRXFHINDIR, the array size of the hardware
548 * array size of the hardware indirection table. 548 * indirection table.
549 * @ring_index: RX ring/queue index for each hash value 549 * @ring_index: RX ring/queue index for each hash value
550 *
551 * For %ETHTOOL_GRXFHINDIR, a @size of zero means that only the size
552 * should be returned. For %ETHTOOL_SRXFHINDIR, a @size of zero means
553 * the table should be reset to default values. This last feature
554 * is not supported by the original implementations.
550 */ 555 */
551struct ethtool_rxfh_indir { 556struct ethtool_rxfh_indir {
552 __u32 cmd; 557 __u32 cmd;
@@ -750,6 +755,18 @@ struct net_device;
750u32 ethtool_op_get_link(struct net_device *dev); 755u32 ethtool_op_get_link(struct net_device *dev);
751 756
752/** 757/**
758 * ethtool_rxfh_indir_default - get default value for RX flow hash indirection
759 * @index: Index in RX flow hash indirection table
760 * @n_rx_rings: Number of RX rings to use
761 *
762 * This function provides the default policy for RX flow hash indirection.
763 */
764static inline u32 ethtool_rxfh_indir_default(u32 index, u32 n_rx_rings)
765{
766 return index % n_rx_rings;
767}
768
769/**
753 * struct ethtool_ops - optional netdev operations 770 * struct ethtool_ops - optional netdev operations
754 * @get_settings: Get various device settings including Ethernet link 771 * @get_settings: Get various device settings including Ethernet link
755 * settings. The @cmd parameter is expected to have been cleared 772 * settings. The @cmd parameter is expected to have been cleared
diff --git a/net/core/ethtool.c b/net/core/ethtool.c
index 69f71b86b035..597732c989ca 100644
--- a/net/core/ethtool.c
+++ b/net/core/ethtool.c
@@ -581,31 +581,38 @@ static noinline_for_stack int ethtool_set_rxfh_indir(struct net_device *dev,
581 sizeof(user_size))) 581 sizeof(user_size)))
582 return -EFAULT; 582 return -EFAULT;
583 583
584 if (user_size != dev_size) 584 if (user_size != 0 && user_size != dev_size)
585 return -EINVAL; 585 return -EINVAL;
586 586
587 indir = kcalloc(dev_size, sizeof(indir[0]), GFP_USER); 587 indir = kcalloc(dev_size, sizeof(indir[0]), GFP_USER);
588 if (!indir) 588 if (!indir)
589 return -ENOMEM; 589 return -ENOMEM;
590 590
591 if (copy_from_user(indir,
592 useraddr +
593 offsetof(struct ethtool_rxfh_indir, ring_index[0]),
594 dev_size * sizeof(indir[0]))) {
595 ret = -EFAULT;
596 goto out;
597 }
598
599 /* Validate ring indices */
600 rx_rings.cmd = ETHTOOL_GRXRINGS; 591 rx_rings.cmd = ETHTOOL_GRXRINGS;
601 ret = dev->ethtool_ops->get_rxnfc(dev, &rx_rings, NULL); 592 ret = dev->ethtool_ops->get_rxnfc(dev, &rx_rings, NULL);
602 if (ret) 593 if (ret)
603 goto out; 594 goto out;
604 for (i = 0; i < dev_size; i++) { 595
605 if (indir[i] >= rx_rings.data) { 596 if (user_size == 0) {
606 ret = -EINVAL; 597 for (i = 0; i < dev_size; i++)
598 indir[i] = ethtool_rxfh_indir_default(i, rx_rings.data);
599 } else {
600 if (copy_from_user(indir,
601 useraddr +
602 offsetof(struct ethtool_rxfh_indir,
603 ring_index[0]),
604 dev_size * sizeof(indir[0]))) {
605 ret = -EFAULT;
607 goto out; 606 goto out;
608 } 607 }
608
609 /* Validate ring indices */
610 for (i = 0; i < dev_size; i++) {
611 if (indir[i] >= rx_rings.data) {
612 ret = -EINVAL;
613 goto out;
614 }
615 }
609 } 616 }
610 617
611 ret = dev->ethtool_ops->set_rxfh_indir(dev, indir); 618 ret = dev->ethtool_ops->set_rxfh_indir(dev, indir);