aboutsummaryrefslogtreecommitdiffstats
path: root/net/core/ethtool.c
diff options
context:
space:
mode:
Diffstat (limited to 'net/core/ethtool.c')
-rw-r--r--net/core/ethtool.c53
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
96u32 ethtool_op_get_ufo(struct net_device *dev)
97{
98 return (dev->features & NETIF_F_UFO) != 0;
99}
100
101int 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
98static int ethtool_get_settings(struct net_device *dev, void __user *useraddr) 112static 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
591static 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}
602static 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
572static int ethtool_self_test(struct net_device *dev, char __user *useraddr) 617static 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);
882EXPORT_SYMBOL(ethtool_op_set_tso); 933EXPORT_SYMBOL(ethtool_op_set_tso);
883EXPORT_SYMBOL(ethtool_op_set_tx_csum); 934EXPORT_SYMBOL(ethtool_op_set_tx_csum);
884EXPORT_SYMBOL(ethtool_op_set_tx_hw_csum); 935EXPORT_SYMBOL(ethtool_op_set_tx_hw_csum);
936EXPORT_SYMBOL(ethtool_op_set_ufo);
937EXPORT_SYMBOL(ethtool_op_get_ufo);