aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--include/linux/ethtool.h85
-rw-r--r--include/linux/netdevice.h37
-rw-r--r--net/core/dev.c46
-rw-r--r--net/core/ethtool.c125
4 files changed, 283 insertions, 10 deletions
diff --git a/include/linux/ethtool.h b/include/linux/ethtool.h
index 1908929204a9..806e716bb4fb 100644
--- a/include/linux/ethtool.h
+++ b/include/linux/ethtool.h
@@ -251,6 +251,7 @@ enum ethtool_stringset {
251 ETH_SS_STATS, 251 ETH_SS_STATS,
252 ETH_SS_PRIV_FLAGS, 252 ETH_SS_PRIV_FLAGS,
253 ETH_SS_NTUPLE_FILTERS, 253 ETH_SS_NTUPLE_FILTERS,
254 ETH_SS_FEATURES,
254}; 255};
255 256
256/* for passing string sets for data tagging */ 257/* for passing string sets for data tagging */
@@ -523,6 +524,87 @@ struct ethtool_flash {
523 char data[ETHTOOL_FLASH_MAX_FILENAME]; 524 char data[ETHTOOL_FLASH_MAX_FILENAME];
524}; 525};
525 526
527/* for returning and changing feature sets */
528
529/**
530 * struct ethtool_get_features_block - block with state of 32 features
531 * @available: mask of changeable features
532 * @requested: mask of features requested to be enabled if possible
533 * @active: mask of currently enabled features
534 * @never_changed: mask of features not changeable for any device
535 */
536struct ethtool_get_features_block {
537 __u32 available;
538 __u32 requested;
539 __u32 active;
540 __u32 never_changed;
541};
542
543/**
544 * struct ethtool_gfeatures - command to get state of device's features
545 * @cmd: command number = %ETHTOOL_GFEATURES
546 * @size: in: number of elements in the features[] array;
547 * out: number of elements in features[] needed to hold all features
548 * @features: state of features
549 */
550struct ethtool_gfeatures {
551 __u32 cmd;
552 __u32 size;
553 struct ethtool_get_features_block features[0];
554};
555
556/**
557 * struct ethtool_set_features_block - block with request for 32 features
558 * @valid: mask of features to be changed
559 * @requested: values of features to be changed
560 */
561struct ethtool_set_features_block {
562 __u32 valid;
563 __u32 requested;
564};
565
566/**
567 * struct ethtool_sfeatures - command to request change in device's features
568 * @cmd: command number = %ETHTOOL_SFEATURES
569 * @size: array size of the features[] array
570 * @features: feature change masks
571 */
572struct ethtool_sfeatures {
573 __u32 cmd;
574 __u32 size;
575 struct ethtool_set_features_block features[0];
576};
577
578/*
579 * %ETHTOOL_SFEATURES changes features present in features[].valid to the
580 * values of corresponding bits in features[].requested. Bits in .requested
581 * not set in .valid or not changeable are ignored.
582 *
583 * Returns %EINVAL when .valid contains undefined or never-changable bits
584 * or size is not equal to required number of features words (32-bit blocks).
585 * Returns >= 0 if request was completed; bits set in the value mean:
586 * %ETHTOOL_F_UNSUPPORTED - there were bits set in .valid that are not
587 * changeable (not present in %ETHTOOL_GFEATURES' features[].available)
588 * those bits were ignored.
589 * %ETHTOOL_F_WISH - some or all changes requested were recorded but the
590 * resulting state of bits masked by .valid is not equal to .requested.
591 * Probably there are other device-specific constraints on some features
592 * in the set. When %ETHTOOL_F_UNSUPPORTED is set, .valid is considered
593 * here as though ignored bits were cleared.
594 *
595 * Meaning of bits in the masks are obtained by %ETHTOOL_GSSET_INFO (number of
596 * bits in the arrays - always multiple of 32) and %ETHTOOL_GSTRINGS commands
597 * for ETH_SS_FEATURES string set. First entry in the table corresponds to least
598 * significant bit in features[0] fields. Empty strings mark undefined features.
599 */
600enum ethtool_sfeatures_retval_bits {
601 ETHTOOL_F_UNSUPPORTED__BIT,
602 ETHTOOL_F_WISH__BIT,
603};
604
605#define ETHTOOL_F_UNSUPPORTED (1 << ETHTOOL_F_UNSUPPORTED__BIT)
606#define ETHTOOL_F_WISH (1 << ETHTOOL_F_WISH__BIT)
607
526#ifdef __KERNEL__ 608#ifdef __KERNEL__
527 609
528#include <linux/rculist.h> 610#include <linux/rculist.h>
@@ -744,6 +826,9 @@ struct ethtool_ops {
744#define ETHTOOL_GRXFHINDIR 0x00000038 /* Get RX flow hash indir'n table */ 826#define ETHTOOL_GRXFHINDIR 0x00000038 /* Get RX flow hash indir'n table */
745#define ETHTOOL_SRXFHINDIR 0x00000039 /* Set RX flow hash indir'n table */ 827#define ETHTOOL_SRXFHINDIR 0x00000039 /* Set RX flow hash indir'n table */
746 828
829#define ETHTOOL_GFEATURES 0x0000003a /* Get device offload settings */
830#define ETHTOOL_SFEATURES 0x0000003b /* Change device offload settings */
831
747/* compatibility with older code */ 832/* compatibility with older code */
748#define SPARC_ETH_GSET ETHTOOL_GSET 833#define SPARC_ETH_GSET ETHTOOL_GSET
749#define SPARC_ETH_SSET ETHTOOL_SSET 834#define SPARC_ETH_SSET ETHTOOL_SSET
diff --git a/include/linux/netdevice.h b/include/linux/netdevice.h
index dede3fdbb4be..85f67e225f60 100644
--- a/include/linux/netdevice.h
+++ b/include/linux/netdevice.h
@@ -791,6 +791,18 @@ struct netdev_tc_txq {
791 * 791 *
792 * int (*ndo_del_slave)(struct net_device *dev, struct net_device *slave_dev); 792 * int (*ndo_del_slave)(struct net_device *dev, struct net_device *slave_dev);
793 * Called to release previously enslaved netdev. 793 * Called to release previously enslaved netdev.
794 *
795 * Feature/offload setting functions.
796 * u32 (*ndo_fix_features)(struct net_device *dev, u32 features);
797 * Adjusts the requested feature flags according to device-specific
798 * constraints, and returns the resulting flags. Must not modify
799 * the device state.
800 *
801 * int (*ndo_set_features)(struct net_device *dev, u32 features);
802 * Called to update device configuration to new features. Passed
803 * feature set might be less than what was returned by ndo_fix_features()).
804 * Must return >0 or -errno if it changed dev->features itself.
805 *
794 */ 806 */
795#define HAVE_NET_DEVICE_OPS 807#define HAVE_NET_DEVICE_OPS
796struct net_device_ops { 808struct net_device_ops {
@@ -874,6 +886,10 @@ struct net_device_ops {
874 struct net_device *slave_dev); 886 struct net_device *slave_dev);
875 int (*ndo_del_slave)(struct net_device *dev, 887 int (*ndo_del_slave)(struct net_device *dev,
876 struct net_device *slave_dev); 888 struct net_device *slave_dev);
889 u32 (*ndo_fix_features)(struct net_device *dev,
890 u32 features);
891 int (*ndo_set_features)(struct net_device *dev,
892 u32 features);
877}; 893};
878 894
879/* 895/*
@@ -925,12 +941,18 @@ struct net_device {
925 struct list_head napi_list; 941 struct list_head napi_list;
926 struct list_head unreg_list; 942 struct list_head unreg_list;
927 943
928 /* Net device features */ 944 /* currently active device features */
929 u32 features; 945 u32 features;
930 946 /* user-changeable features */
947 u32 hw_features;
948 /* user-requested features */
949 u32 wanted_features;
931 /* VLAN feature mask */ 950 /* VLAN feature mask */
932 u32 vlan_features; 951 u32 vlan_features;
933 952
953 /* Net device feature bits; if you change something,
954 * also update netdev_features_strings[] in ethtool.c */
955
934#define NETIF_F_SG 1 /* Scatter/gather IO. */ 956#define NETIF_F_SG 1 /* Scatter/gather IO. */
935#define NETIF_F_IP_CSUM 2 /* Can checksum TCP/UDP over IPv4. */ 957#define NETIF_F_IP_CSUM 2 /* Can checksum TCP/UDP over IPv4. */
936#define NETIF_F_NO_CSUM 4 /* Does not require checksum. F.e. loopack. */ 958#define NETIF_F_NO_CSUM 4 /* Does not require checksum. F.e. loopack. */
@@ -966,6 +988,12 @@ struct net_device {
966#define NETIF_F_TSO6 (SKB_GSO_TCPV6 << NETIF_F_GSO_SHIFT) 988#define NETIF_F_TSO6 (SKB_GSO_TCPV6 << NETIF_F_GSO_SHIFT)
967#define NETIF_F_FSO (SKB_GSO_FCOE << NETIF_F_GSO_SHIFT) 989#define NETIF_F_FSO (SKB_GSO_FCOE << NETIF_F_GSO_SHIFT)
968 990
991 /* Features valid for ethtool to change */
992 /* = all defined minus driver/device-class-related */
993#define NETIF_F_NEVER_CHANGE (NETIF_F_HIGHDMA | NETIF_F_VLAN_CHALLENGED | \
994 NETIF_F_LLTX | NETIF_F_NETNS_LOCAL)
995#define NETIF_F_ETHTOOL_BITS (0x1f3fffff & ~NETIF_F_NEVER_CHANGE)
996
969 /* List of features with software fallbacks. */ 997 /* List of features with software fallbacks. */
970#define NETIF_F_GSO_SOFTWARE (NETIF_F_TSO | NETIF_F_TSO_ECN | \ 998#define NETIF_F_GSO_SOFTWARE (NETIF_F_TSO | NETIF_F_TSO_ECN | \
971 NETIF_F_TSO6 | NETIF_F_UFO) 999 NETIF_F_TSO6 | NETIF_F_UFO)
@@ -2428,8 +2456,13 @@ extern char *netdev_drivername(const struct net_device *dev, char *buffer, int l
2428 2456
2429extern void linkwatch_run_queue(void); 2457extern void linkwatch_run_queue(void);
2430 2458
2459static inline u32 netdev_get_wanted_features(struct net_device *dev)
2460{
2461 return (dev->features & ~dev->hw_features) | dev->wanted_features;
2462}
2431u32 netdev_increment_features(u32 all, u32 one, u32 mask); 2463u32 netdev_increment_features(u32 all, u32 one, u32 mask);
2432u32 netdev_fix_features(struct net_device *dev, u32 features); 2464u32 netdev_fix_features(struct net_device *dev, u32 features);
2465void netdev_update_features(struct net_device *dev);
2433 2466
2434void netif_stacked_transfer_operstate(const struct net_device *rootdev, 2467void netif_stacked_transfer_operstate(const struct net_device *rootdev,
2435 struct net_device *dev); 2468 struct net_device *dev);
diff --git a/net/core/dev.c b/net/core/dev.c
index 8686f6ffe7f0..4f6943928fe8 100644
--- a/net/core/dev.c
+++ b/net/core/dev.c
@@ -5302,6 +5302,37 @@ u32 netdev_fix_features(struct net_device *dev, u32 features)
5302} 5302}
5303EXPORT_SYMBOL(netdev_fix_features); 5303EXPORT_SYMBOL(netdev_fix_features);
5304 5304
5305void netdev_update_features(struct net_device *dev)
5306{
5307 u32 features;
5308 int err = 0;
5309
5310 features = netdev_get_wanted_features(dev);
5311
5312 if (dev->netdev_ops->ndo_fix_features)
5313 features = dev->netdev_ops->ndo_fix_features(dev, features);
5314
5315 /* driver might be less strict about feature dependencies */
5316 features = netdev_fix_features(dev, features);
5317
5318 if (dev->features == features)
5319 return;
5320
5321 netdev_info(dev, "Features changed: 0x%08x -> 0x%08x\n",
5322 dev->features, features);
5323
5324 if (dev->netdev_ops->ndo_set_features)
5325 err = dev->netdev_ops->ndo_set_features(dev, features);
5326
5327 if (!err)
5328 dev->features = features;
5329 else if (err < 0)
5330 netdev_err(dev,
5331 "set_features() failed (%d); wanted 0x%08x, left 0x%08x\n",
5332 err, features, dev->features);
5333}
5334EXPORT_SYMBOL(netdev_update_features);
5335
5305/** 5336/**
5306 * netif_stacked_transfer_operstate - transfer operstate 5337 * netif_stacked_transfer_operstate - transfer operstate
5307 * @rootdev: the root or lower level device to transfer state from 5338 * @rootdev: the root or lower level device to transfer state from
@@ -5436,15 +5467,18 @@ int register_netdevice(struct net_device *dev)
5436 if (dev->iflink == -1) 5467 if (dev->iflink == -1)
5437 dev->iflink = dev->ifindex; 5468 dev->iflink = dev->ifindex;
5438 5469
5439 /* Enable software offloads by default - will be stripped in 5470 /* Transfer changeable features to wanted_features and enable
5440 * netdev_fix_features() if not supported. */ 5471 * software offloads (GSO and GRO).
5441 dev->features |= NETIF_F_SOFT_FEATURES; 5472 */
5473 dev->hw_features |= NETIF_F_SOFT_FEATURES;
5474 dev->wanted_features = (dev->features & dev->hw_features)
5475 | NETIF_F_SOFT_FEATURES;
5442 5476
5443 /* Avoid warning from netdev_fix_features() for GSO without SG */ 5477 /* Avoid warning from netdev_fix_features() for GSO without SG */
5444 if (!(dev->features & NETIF_F_SG)) 5478 if (!(dev->wanted_features & NETIF_F_SG))
5445 dev->features &= ~NETIF_F_GSO; 5479 dev->wanted_features &= ~NETIF_F_GSO;
5446 5480
5447 dev->features = netdev_fix_features(dev, dev->features); 5481 netdev_update_features(dev);
5448 5482
5449 /* Enable GRO and NETIF_F_HIGHDMA for vlans by default, 5483 /* Enable GRO and NETIF_F_HIGHDMA for vlans by default,
5450 * vlan_dev_init() will do the dev->features check, so these features 5484 * vlan_dev_init() will do the dev->features check, so these features
diff --git a/net/core/ethtool.c b/net/core/ethtool.c
index c3fb8f90de6d..95773960dc77 100644
--- a/net/core/ethtool.c
+++ b/net/core/ethtool.c
@@ -172,10 +172,120 @@ EXPORT_SYMBOL(ethtool_ntuple_flush);
172 172
173/* Handlers for each ethtool command */ 173/* Handlers for each ethtool command */
174 174
175#define ETHTOOL_DEV_FEATURE_WORDS 1
176
177static int ethtool_get_features(struct net_device *dev, void __user *useraddr)
178{
179 struct ethtool_gfeatures cmd = {
180 .cmd = ETHTOOL_GFEATURES,
181 .size = ETHTOOL_DEV_FEATURE_WORDS,
182 };
183 struct ethtool_get_features_block features[ETHTOOL_DEV_FEATURE_WORDS] = {
184 {
185 .available = dev->hw_features,
186 .requested = dev->wanted_features,
187 .active = dev->features,
188 .never_changed = NETIF_F_NEVER_CHANGE,
189 },
190 };
191 u32 __user *sizeaddr;
192 u32 copy_size;
193
194 sizeaddr = useraddr + offsetof(struct ethtool_gfeatures, size);
195 if (get_user(copy_size, sizeaddr))
196 return -EFAULT;
197
198 if (copy_size > ETHTOOL_DEV_FEATURE_WORDS)
199 copy_size = ETHTOOL_DEV_FEATURE_WORDS;
200
201 if (copy_to_user(useraddr, &cmd, sizeof(cmd)))
202 return -EFAULT;
203 useraddr += sizeof(cmd);
204 if (copy_to_user(useraddr, features, copy_size * sizeof(*features)))
205 return -EFAULT;
206
207 return 0;
208}
209
210static int ethtool_set_features(struct net_device *dev, void __user *useraddr)
211{
212 struct ethtool_sfeatures cmd;
213 struct ethtool_set_features_block features[ETHTOOL_DEV_FEATURE_WORDS];
214 int ret = 0;
215
216 if (copy_from_user(&cmd, useraddr, sizeof(cmd)))
217 return -EFAULT;
218 useraddr += sizeof(cmd);
219
220 if (cmd.size != ETHTOOL_DEV_FEATURE_WORDS)
221 return -EINVAL;
222
223 if (copy_from_user(features, useraddr, sizeof(features)))
224 return -EFAULT;
225
226 if (features[0].valid & ~NETIF_F_ETHTOOL_BITS)
227 return -EINVAL;
228
229 if (features[0].valid & ~dev->hw_features) {
230 features[0].valid &= dev->hw_features;
231 ret |= ETHTOOL_F_UNSUPPORTED;
232 }
233
234 dev->wanted_features &= ~features[0].valid;
235 dev->wanted_features |= features[0].valid & features[0].requested;
236 netdev_update_features(dev);
237
238 if ((dev->wanted_features ^ dev->features) & features[0].valid)
239 ret |= ETHTOOL_F_WISH;
240
241 return ret;
242}
243
244static const char netdev_features_strings[ETHTOOL_DEV_FEATURE_WORDS * 32][ETH_GSTRING_LEN] = {
245 /* NETIF_F_SG */ "tx-scatter-gather",
246 /* NETIF_F_IP_CSUM */ "tx-checksum-ipv4",
247 /* NETIF_F_NO_CSUM */ "tx-checksum-unneeded",
248 /* NETIF_F_HW_CSUM */ "tx-checksum-ip-generic",
249 /* NETIF_F_IPV6_CSUM */ "tx_checksum-ipv6",
250 /* NETIF_F_HIGHDMA */ "highdma",
251 /* NETIF_F_FRAGLIST */ "tx-scatter-gather-fraglist",
252 /* NETIF_F_HW_VLAN_TX */ "tx-vlan-hw-insert",
253
254 /* NETIF_F_HW_VLAN_RX */ "rx-vlan-hw-parse",
255 /* NETIF_F_HW_VLAN_FILTER */ "rx-vlan-filter",
256 /* NETIF_F_VLAN_CHALLENGED */ "vlan-challenged",
257 /* NETIF_F_GSO */ "tx-generic-segmentation",
258 /* NETIF_F_LLTX */ "tx-lockless",
259 /* NETIF_F_NETNS_LOCAL */ "netns-local",
260 /* NETIF_F_GRO */ "rx-gro",
261 /* NETIF_F_LRO */ "rx-lro",
262
263 /* NETIF_F_TSO */ "tx-tcp-segmentation",
264 /* NETIF_F_UFO */ "tx-udp-fragmentation",
265 /* NETIF_F_GSO_ROBUST */ "tx-gso-robust",
266 /* NETIF_F_TSO_ECN */ "tx-tcp-ecn-segmentation",
267 /* NETIF_F_TSO6 */ "tx-tcp6-segmentation",
268 /* NETIF_F_FSO */ "tx-fcoe-segmentation",
269 "",
270 "",
271
272 /* NETIF_F_FCOE_CRC */ "tx-checksum-fcoe-crc",
273 /* NETIF_F_SCTP_CSUM */ "tx-checksum-sctp",
274 /* NETIF_F_FCOE_MTU */ "fcoe-mtu",
275 /* NETIF_F_NTUPLE */ "rx-ntuple-filter",
276 /* NETIF_F_RXHASH */ "rx-hashing",
277 "",
278 "",
279 "",
280};
281
175static int __ethtool_get_sset_count(struct net_device *dev, int sset) 282static int __ethtool_get_sset_count(struct net_device *dev, int sset)
176{ 283{
177 const struct ethtool_ops *ops = dev->ethtool_ops; 284 const struct ethtool_ops *ops = dev->ethtool_ops;
178 285
286 if (sset == ETH_SS_FEATURES)
287 return ARRAY_SIZE(netdev_features_strings);
288
179 if (ops && ops->get_sset_count && ops->get_strings) 289 if (ops && ops->get_sset_count && ops->get_strings)
180 return ops->get_sset_count(dev, sset); 290 return ops->get_sset_count(dev, sset);
181 else 291 else
@@ -187,8 +297,12 @@ static void __ethtool_get_strings(struct net_device *dev,
187{ 297{
188 const struct ethtool_ops *ops = dev->ethtool_ops; 298 const struct ethtool_ops *ops = dev->ethtool_ops;
189 299
190 /* ops->get_strings is valid because checked earlier */ 300 if (stringset == ETH_SS_FEATURES)
191 ops->get_strings(dev, stringset, data); 301 memcpy(data, netdev_features_strings,
302 sizeof(netdev_features_strings));
303 else
304 /* ops->get_strings is valid because checked earlier */
305 ops->get_strings(dev, stringset, data);
192} 306}
193 307
194static u32 ethtool_get_feature_mask(u32 eth_cmd) 308static u32 ethtool_get_feature_mask(u32 eth_cmd)
@@ -1533,6 +1647,7 @@ int dev_ethtool(struct net *net, struct ifreq *ifr)
1533 case ETHTOOL_GRXCLSRLCNT: 1647 case ETHTOOL_GRXCLSRLCNT:
1534 case ETHTOOL_GRXCLSRULE: 1648 case ETHTOOL_GRXCLSRULE:
1535 case ETHTOOL_GRXCLSRLALL: 1649 case ETHTOOL_GRXCLSRLALL:
1650 case ETHTOOL_GFEATURES:
1536 break; 1651 break;
1537 default: 1652 default:
1538 if (!capable(CAP_NET_ADMIN)) 1653 if (!capable(CAP_NET_ADMIN))
@@ -1678,6 +1793,12 @@ int dev_ethtool(struct net *net, struct ifreq *ifr)
1678 case ETHTOOL_SRXFHINDIR: 1793 case ETHTOOL_SRXFHINDIR:
1679 rc = ethtool_set_rxfh_indir(dev, useraddr); 1794 rc = ethtool_set_rxfh_indir(dev, useraddr);
1680 break; 1795 break;
1796 case ETHTOOL_GFEATURES:
1797 rc = ethtool_get_features(dev, useraddr);
1798 break;
1799 case ETHTOOL_SFEATURES:
1800 rc = ethtool_set_features(dev, useraddr);
1801 break;
1681 case ETHTOOL_GTXCSUM: 1802 case ETHTOOL_GTXCSUM:
1682 case ETHTOOL_GSG: 1803 case ETHTOOL_GSG:
1683 case ETHTOOL_GTSO: 1804 case ETHTOOL_GTSO: