diff options
-rw-r--r-- | drivers/net/ethernet/broadcom/bnx2x/bnx2x_cmn.c | 3 | ||||
-rw-r--r-- | drivers/net/ethernet/chelsio/cxgb4/cxgb4_main.c | 2 | ||||
-rw-r--r-- | drivers/net/ethernet/sfc/efx.c | 3 | ||||
-rw-r--r-- | drivers/net/vmxnet3/vmxnet3_drv.c | 3 | ||||
-rw-r--r-- | include/linux/ethtool.h | 23 | ||||
-rw-r--r-- | net/core/ethtool.c | 33 |
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 | */ |
551 | struct ethtool_rxfh_indir { | 556 | struct ethtool_rxfh_indir { |
552 | __u32 cmd; | 557 | __u32 cmd; |
@@ -750,6 +755,18 @@ struct net_device; | |||
750 | u32 ethtool_op_get_link(struct net_device *dev); | 755 | u32 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 | */ | ||
764 | static 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); |