diff options
author | Ben Hutchings <bhutchings@solarflare.com> | 2011-12-15 08:56:49 -0500 |
---|---|---|
committer | David S. Miller <davem@davemloft.net> | 2011-12-16 13:53:18 -0500 |
commit | 278bc4296bd64ffd1d3913b487dc8a520e423a7a (patch) | |
tree | 87781870cf9b96398a90fae6ebe1dae6d43d9ea4 /net/core | |
parent | 7850f63f1620512631445b901ae11cd149e7375c (diff) |
ethtool: Define and apply a default policy for RX flow hash indirection
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>
Diffstat (limited to 'net/core')
-rw-r--r-- | net/core/ethtool.c | 33 |
1 files changed, 20 insertions, 13 deletions
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); |