aboutsummaryrefslogtreecommitdiffstats
path: root/net/core
diff options
context:
space:
mode:
Diffstat (limited to 'net/core')
-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 }