aboutsummaryrefslogtreecommitdiffstats
path: root/net/core
diff options
context:
space:
mode:
authorBen Hutchings <bhutchings@solarflare.com>2011-12-15 08:56:49 -0500
committerDavid S. Miller <davem@davemloft.net>2011-12-16 13:53:18 -0500
commit278bc4296bd64ffd1d3913b487dc8a520e423a7a (patch)
tree87781870cf9b96398a90fae6ebe1dae6d43d9ea4 /net/core
parent7850f63f1620512631445b901ae11cd149e7375c (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.c33
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);