aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--include/linux/ethtool.h53
-rw-r--r--include/linux/netdevice.h16
-rw-r--r--net/8021q/vlan_dev.c6
-rw-r--r--net/core/dev.c12
-rw-r--r--net/core/ethtool.c418
5 files changed, 26 insertions, 479 deletions
diff --git a/include/linux/ethtool.h b/include/linux/ethtool.h
index de33de1e2052..20db5b275c3f 100644
--- a/include/linux/ethtool.h
+++ b/include/linux/ethtool.h
@@ -724,9 +724,6 @@ enum ethtool_sfeatures_retval_bits {
724 724
725#include <linux/rculist.h> 725#include <linux/rculist.h>
726 726
727/* needed by dev_disable_lro() */
728extern int __ethtool_set_flags(struct net_device *dev, u32 flags);
729
730extern int __ethtool_get_settings(struct net_device *dev, 727extern int __ethtool_get_settings(struct net_device *dev,
731 struct ethtool_cmd *cmd); 728 struct ethtool_cmd *cmd);
732 729
@@ -750,19 +747,6 @@ struct net_device;
750 747
751/* Some generic methods drivers may use in their ethtool_ops */ 748/* Some generic methods drivers may use in their ethtool_ops */
752u32 ethtool_op_get_link(struct net_device *dev); 749u32 ethtool_op_get_link(struct net_device *dev);
753u32 ethtool_op_get_tx_csum(struct net_device *dev);
754int ethtool_op_set_tx_csum(struct net_device *dev, u32 data);
755int ethtool_op_set_tx_hw_csum(struct net_device *dev, u32 data);
756int ethtool_op_set_tx_ipv6_csum(struct net_device *dev, u32 data);
757u32 ethtool_op_get_sg(struct net_device *dev);
758int ethtool_op_set_sg(struct net_device *dev, u32 data);
759u32 ethtool_op_get_tso(struct net_device *dev);
760int ethtool_op_set_tso(struct net_device *dev, u32 data);
761u32 ethtool_op_get_ufo(struct net_device *dev);
762int ethtool_op_set_ufo(struct net_device *dev, u32 data);
763u32 ethtool_op_get_flags(struct net_device *dev);
764int ethtool_op_set_flags(struct net_device *dev, u32 data, u32 supported);
765bool ethtool_invalid_flags(struct net_device *dev, u32 data, u32 supported);
766 750
767/** 751/**
768 * struct ethtool_ops - optional netdev operations 752 * struct ethtool_ops - optional netdev operations
@@ -807,22 +791,6 @@ bool ethtool_invalid_flags(struct net_device *dev, u32 data, u32 supported);
807 * @get_pauseparam: Report pause parameters 791 * @get_pauseparam: Report pause parameters
808 * @set_pauseparam: Set pause parameters. Returns a negative error code 792 * @set_pauseparam: Set pause parameters. Returns a negative error code
809 * or zero. 793 * or zero.
810 * @get_rx_csum: Deprecated in favour of the netdev feature %NETIF_F_RXCSUM.
811 * Report whether receive checksums are turned on or off.
812 * @set_rx_csum: Deprecated in favour of generic netdev features. Turn
813 * receive checksum on or off. Returns a negative error code or zero.
814 * @get_tx_csum: Deprecated as redundant. Report whether transmit checksums
815 * are turned on or off.
816 * @set_tx_csum: Deprecated in favour of generic netdev features. Turn
817 * transmit checksums on or off. Returns a negative error code or zero.
818 * @get_sg: Deprecated as redundant. Report whether scatter-gather is
819 * enabled.
820 * @set_sg: Deprecated in favour of generic netdev features. Turn
821 * scatter-gather on or off. Returns a negative error code or zero.
822 * @get_tso: Deprecated as redundant. Report whether TCP segmentation
823 * offload is enabled.
824 * @set_tso: Deprecated in favour of generic netdev features. Turn TCP
825 * segmentation offload on or off. Returns a negative error code or zero.
826 * @self_test: Run specified self-tests 794 * @self_test: Run specified self-tests
827 * @get_strings: Return a set of strings that describe the requested objects 795 * @get_strings: Return a set of strings that describe the requested objects
828 * @set_phys_id: Identify the physical devices, e.g. by flashing an LED 796 * @set_phys_id: Identify the physical devices, e.g. by flashing an LED
@@ -844,15 +812,6 @@ bool ethtool_invalid_flags(struct net_device *dev, u32 data, u32 supported);
844 * negative error code or zero. 812 * negative error code or zero.
845 * @complete: Function to be called after any other operation except 813 * @complete: Function to be called after any other operation except
846 * @begin. Will be called even if the other operation failed. 814 * @begin. Will be called even if the other operation failed.
847 * @get_ufo: Deprecated as redundant. Report whether UDP fragmentation
848 * offload is enabled.
849 * @set_ufo: Deprecated in favour of generic netdev features. Turn UDP
850 * fragmentation offload on or off. Returns a negative error code or zero.
851 * @get_flags: Deprecated as redundant. Report features included in
852 * &enum ethtool_flags that are enabled.
853 * @set_flags: Deprecated in favour of generic netdev features. Turn
854 * features included in &enum ethtool_flags on or off. Returns a
855 * negative error code or zero.
856 * @get_priv_flags: Report driver-specific feature flags. 815 * @get_priv_flags: Report driver-specific feature flags.
857 * @set_priv_flags: Set driver-specific feature flags. Returns a negative 816 * @set_priv_flags: Set driver-specific feature flags. Returns a negative
858 * error code or zero. 817 * error code or zero.
@@ -917,14 +876,6 @@ struct ethtool_ops {
917 struct ethtool_pauseparam*); 876 struct ethtool_pauseparam*);
918 int (*set_pauseparam)(struct net_device *, 877 int (*set_pauseparam)(struct net_device *,
919 struct ethtool_pauseparam*); 878 struct ethtool_pauseparam*);
920 u32 (*get_rx_csum)(struct net_device *);
921 int (*set_rx_csum)(struct net_device *, u32);
922 u32 (*get_tx_csum)(struct net_device *);
923 int (*set_tx_csum)(struct net_device *, u32);
924 u32 (*get_sg)(struct net_device *);
925 int (*set_sg)(struct net_device *, u32);
926 u32 (*get_tso)(struct net_device *);
927 int (*set_tso)(struct net_device *, u32);
928 void (*self_test)(struct net_device *, struct ethtool_test *, u64 *); 879 void (*self_test)(struct net_device *, struct ethtool_test *, u64 *);
929 void (*get_strings)(struct net_device *, u32 stringset, u8 *); 880 void (*get_strings)(struct net_device *, u32 stringset, u8 *);
930 int (*set_phys_id)(struct net_device *, enum ethtool_phys_id_state); 881 int (*set_phys_id)(struct net_device *, enum ethtool_phys_id_state);
@@ -932,10 +883,6 @@ struct ethtool_ops {
932 struct ethtool_stats *, u64 *); 883 struct ethtool_stats *, u64 *);
933 int (*begin)(struct net_device *); 884 int (*begin)(struct net_device *);
934 void (*complete)(struct net_device *); 885 void (*complete)(struct net_device *);
935 u32 (*get_ufo)(struct net_device *);
936 int (*set_ufo)(struct net_device *, u32);
937 u32 (*get_flags)(struct net_device *);
938 int (*set_flags)(struct net_device *, u32);
939 u32 (*get_priv_flags)(struct net_device *); 886 u32 (*get_priv_flags)(struct net_device *);
940 int (*set_priv_flags)(struct net_device *, u32); 887 int (*set_priv_flags)(struct net_device *, u32);
941 int (*get_sset_count)(struct net_device *, int); 888 int (*get_sset_count)(struct net_device *, int);
diff --git a/include/linux/netdevice.h b/include/linux/netdevice.h
index cbeb5867cff7..e34717a792b4 100644
--- a/include/linux/netdevice.h
+++ b/include/linux/netdevice.h
@@ -2592,22 +2592,6 @@ static inline int netif_is_bond_slave(struct net_device *dev)
2592 2592
2593extern struct pernet_operations __net_initdata loopback_net_ops; 2593extern struct pernet_operations __net_initdata loopback_net_ops;
2594 2594
2595static inline u32 dev_ethtool_get_rx_csum(struct net_device *dev)
2596{
2597 if (dev->features & NETIF_F_RXCSUM)
2598 return 1;
2599 if (!dev->ethtool_ops || !dev->ethtool_ops->get_rx_csum)
2600 return 0;
2601 return dev->ethtool_ops->get_rx_csum(dev);
2602}
2603
2604static inline u32 dev_ethtool_get_flags(struct net_device *dev)
2605{
2606 if (!dev->ethtool_ops || !dev->ethtool_ops->get_flags)
2607 return 0;
2608 return dev->ethtool_ops->get_flags(dev);
2609}
2610
2611/* Logging, debugging and troubleshooting/diagnostic helpers. */ 2595/* Logging, debugging and troubleshooting/diagnostic helpers. */
2612 2596
2613/* netdev_printk helpers, similar to dev_printk */ 2597/* netdev_printk helpers, similar to dev_printk */
diff --git a/net/8021q/vlan_dev.c b/net/8021q/vlan_dev.c
index bc2528624583..6a4e0cb897b7 100644
--- a/net/8021q/vlan_dev.c
+++ b/net/8021q/vlan_dev.c
@@ -596,13 +596,11 @@ static u32 vlan_dev_fix_features(struct net_device *dev, u32 features)
596 struct net_device *real_dev = vlan_dev_info(dev)->real_dev; 596 struct net_device *real_dev = vlan_dev_info(dev)->real_dev;
597 u32 old_features = features; 597 u32 old_features = features;
598 598
599 features &= real_dev->features;
600 features &= real_dev->vlan_features; 599 features &= real_dev->vlan_features;
600 features |= NETIF_F_RXCSUM;
601 features &= real_dev->features;
601 602
602 features |= old_features & NETIF_F_SOFT_FEATURES; 603 features |= old_features & NETIF_F_SOFT_FEATURES;
603
604 if (dev_ethtool_get_rx_csum(real_dev))
605 features |= NETIF_F_RXCSUM;
606 features |= NETIF_F_LLTX; 604 features |= NETIF_F_LLTX;
607 605
608 return features; 606 return features;
diff --git a/net/core/dev.c b/net/core/dev.c
index 51f89cd0a3f4..185e246d61fd 100644
--- a/net/core/dev.c
+++ b/net/core/dev.c
@@ -1321,8 +1321,6 @@ EXPORT_SYMBOL(dev_close);
1321 */ 1321 */
1322void dev_disable_lro(struct net_device *dev) 1322void dev_disable_lro(struct net_device *dev)
1323{ 1323{
1324 u32 flags;
1325
1326 /* 1324 /*
1327 * If we're trying to disable lro on a vlan device 1325 * If we're trying to disable lro on a vlan device
1328 * use the underlying physical device instead 1326 * use the underlying physical device instead
@@ -1330,15 +1328,9 @@ void dev_disable_lro(struct net_device *dev)
1330 if (is_vlan_dev(dev)) 1328 if (is_vlan_dev(dev))
1331 dev = vlan_dev_real_dev(dev); 1329 dev = vlan_dev_real_dev(dev);
1332 1330
1333 if (dev->ethtool_ops && dev->ethtool_ops->get_flags) 1331 dev->wanted_features &= ~NETIF_F_LRO;
1334 flags = dev->ethtool_ops->get_flags(dev); 1332 netdev_update_features(dev);
1335 else
1336 flags = ethtool_op_get_flags(dev);
1337
1338 if (!(flags & ETH_FLAG_LRO))
1339 return;
1340 1333
1341 __ethtool_set_flags(dev, flags & ~ETH_FLAG_LRO);
1342 if (unlikely(dev->features & NETIF_F_LRO)) 1334 if (unlikely(dev->features & NETIF_F_LRO))
1343 netdev_WARN(dev, "failed to disable LRO!\n"); 1335 netdev_WARN(dev, "failed to disable LRO!\n");
1344} 1336}
diff --git a/net/core/ethtool.c b/net/core/ethtool.c
index f44481707124..db8a77bb557b 100644
--- a/net/core/ethtool.c
+++ b/net/core/ethtool.c
@@ -36,236 +36,10 @@ u32 ethtool_op_get_link(struct net_device *dev)
36} 36}
37EXPORT_SYMBOL(ethtool_op_get_link); 37EXPORT_SYMBOL(ethtool_op_get_link);
38 38
39u32 ethtool_op_get_tx_csum(struct net_device *dev)
40{
41 return (dev->features & NETIF_F_ALL_CSUM) != 0;
42}
43EXPORT_SYMBOL(ethtool_op_get_tx_csum);
44
45int ethtool_op_set_tx_csum(struct net_device *dev, u32 data)
46{
47 if (data)
48 dev->features |= NETIF_F_IP_CSUM;
49 else
50 dev->features &= ~NETIF_F_IP_CSUM;
51
52 return 0;
53}
54EXPORT_SYMBOL(ethtool_op_set_tx_csum);
55
56int ethtool_op_set_tx_hw_csum(struct net_device *dev, u32 data)
57{
58 if (data)
59 dev->features |= NETIF_F_HW_CSUM;
60 else
61 dev->features &= ~NETIF_F_HW_CSUM;
62
63 return 0;
64}
65EXPORT_SYMBOL(ethtool_op_set_tx_hw_csum);
66
67int ethtool_op_set_tx_ipv6_csum(struct net_device *dev, u32 data)
68{
69 if (data)
70 dev->features |= NETIF_F_IP_CSUM | NETIF_F_IPV6_CSUM;
71 else
72 dev->features &= ~(NETIF_F_IP_CSUM | NETIF_F_IPV6_CSUM);
73
74 return 0;
75}
76EXPORT_SYMBOL(ethtool_op_set_tx_ipv6_csum);
77
78u32 ethtool_op_get_sg(struct net_device *dev)
79{
80 return (dev->features & NETIF_F_SG) != 0;
81}
82EXPORT_SYMBOL(ethtool_op_get_sg);
83
84int ethtool_op_set_sg(struct net_device *dev, u32 data)
85{
86 if (data)
87 dev->features |= NETIF_F_SG;
88 else
89 dev->features &= ~NETIF_F_SG;
90
91 return 0;
92}
93EXPORT_SYMBOL(ethtool_op_set_sg);
94
95u32 ethtool_op_get_tso(struct net_device *dev)
96{
97 return (dev->features & NETIF_F_TSO) != 0;
98}
99EXPORT_SYMBOL(ethtool_op_get_tso);
100
101int ethtool_op_set_tso(struct net_device *dev, u32 data)
102{
103 if (data)
104 dev->features |= NETIF_F_TSO;
105 else
106 dev->features &= ~NETIF_F_TSO;
107
108 return 0;
109}
110EXPORT_SYMBOL(ethtool_op_set_tso);
111
112u32 ethtool_op_get_ufo(struct net_device *dev)
113{
114 return (dev->features & NETIF_F_UFO) != 0;
115}
116EXPORT_SYMBOL(ethtool_op_get_ufo);
117
118int ethtool_op_set_ufo(struct net_device *dev, u32 data)
119{
120 if (data)
121 dev->features |= NETIF_F_UFO;
122 else
123 dev->features &= ~NETIF_F_UFO;
124 return 0;
125}
126EXPORT_SYMBOL(ethtool_op_set_ufo);
127
128/* the following list of flags are the same as their associated
129 * NETIF_F_xxx values in include/linux/netdevice.h
130 */
131static const u32 flags_dup_features =
132 (ETH_FLAG_LRO | ETH_FLAG_RXVLAN | ETH_FLAG_TXVLAN | ETH_FLAG_NTUPLE |
133 ETH_FLAG_RXHASH);
134
135u32 ethtool_op_get_flags(struct net_device *dev)
136{
137 /* in the future, this function will probably contain additional
138 * handling for flags which are not so easily handled
139 * by a simple masking operation
140 */
141
142 return dev->features & flags_dup_features;
143}
144EXPORT_SYMBOL(ethtool_op_get_flags);
145
146/* Check if device can enable (or disable) particular feature coded in "data"
147 * argument. Flags "supported" describe features that can be toggled by device.
148 * If feature can not be toggled, it state (enabled or disabled) must match
149 * hardcoded device features state, otherwise flags are marked as invalid.
150 */
151bool ethtool_invalid_flags(struct net_device *dev, u32 data, u32 supported)
152{
153 u32 features = dev->features & flags_dup_features;
154 /* "data" can contain only flags_dup_features bits,
155 * see __ethtool_set_flags */
156
157 return (features & ~supported) != (data & ~supported);
158}
159EXPORT_SYMBOL(ethtool_invalid_flags);
160
161int ethtool_op_set_flags(struct net_device *dev, u32 data, u32 supported)
162{
163 if (ethtool_invalid_flags(dev, data, supported))
164 return -EINVAL;
165
166 dev->features = ((dev->features & ~flags_dup_features) |
167 (data & flags_dup_features));
168 return 0;
169}
170EXPORT_SYMBOL(ethtool_op_set_flags);
171
172/* Handlers for each ethtool command */ 39/* Handlers for each ethtool command */
173 40
174#define ETHTOOL_DEV_FEATURE_WORDS 1 41#define ETHTOOL_DEV_FEATURE_WORDS 1
175 42
176static void ethtool_get_features_compat(struct net_device *dev,
177 struct ethtool_get_features_block *features)
178{
179 if (!dev->ethtool_ops)
180 return;
181
182 /* getting RX checksum */
183 if (dev->ethtool_ops->get_rx_csum)
184 if (dev->ethtool_ops->get_rx_csum(dev))
185 features[0].active |= NETIF_F_RXCSUM;
186
187 /* mark legacy-changeable features */
188 if (dev->ethtool_ops->set_sg)
189 features[0].available |= NETIF_F_SG;
190 if (dev->ethtool_ops->set_tx_csum)
191 features[0].available |= NETIF_F_ALL_CSUM;
192 if (dev->ethtool_ops->set_tso)
193 features[0].available |= NETIF_F_ALL_TSO;
194 if (dev->ethtool_ops->set_rx_csum)
195 features[0].available |= NETIF_F_RXCSUM;
196 if (dev->ethtool_ops->set_flags)
197 features[0].available |= flags_dup_features;
198}
199
200static int ethtool_set_feature_compat(struct net_device *dev,
201 int (*legacy_set)(struct net_device *, u32),
202 struct ethtool_set_features_block *features, u32 mask)
203{
204 u32 do_set;
205
206 if (!legacy_set)
207 return 0;
208
209 if (!(features[0].valid & mask))
210 return 0;
211
212 features[0].valid &= ~mask;
213
214 do_set = !!(features[0].requested & mask);
215
216 if (legacy_set(dev, do_set) < 0)
217 netdev_info(dev,
218 "Legacy feature change (%s) failed for 0x%08x\n",
219 do_set ? "set" : "clear", mask);
220
221 return 1;
222}
223
224static int ethtool_set_flags_compat(struct net_device *dev,
225 int (*legacy_set)(struct net_device *, u32),
226 struct ethtool_set_features_block *features, u32 mask)
227{
228 u32 value;
229
230 if (!legacy_set)
231 return 0;
232
233 if (!(features[0].valid & mask))
234 return 0;
235
236 value = dev->features & ~features[0].valid;
237 value |= features[0].requested;
238
239 features[0].valid &= ~mask;
240
241 if (legacy_set(dev, value & mask) < 0)
242 netdev_info(dev, "Legacy flags change failed\n");
243
244 return 1;
245}
246
247static int ethtool_set_features_compat(struct net_device *dev,
248 struct ethtool_set_features_block *features)
249{
250 int compat;
251
252 if (!dev->ethtool_ops)
253 return 0;
254
255 compat = ethtool_set_feature_compat(dev, dev->ethtool_ops->set_sg,
256 features, NETIF_F_SG);
257 compat |= ethtool_set_feature_compat(dev, dev->ethtool_ops->set_tx_csum,
258 features, NETIF_F_ALL_CSUM);
259 compat |= ethtool_set_feature_compat(dev, dev->ethtool_ops->set_tso,
260 features, NETIF_F_ALL_TSO);
261 compat |= ethtool_set_feature_compat(dev, dev->ethtool_ops->set_rx_csum,
262 features, NETIF_F_RXCSUM);
263 compat |= ethtool_set_flags_compat(dev, dev->ethtool_ops->set_flags,
264 features, flags_dup_features);
265
266 return compat;
267}
268
269static int ethtool_get_features(struct net_device *dev, void __user *useraddr) 43static int ethtool_get_features(struct net_device *dev, void __user *useraddr)
270{ 44{
271 struct ethtool_gfeatures cmd = { 45 struct ethtool_gfeatures cmd = {
@@ -283,8 +57,6 @@ static int ethtool_get_features(struct net_device *dev, void __user *useraddr)
283 u32 __user *sizeaddr; 57 u32 __user *sizeaddr;
284 u32 copy_size; 58 u32 copy_size;
285 59
286 ethtool_get_features_compat(dev, features);
287
288 sizeaddr = useraddr + offsetof(struct ethtool_gfeatures, size); 60 sizeaddr = useraddr + offsetof(struct ethtool_gfeatures, size);
289 if (get_user(copy_size, sizeaddr)) 61 if (get_user(copy_size, sizeaddr))
290 return -EFAULT; 62 return -EFAULT;
@@ -320,9 +92,6 @@ static int ethtool_set_features(struct net_device *dev, void __user *useraddr)
320 if (features[0].valid & ~NETIF_F_ETHTOOL_BITS) 92 if (features[0].valid & ~NETIF_F_ETHTOOL_BITS)
321 return -EINVAL; 93 return -EINVAL;
322 94
323 if (ethtool_set_features_compat(dev, features))
324 ret |= ETHTOOL_F_COMPAT;
325
326 if (features[0].valid & ~dev->hw_features) { 95 if (features[0].valid & ~dev->hw_features) {
327 features[0].valid &= dev->hw_features; 96 features[0].valid &= dev->hw_features;
328 ret |= ETHTOOL_F_UNSUPPORTED; 97 ret |= ETHTOOL_F_UNSUPPORTED;
@@ -433,34 +202,6 @@ static u32 ethtool_get_feature_mask(u32 eth_cmd)
433 } 202 }
434} 203}
435 204
436static void *__ethtool_get_one_feature_actor(struct net_device *dev, u32 ethcmd)
437{
438 const struct ethtool_ops *ops = dev->ethtool_ops;
439
440 if (!ops)
441 return NULL;
442
443 switch (ethcmd) {
444 case ETHTOOL_GTXCSUM:
445 return ops->get_tx_csum;
446 case ETHTOOL_GRXCSUM:
447 return ops->get_rx_csum;
448 case ETHTOOL_SSG:
449 return ops->get_sg;
450 case ETHTOOL_STSO:
451 return ops->get_tso;
452 case ETHTOOL_SUFO:
453 return ops->get_ufo;
454 default:
455 return NULL;
456 }
457}
458
459static u32 __ethtool_get_rx_csum_oldbug(struct net_device *dev)
460{
461 return !!(dev->features & NETIF_F_ALL_CSUM);
462}
463
464static int ethtool_get_one_feature(struct net_device *dev, 205static int ethtool_get_one_feature(struct net_device *dev,
465 char __user *useraddr, u32 ethcmd) 206 char __user *useraddr, u32 ethcmd)
466{ 207{
@@ -470,31 +211,11 @@ static int ethtool_get_one_feature(struct net_device *dev,
470 .data = !!(dev->features & mask), 211 .data = !!(dev->features & mask),
471 }; 212 };
472 213
473 /* compatibility with discrete get_ ops */
474 if (!(dev->hw_features & mask)) {
475 u32 (*actor)(struct net_device *);
476
477 actor = __ethtool_get_one_feature_actor(dev, ethcmd);
478
479 /* bug compatibility with old get_rx_csum */
480 if (ethcmd == ETHTOOL_GRXCSUM && !actor)
481 actor = __ethtool_get_rx_csum_oldbug;
482
483 if (actor)
484 edata.data = actor(dev);
485 }
486
487 if (copy_to_user(useraddr, &edata, sizeof(edata))) 214 if (copy_to_user(useraddr, &edata, sizeof(edata)))
488 return -EFAULT; 215 return -EFAULT;
489 return 0; 216 return 0;
490} 217}
491 218
492static int __ethtool_set_tx_csum(struct net_device *dev, u32 data);
493static int __ethtool_set_rx_csum(struct net_device *dev, u32 data);
494static int __ethtool_set_sg(struct net_device *dev, u32 data);
495static int __ethtool_set_tso(struct net_device *dev, u32 data);
496static int __ethtool_set_ufo(struct net_device *dev, u32 data);
497
498static int ethtool_set_one_feature(struct net_device *dev, 219static int ethtool_set_one_feature(struct net_device *dev,
499 void __user *useraddr, u32 ethcmd) 220 void __user *useraddr, u32 ethcmd)
500{ 221{
@@ -506,56 +227,38 @@ static int ethtool_set_one_feature(struct net_device *dev,
506 227
507 mask = ethtool_get_feature_mask(ethcmd); 228 mask = ethtool_get_feature_mask(ethcmd);
508 mask &= dev->hw_features; 229 mask &= dev->hw_features;
509 if (mask) { 230 if (!mask)
510 if (edata.data) 231 return -EOPNOTSUPP;
511 dev->wanted_features |= mask;
512 else
513 dev->wanted_features &= ~mask;
514 232
515 __netdev_update_features(dev); 233 if (edata.data)
516 return 0; 234 dev->wanted_features |= mask;
517 } 235 else
236 dev->wanted_features &= ~mask;
518 237
519 /* Driver is not converted to ndo_fix_features or does not 238 __netdev_update_features(dev);
520 * support changing this offload. In the latter case it won't
521 * have corresponding ethtool_ops field set.
522 *
523 * Following part is to be removed after all drivers advertise
524 * their changeable features in netdev->hw_features and stop
525 * using discrete offload setting ops.
526 */
527 239
528 switch (ethcmd) { 240 return 0;
529 case ETHTOOL_STXCSUM: 241}
530 return __ethtool_set_tx_csum(dev, edata.data); 242
531 case ETHTOOL_SRXCSUM: 243/* the following list of flags are the same as their associated
532 return __ethtool_set_rx_csum(dev, edata.data); 244 * NETIF_F_xxx values in include/linux/netdevice.h
533 case ETHTOOL_SSG: 245 */
534 return __ethtool_set_sg(dev, edata.data); 246static const u32 flags_dup_features =
535 case ETHTOOL_STSO: 247 (ETH_FLAG_LRO | ETH_FLAG_RXVLAN | ETH_FLAG_TXVLAN | ETH_FLAG_NTUPLE |
536 return __ethtool_set_tso(dev, edata.data); 248 ETH_FLAG_RXHASH);
537 case ETHTOOL_SUFO: 249
538 return __ethtool_set_ufo(dev, edata.data); 250static u32 __ethtool_get_flags(struct net_device *dev)
539 default: 251{
540 return -EOPNOTSUPP; 252 return dev->features & flags_dup_features;
541 }
542} 253}
543 254
544int __ethtool_set_flags(struct net_device *dev, u32 data) 255static int __ethtool_set_flags(struct net_device *dev, u32 data)
545{ 256{
546 u32 changed; 257 u32 changed;
547 258
548 if (data & ~flags_dup_features) 259 if (data & ~flags_dup_features)
549 return -EINVAL; 260 return -EINVAL;
550 261
551 /* legacy set_flags() op */
552 if (dev->ethtool_ops->set_flags) {
553 if (unlikely(dev->hw_features & flags_dup_features))
554 netdev_warn(dev,
555 "driver BUG: mixed hw_features and set_flags()\n");
556 return dev->ethtool_ops->set_flags(dev, data);
557 }
558
559 /* allow changing only bits set in hw_features */ 262 /* allow changing only bits set in hw_features */
560 changed = (data ^ dev->features) & flags_dup_features; 263 changed = (data ^ dev->features) & flags_dup_features;
561 if (changed & ~dev->hw_features) 264 if (changed & ~dev->hw_features)
@@ -1231,81 +934,6 @@ static int ethtool_set_pauseparam(struct net_device *dev, void __user *useraddr)
1231 return dev->ethtool_ops->set_pauseparam(dev, &pauseparam); 934 return dev->ethtool_ops->set_pauseparam(dev, &pauseparam);
1232} 935}
1233 936
1234static int __ethtool_set_sg(struct net_device *dev, u32 data)
1235{
1236 int err;
1237
1238 if (!dev->ethtool_ops->set_sg)
1239 return -EOPNOTSUPP;
1240
1241 if (data && !(dev->features & NETIF_F_ALL_CSUM))
1242 return -EINVAL;
1243
1244 if (!data && dev->ethtool_ops->set_tso) {
1245 err = dev->ethtool_ops->set_tso(dev, 0);
1246 if (err)
1247 return err;
1248 }
1249
1250 if (!data && dev->ethtool_ops->set_ufo) {
1251 err = dev->ethtool_ops->set_ufo(dev, 0);
1252 if (err)
1253 return err;
1254 }
1255 return dev->ethtool_ops->set_sg(dev, data);
1256}
1257
1258static int __ethtool_set_tx_csum(struct net_device *dev, u32 data)
1259{
1260 int err;
1261
1262 if (!dev->ethtool_ops->set_tx_csum)
1263 return -EOPNOTSUPP;
1264
1265 if (!data && dev->ethtool_ops->set_sg) {
1266 err = __ethtool_set_sg(dev, 0);
1267 if (err)
1268 return err;
1269 }
1270
1271 return dev->ethtool_ops->set_tx_csum(dev, data);
1272}
1273
1274static int __ethtool_set_rx_csum(struct net_device *dev, u32 data)
1275{
1276 if (!dev->ethtool_ops->set_rx_csum)
1277 return -EOPNOTSUPP;
1278
1279 if (!data)
1280 dev->features &= ~NETIF_F_GRO;
1281
1282 return dev->ethtool_ops->set_rx_csum(dev, data);
1283}
1284
1285static int __ethtool_set_tso(struct net_device *dev, u32 data)
1286{
1287 if (!dev->ethtool_ops->set_tso)
1288 return -EOPNOTSUPP;
1289
1290 if (data && !(dev->features & NETIF_F_SG))
1291 return -EINVAL;
1292
1293 return dev->ethtool_ops->set_tso(dev, data);
1294}
1295
1296static int __ethtool_set_ufo(struct net_device *dev, u32 data)
1297{
1298 if (!dev->ethtool_ops->set_ufo)
1299 return -EOPNOTSUPP;
1300 if (data && !(dev->features & NETIF_F_SG))
1301 return -EINVAL;
1302 if (data && !((dev->features & NETIF_F_GEN_CSUM) ||
1303 (dev->features & (NETIF_F_IP_CSUM|NETIF_F_IPV6_CSUM))
1304 == (NETIF_F_IP_CSUM|NETIF_F_IPV6_CSUM)))
1305 return -EINVAL;
1306 return dev->ethtool_ops->set_ufo(dev, data);
1307}
1308
1309static int ethtool_self_test(struct net_device *dev, char __user *useraddr) 937static int ethtool_self_test(struct net_device *dev, char __user *useraddr)
1310{ 938{
1311 struct ethtool_test test; 939 struct ethtool_test test;
@@ -1771,9 +1399,7 @@ int dev_ethtool(struct net *net, struct ifreq *ifr)
1771 break; 1399 break;
1772 case ETHTOOL_GFLAGS: 1400 case ETHTOOL_GFLAGS:
1773 rc = ethtool_get_value(dev, useraddr, ethcmd, 1401 rc = ethtool_get_value(dev, useraddr, ethcmd,
1774 (dev->ethtool_ops->get_flags ? 1402 __ethtool_get_flags);
1775 dev->ethtool_ops->get_flags :
1776 ethtool_op_get_flags));
1777 break; 1403 break;
1778 case ETHTOOL_SFLAGS: 1404 case ETHTOOL_SFLAGS:
1779 rc = ethtool_set_value(dev, useraddr, __ethtool_set_flags); 1405 rc = ethtool_set_value(dev, useraddr, __ethtool_set_flags);