diff options
-rw-r--r-- | include/linux/ethtool.h | 53 | ||||
-rw-r--r-- | include/linux/netdevice.h | 16 | ||||
-rw-r--r-- | net/8021q/vlan_dev.c | 6 | ||||
-rw-r--r-- | net/core/dev.c | 12 | ||||
-rw-r--r-- | net/core/ethtool.c | 418 |
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() */ | ||
728 | extern int __ethtool_set_flags(struct net_device *dev, u32 flags); | ||
729 | |||
730 | extern int __ethtool_get_settings(struct net_device *dev, | 727 | extern 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 */ |
752 | u32 ethtool_op_get_link(struct net_device *dev); | 749 | u32 ethtool_op_get_link(struct net_device *dev); |
753 | u32 ethtool_op_get_tx_csum(struct net_device *dev); | ||
754 | int ethtool_op_set_tx_csum(struct net_device *dev, u32 data); | ||
755 | int ethtool_op_set_tx_hw_csum(struct net_device *dev, u32 data); | ||
756 | int ethtool_op_set_tx_ipv6_csum(struct net_device *dev, u32 data); | ||
757 | u32 ethtool_op_get_sg(struct net_device *dev); | ||
758 | int ethtool_op_set_sg(struct net_device *dev, u32 data); | ||
759 | u32 ethtool_op_get_tso(struct net_device *dev); | ||
760 | int ethtool_op_set_tso(struct net_device *dev, u32 data); | ||
761 | u32 ethtool_op_get_ufo(struct net_device *dev); | ||
762 | int ethtool_op_set_ufo(struct net_device *dev, u32 data); | ||
763 | u32 ethtool_op_get_flags(struct net_device *dev); | ||
764 | int ethtool_op_set_flags(struct net_device *dev, u32 data, u32 supported); | ||
765 | bool 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 | ||
2593 | extern struct pernet_operations __net_initdata loopback_net_ops; | 2593 | extern struct pernet_operations __net_initdata loopback_net_ops; |
2594 | 2594 | ||
2595 | static 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 | |||
2604 | static 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 | */ |
1322 | void dev_disable_lro(struct net_device *dev) | 1322 | void 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 | } |
37 | EXPORT_SYMBOL(ethtool_op_get_link); | 37 | EXPORT_SYMBOL(ethtool_op_get_link); |
38 | 38 | ||
39 | u32 ethtool_op_get_tx_csum(struct net_device *dev) | ||
40 | { | ||
41 | return (dev->features & NETIF_F_ALL_CSUM) != 0; | ||
42 | } | ||
43 | EXPORT_SYMBOL(ethtool_op_get_tx_csum); | ||
44 | |||
45 | int 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 | } | ||
54 | EXPORT_SYMBOL(ethtool_op_set_tx_csum); | ||
55 | |||
56 | int 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 | } | ||
65 | EXPORT_SYMBOL(ethtool_op_set_tx_hw_csum); | ||
66 | |||
67 | int 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 | } | ||
76 | EXPORT_SYMBOL(ethtool_op_set_tx_ipv6_csum); | ||
77 | |||
78 | u32 ethtool_op_get_sg(struct net_device *dev) | ||
79 | { | ||
80 | return (dev->features & NETIF_F_SG) != 0; | ||
81 | } | ||
82 | EXPORT_SYMBOL(ethtool_op_get_sg); | ||
83 | |||
84 | int 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 | } | ||
93 | EXPORT_SYMBOL(ethtool_op_set_sg); | ||
94 | |||
95 | u32 ethtool_op_get_tso(struct net_device *dev) | ||
96 | { | ||
97 | return (dev->features & NETIF_F_TSO) != 0; | ||
98 | } | ||
99 | EXPORT_SYMBOL(ethtool_op_get_tso); | ||
100 | |||
101 | int 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 | } | ||
110 | EXPORT_SYMBOL(ethtool_op_set_tso); | ||
111 | |||
112 | u32 ethtool_op_get_ufo(struct net_device *dev) | ||
113 | { | ||
114 | return (dev->features & NETIF_F_UFO) != 0; | ||
115 | } | ||
116 | EXPORT_SYMBOL(ethtool_op_get_ufo); | ||
117 | |||
118 | int 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 | } | ||
126 | EXPORT_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 | */ | ||
131 | static const u32 flags_dup_features = | ||
132 | (ETH_FLAG_LRO | ETH_FLAG_RXVLAN | ETH_FLAG_TXVLAN | ETH_FLAG_NTUPLE | | ||
133 | ETH_FLAG_RXHASH); | ||
134 | |||
135 | u32 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 | } | ||
144 | EXPORT_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 | */ | ||
151 | bool 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 | } | ||
159 | EXPORT_SYMBOL(ethtool_invalid_flags); | ||
160 | |||
161 | int 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 | } | ||
170 | EXPORT_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 | ||
176 | static 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 | |||
200 | static 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 | |||
224 | static 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 | |||
247 | static 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 | |||
269 | static int ethtool_get_features(struct net_device *dev, void __user *useraddr) | 43 | static 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 | ||
436 | static 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 | |||
459 | static u32 __ethtool_get_rx_csum_oldbug(struct net_device *dev) | ||
460 | { | ||
461 | return !!(dev->features & NETIF_F_ALL_CSUM); | ||
462 | } | ||
463 | |||
464 | static int ethtool_get_one_feature(struct net_device *dev, | 205 | static 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 | ||
492 | static int __ethtool_set_tx_csum(struct net_device *dev, u32 data); | ||
493 | static int __ethtool_set_rx_csum(struct net_device *dev, u32 data); | ||
494 | static int __ethtool_set_sg(struct net_device *dev, u32 data); | ||
495 | static int __ethtool_set_tso(struct net_device *dev, u32 data); | ||
496 | static int __ethtool_set_ufo(struct net_device *dev, u32 data); | ||
497 | |||
498 | static int ethtool_set_one_feature(struct net_device *dev, | 219 | static 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); | 246 | static 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); | 250 | static 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 | ||
544 | int __ethtool_set_flags(struct net_device *dev, u32 data) | 255 | static 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 | ||
1234 | static 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 | |||
1258 | static 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 | |||
1274 | static 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 | |||
1285 | static 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 | |||
1296 | static 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 | |||
1309 | static int ethtool_self_test(struct net_device *dev, char __user *useraddr) | 937 | static 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); |