aboutsummaryrefslogtreecommitdiffstats
path: root/net
diff options
context:
space:
mode:
authorHerbert Xu <herbert@gondor.apana.org.au>2008-12-16 02:44:31 -0500
committerDavid S. Miller <davem@davemloft.net>2008-12-16 02:44:31 -0500
commitb240a0e5644eb817c4a397098a40e1ad42a615bc (patch)
treeff2262ce70c4f7773c01e736186dbb4b40145841 /net
parentbf296b125b21b8d558ceb6ec30bb4eba2730cd6b (diff)
ethtool: Add GGRO and SGRO ops
This patch adds the ethtool ops to enable and disable GRO. It also makes GRO depend on RX checksum offload much the same as how TSO depends on SG support. Signed-off-by: Herbert Xu <herbert@gondor.apana.org.au> Signed-off-by: David S. Miller <davem@davemloft.net>
Diffstat (limited to 'net')
-rw-r--r--net/core/ethtool.c53
1 files changed, 51 insertions, 2 deletions
diff --git a/net/core/ethtool.c b/net/core/ethtool.c
index 14ada537f895..947710a36ced 100644
--- a/net/core/ethtool.c
+++ b/net/core/ethtool.c
@@ -528,6 +528,22 @@ static int ethtool_set_tx_csum(struct net_device *dev, char __user *useraddr)
528 return dev->ethtool_ops->set_tx_csum(dev, edata.data); 528 return dev->ethtool_ops->set_tx_csum(dev, edata.data);
529} 529}
530 530
531static int ethtool_set_rx_csum(struct net_device *dev, char __user *useraddr)
532{
533 struct ethtool_value edata;
534
535 if (!dev->ethtool_ops->set_rx_csum)
536 return -EOPNOTSUPP;
537
538 if (copy_from_user(&edata, useraddr, sizeof(edata)))
539 return -EFAULT;
540
541 if (!edata.data && dev->ethtool_ops->set_sg)
542 dev->features &= ~NETIF_F_GRO;
543
544 return dev->ethtool_ops->set_rx_csum(dev, edata.data);
545}
546
531static int ethtool_set_sg(struct net_device *dev, char __user *useraddr) 547static int ethtool_set_sg(struct net_device *dev, char __user *useraddr)
532{ 548{
533 struct ethtool_value edata; 549 struct ethtool_value edata;
@@ -599,6 +615,34 @@ static int ethtool_set_gso(struct net_device *dev, char __user *useraddr)
599 return 0; 615 return 0;
600} 616}
601 617
618static int ethtool_get_gro(struct net_device *dev, char __user *useraddr)
619{
620 struct ethtool_value edata = { ETHTOOL_GGRO };
621
622 edata.data = dev->features & NETIF_F_GRO;
623 if (copy_to_user(useraddr, &edata, sizeof(edata)))
624 return -EFAULT;
625 return 0;
626}
627
628static int ethtool_set_gro(struct net_device *dev, char __user *useraddr)
629{
630 struct ethtool_value edata;
631
632 if (copy_from_user(&edata, useraddr, sizeof(edata)))
633 return -EFAULT;
634
635 if (edata.data) {
636 if (!dev->ethtool_ops->get_rx_csum ||
637 !dev->ethtool_ops->get_rx_csum(dev))
638 return -EINVAL;
639 dev->features |= NETIF_F_GRO;
640 } else
641 dev->features &= ~NETIF_F_GRO;
642
643 return 0;
644}
645
602static int ethtool_self_test(struct net_device *dev, char __user *useraddr) 646static int ethtool_self_test(struct net_device *dev, char __user *useraddr)
603{ 647{
604 struct ethtool_test test; 648 struct ethtool_test test;
@@ -932,8 +976,7 @@ int dev_ethtool(struct net *net, struct ifreq *ifr)
932 dev->ethtool_ops->get_rx_csum); 976 dev->ethtool_ops->get_rx_csum);
933 break; 977 break;
934 case ETHTOOL_SRXCSUM: 978 case ETHTOOL_SRXCSUM:
935 rc = ethtool_set_value(dev, useraddr, 979 rc = ethtool_set_rx_csum(dev, useraddr);
936 dev->ethtool_ops->set_rx_csum);
937 break; 980 break;
938 case ETHTOOL_GTXCSUM: 981 case ETHTOOL_GTXCSUM:
939 rc = ethtool_get_value(dev, useraddr, ethcmd, 982 rc = ethtool_get_value(dev, useraddr, ethcmd,
@@ -1014,6 +1057,12 @@ int dev_ethtool(struct net *net, struct ifreq *ifr)
1014 case ETHTOOL_SRXFH: 1057 case ETHTOOL_SRXFH:
1015 rc = ethtool_set_rxhash(dev, useraddr); 1058 rc = ethtool_set_rxhash(dev, useraddr);
1016 break; 1059 break;
1060 case ETHTOOL_GGRO:
1061 rc = ethtool_get_gro(dev, useraddr);
1062 break;
1063 case ETHTOOL_SGRO:
1064 rc = ethtool_set_gro(dev, useraddr);
1065 break;
1017 default: 1066 default:
1018 rc = -EOPNOTSUPP; 1067 rc = -EOPNOTSUPP;
1019 } 1068 }