diff options
Diffstat (limited to 'net/core/ethtool.c')
-rw-r--r-- | net/core/ethtool.c | 53 |
1 files changed, 53 insertions, 0 deletions
diff --git a/net/core/ethtool.c b/net/core/ethtool.c index 404b761e82ce..0350586e9195 100644 --- a/net/core/ethtool.c +++ b/net/core/ethtool.c | |||
@@ -93,6 +93,20 @@ int ethtool_op_get_perm_addr(struct net_device *dev, struct ethtool_perm_addr *a | |||
93 | } | 93 | } |
94 | 94 | ||
95 | 95 | ||
96 | u32 ethtool_op_get_ufo(struct net_device *dev) | ||
97 | { | ||
98 | return (dev->features & NETIF_F_UFO) != 0; | ||
99 | } | ||
100 | |||
101 | int ethtool_op_set_ufo(struct net_device *dev, u32 data) | ||
102 | { | ||
103 | if (data) | ||
104 | dev->features |= NETIF_F_UFO; | ||
105 | else | ||
106 | dev->features &= ~NETIF_F_UFO; | ||
107 | return 0; | ||
108 | } | ||
109 | |||
96 | /* Handlers for each ethtool command */ | 110 | /* Handlers for each ethtool command */ |
97 | 111 | ||
98 | static int ethtool_get_settings(struct net_device *dev, void __user *useraddr) | 112 | static int ethtool_get_settings(struct net_device *dev, void __user *useraddr) |
@@ -483,6 +497,11 @@ static int __ethtool_set_sg(struct net_device *dev, u32 data) | |||
483 | return err; | 497 | return err; |
484 | } | 498 | } |
485 | 499 | ||
500 | if (!data && dev->ethtool_ops->set_ufo) { | ||
501 | err = dev->ethtool_ops->set_ufo(dev, 0); | ||
502 | if (err) | ||
503 | return err; | ||
504 | } | ||
486 | return dev->ethtool_ops->set_sg(dev, data); | 505 | return dev->ethtool_ops->set_sg(dev, data); |
487 | } | 506 | } |
488 | 507 | ||
@@ -569,6 +588,32 @@ static int ethtool_set_tso(struct net_device *dev, char __user *useraddr) | |||
569 | return dev->ethtool_ops->set_tso(dev, edata.data); | 588 | return dev->ethtool_ops->set_tso(dev, edata.data); |
570 | } | 589 | } |
571 | 590 | ||
591 | static int ethtool_get_ufo(struct net_device *dev, char __user *useraddr) | ||
592 | { | ||
593 | struct ethtool_value edata = { ETHTOOL_GTSO }; | ||
594 | |||
595 | if (!dev->ethtool_ops->get_ufo) | ||
596 | return -EOPNOTSUPP; | ||
597 | edata.data = dev->ethtool_ops->get_ufo(dev); | ||
598 | if (copy_to_user(useraddr, &edata, sizeof(edata))) | ||
599 | return -EFAULT; | ||
600 | return 0; | ||
601 | } | ||
602 | static int ethtool_set_ufo(struct net_device *dev, char __user *useraddr) | ||
603 | { | ||
604 | struct ethtool_value edata; | ||
605 | |||
606 | if (!dev->ethtool_ops->set_ufo) | ||
607 | return -EOPNOTSUPP; | ||
608 | if (copy_from_user(&edata, useraddr, sizeof(edata))) | ||
609 | return -EFAULT; | ||
610 | if (edata.data && !(dev->features & NETIF_F_SG)) | ||
611 | return -EINVAL; | ||
612 | if (edata.data && !(dev->features & NETIF_F_HW_CSUM)) | ||
613 | return -EINVAL; | ||
614 | return dev->ethtool_ops->set_ufo(dev, edata.data); | ||
615 | } | ||
616 | |||
572 | static int ethtool_self_test(struct net_device *dev, char __user *useraddr) | 617 | static int ethtool_self_test(struct net_device *dev, char __user *useraddr) |
573 | { | 618 | { |
574 | struct ethtool_test test; | 619 | struct ethtool_test test; |
@@ -854,6 +899,12 @@ int dev_ethtool(struct ifreq *ifr) | |||
854 | case ETHTOOL_GPERMADDR: | 899 | case ETHTOOL_GPERMADDR: |
855 | rc = ethtool_get_perm_addr(dev, useraddr); | 900 | rc = ethtool_get_perm_addr(dev, useraddr); |
856 | break; | 901 | break; |
902 | case ETHTOOL_GUFO: | ||
903 | rc = ethtool_get_ufo(dev, useraddr); | ||
904 | break; | ||
905 | case ETHTOOL_SUFO: | ||
906 | rc = ethtool_set_ufo(dev, useraddr); | ||
907 | break; | ||
857 | default: | 908 | default: |
858 | rc = -EOPNOTSUPP; | 909 | rc = -EOPNOTSUPP; |
859 | } | 910 | } |
@@ -882,3 +933,5 @@ EXPORT_SYMBOL(ethtool_op_set_sg); | |||
882 | EXPORT_SYMBOL(ethtool_op_set_tso); | 933 | EXPORT_SYMBOL(ethtool_op_set_tso); |
883 | EXPORT_SYMBOL(ethtool_op_set_tx_csum); | 934 | EXPORT_SYMBOL(ethtool_op_set_tx_csum); |
884 | EXPORT_SYMBOL(ethtool_op_set_tx_hw_csum); | 935 | EXPORT_SYMBOL(ethtool_op_set_tx_hw_csum); |
936 | EXPORT_SYMBOL(ethtool_op_set_ufo); | ||
937 | EXPORT_SYMBOL(ethtool_op_get_ufo); | ||