Netdev List
 help / color / mirror / Atom feed
* Re: [PATCH] myri10ge: 64bit slice stats
From: Eric Dumazet @ 2011-06-20 18:52 UTC (permalink / raw)
  To: Jon Mason; +Cc: David Miller, netdev, Andrew Gallatin
In-Reply-To: <1308595758.2658.16.camel@edumazet-laptop>

Le lundi 20 juin 2011 à 20:49 +0200, Eric Dumazet a écrit :

> Hmm, no sorry, this wont work on 32bit arches :(
> 
> Please take a look at various patches addressing this problem.
> 
> 

For example take a look at the once sent some hours ago :

http://patchwork.ozlabs.org/patch/101128/




^ permalink raw reply

* [RFT PATCH 3/9] net: ethtool: break association of ETH_FLAG_* with NETIF_F_*
From: Michał Mirosław @ 2011-06-20 19:14 UTC (permalink / raw)
  To: netdev; +Cc: David S. Miller, Ben Hutchings
In-Reply-To: <cover.1308596962.git.mirq-linux@rere.qmqm.pl>

This is the only place where NETIF_F_* feature flags are exposed
to userspace. After this patch feature flags may be changed/reordered
freely.

Signed-off-by: Michał Mirosław <mirq-linux@rere.qmqm.pl>
---
 net/core/ethtool.c |   33 +++++++++++++++++++++++----------
 1 files changed, 23 insertions(+), 10 deletions(-)

diff --git a/net/core/ethtool.c b/net/core/ethtool.c
index 58d98c3..9214e54 100644
--- a/net/core/ethtool.c
+++ b/net/core/ethtool.c
@@ -240,32 +240,45 @@ static int ethtool_set_one_feature(struct net_device *dev,
 	return 0;
 }
 
-/* the following list of flags are the same as their associated
- * NETIF_F_xxx values in include/linux/netdevice.h
- */
-static const u32 flags_dup_features =
-	(ETH_FLAG_LRO | ETH_FLAG_RXVLAN | ETH_FLAG_TXVLAN | ETH_FLAG_NTUPLE |
-	 ETH_FLAG_RXHASH);
+#define ETH_ALL_FLAGS    (ETH_FLAG_LRO | ETH_FLAG_RXVLAN | ETH_FLAG_TXVLAN | \
+			  ETH_FLAG_NTUPLE | ETH_FLAG_RXHASH)
+#define ETH_ALL_FEATURES (NETIF_F_LRO | NETIF_F_HW_VLAN_RX | \
+			  NETIF_F_HW_VLAN_TX | NETIF_F_NTUPLE | NETIF_F_RXHASH)
 
 static u32 __ethtool_get_flags(struct net_device *dev)
 {
-	return dev->features & flags_dup_features;
+	u32 flags = 0;
+
+	if (dev->features & NETIF_F_LRO)	flags |= ETH_FLAG_LRO;
+	if (dev->features & NETIF_F_HW_VLAN_RX)	flags |= ETH_FLAG_RXVLAN;
+	if (dev->features & NETIF_F_HW_VLAN_TX)	flags |= ETH_FLAG_TXVLAN;
+	if (dev->features & NETIF_F_NTUPLE)	flags |= ETH_FLAG_NTUPLE;
+	if (dev->features & NETIF_F_RXHASH)	flags |= ETH_FLAG_RXHASH;
+
+	return flags;
 }
 
 static int __ethtool_set_flags(struct net_device *dev, u32 data)
 {
+	u32 features = 0;
 	u32 changed;
 
-	if (data & ~flags_dup_features)
+	if (data & ~ETH_ALL_FLAGS)
 		return -EINVAL;
 
+	if (data & ETH_FLAG_LRO)	features |= NETIF_F_LRO;
+	if (data & ETH_FLAG_RXVLAN)	features |= NETIF_F_HW_VLAN_RX;
+	if (data & ETH_FLAG_TXVLAN)	features |= NETIF_F_HW_VLAN_TX;
+	if (data & ETH_FLAG_NTUPLE)	features |= NETIF_F_NTUPLE;
+	if (data & ETH_FLAG_RXHASH)	features |= NETIF_F_RXHASH;
+
 	/* allow changing only bits set in hw_features */
-	changed = (data ^ dev->features) & flags_dup_features;
+	changed = (features ^ dev->features) & ETH_ALL_FEATURES;
 	if (changed & ~dev->hw_features)
 		return (changed & dev->hw_features) ? -EINVAL : -EOPNOTSUPP;
 
 	dev->wanted_features =
-		(dev->wanted_features & ~changed) | (data & dev->hw_features);
+		(dev->wanted_features & ~changed) | (features & dev->hw_features);
 
 	__netdev_update_features(dev);
 
-- 
1.7.2.5


^ permalink raw reply related

* [RFT PATCH 6/9] net: ethtool: use C99 array initialization for feature-names table
From: Michał Mirosław @ 2011-06-20 19:14 UTC (permalink / raw)
  To: netdev; +Cc: David S. Miller, Ben Hutchings
In-Reply-To: <cover.1308596962.git.mirq-linux@rere.qmqm.pl>

Signed-off-by: Michał Mirosław <mirq-linux@rere.qmqm.pl>
---
 net/core/ethtool.c |   74 +++++++++++++++++++++++++--------------------------
 1 files changed, 36 insertions(+), 38 deletions(-)

diff --git a/net/core/ethtool.c b/net/core/ethtool.c
index 17f5f96..97bbf25 100644
--- a/net/core/ethtool.c
+++ b/net/core/ethtool.c
@@ -40,6 +40,42 @@ EXPORT_SYMBOL(ethtool_op_get_link);
 
 #define ETHTOOL_DEV_FEATURE_WORDS	1
 
+static const char netdev_features_strings[NETDEV_FEATURE_COUNT][ETH_GSTRING_LEN] = {
+	[NETIF_F_SG_BIT] =               "tx-scatter-gather",
+	[NETIF_F_IP_CSUM_BIT] =          "tx-checksum-ipv4",
+	[NETIF_F_NO_CSUM_BIT] =          "tx-checksum-unneeded",
+	[NETIF_F_HW_CSUM_BIT] =          "tx-checksum-ip-generic",
+	[NETIF_F_IPV6_CSUM_BIT] =        "tx-checksum-ipv6",
+	[NETIF_F_HIGHDMA_BIT] =          "highdma",
+	[NETIF_F_FRAGLIST_BIT] =         "tx-scatter-gather-fraglist",
+	[NETIF_F_HW_VLAN_TX_BIT] =       "tx-vlan-hw-insert",
+
+	[NETIF_F_HW_VLAN_RX_BIT] =       "rx-vlan-hw-parse",
+	[NETIF_F_HW_VLAN_FILTER_BIT] =   "rx-vlan-filter",
+	[NETIF_F_VLAN_CHALLENGED_BIT] =  "vlan-challenged",
+	[NETIF_F_GSO_BIT] =              "tx-generic-segmentation",
+	[NETIF_F_LLTX_BIT] =             "tx-lockless",
+	[NETIF_F_NETNS_LOCAL_BIT] =      "netns-local",
+	[NETIF_F_GRO_BIT] =              "rx-gro",
+	[NETIF_F_LRO_BIT] =              "rx-lro",
+
+	[NETIF_F_TSO_BIT] =              "tx-tcp-segmentation",
+	[NETIF_F_UFO_BIT] =              "tx-udp-fragmentation",
+	[NETIF_F_GSO_ROBUST_BIT] =       "tx-gso-robust",
+	[NETIF_F_TSO_ECN_BIT] =          "tx-tcp-ecn-segmentation",
+	[NETIF_F_TSO6_BIT] =             "tx-tcp6-segmentation",
+	[NETIF_F_FSO_BIT] =              "tx-fcoe-segmentation",
+
+	[NETIF_F_FCOE_CRC_BIT] =         "tx-checksum-fcoe-crc",
+	[NETIF_F_SCTP_CSUM_BIT] =        "tx-checksum-sctp",
+	[NETIF_F_FCOE_MTU_BIT] =         "fcoe-mtu",
+	[NETIF_F_NTUPLE_BIT] =           "rx-ntuple-filter",
+	[NETIF_F_RXHASH_BIT] =           "rx-hashing",
+	[NETIF_F_RXCSUM_BIT] =           "rx-checksum",
+	[NETIF_F_NOCACHE_COPY_BIT] =     "tx-nocache-copy",
+	[NETIF_F_LOOPBACK_BIT] =         "loopback",
+};
+
 static int ethtool_get_features(struct net_device *dev, void __user *useraddr)
 {
 	struct ethtool_gfeatures cmd = {
@@ -107,44 +143,6 @@ static int ethtool_set_features(struct net_device *dev, void __user *useraddr)
 	return ret;
 }
 
-static const char netdev_features_strings[ETHTOOL_DEV_FEATURE_WORDS * 32][ETH_GSTRING_LEN] = {
-	/* NETIF_F_SG */              "tx-scatter-gather",
-	/* NETIF_F_IP_CSUM */         "tx-checksum-ipv4",
-	/* NETIF_F_NO_CSUM */         "tx-checksum-unneeded",
-	/* NETIF_F_HW_CSUM */         "tx-checksum-ip-generic",
-	/* NETIF_F_IPV6_CSUM */       "tx-checksum-ipv6",
-	/* NETIF_F_HIGHDMA */         "highdma",
-	/* NETIF_F_FRAGLIST */        "tx-scatter-gather-fraglist",
-	/* NETIF_F_HW_VLAN_TX */      "tx-vlan-hw-insert",
-
-	/* NETIF_F_HW_VLAN_RX */      "rx-vlan-hw-parse",
-	/* NETIF_F_HW_VLAN_FILTER */  "rx-vlan-filter",
-	/* NETIF_F_VLAN_CHALLENGED */ "vlan-challenged",
-	/* NETIF_F_GSO */             "tx-generic-segmentation",
-	/* NETIF_F_LLTX */            "tx-lockless",
-	/* NETIF_F_NETNS_LOCAL */     "netns-local",
-	/* NETIF_F_GRO */             "rx-gro",
-	/* NETIF_F_LRO */             "rx-lro",
-
-	/* NETIF_F_TSO */             "tx-tcp-segmentation",
-	/* NETIF_F_UFO */             "tx-udp-fragmentation",
-	/* NETIF_F_GSO_ROBUST */      "tx-gso-robust",
-	/* NETIF_F_TSO_ECN */         "tx-tcp-ecn-segmentation",
-	/* NETIF_F_TSO6 */            "tx-tcp6-segmentation",
-	/* NETIF_F_FSO */             "tx-fcoe-segmentation",
-	"",
-	"",
-
-	/* NETIF_F_FCOE_CRC */        "tx-checksum-fcoe-crc",
-	/* NETIF_F_SCTP_CSUM */       "tx-checksum-sctp",
-	/* NETIF_F_FCOE_MTU */        "fcoe-mtu",
-	/* NETIF_F_NTUPLE */          "rx-ntuple-filter",
-	/* NETIF_F_RXHASH */          "rx-hashing",
-	/* NETIF_F_RXCSUM */          "rx-checksum",
-	/* NETIF_F_NOCACHE_COPY */    "tx-nocache-copy",
-	/* NETIF_F_LOOPBACK */        "loopback",
-};
-
 static int __ethtool_get_sset_count(struct net_device *dev, int sset)
 {
 	const struct ethtool_ops *ops = dev->ethtool_ops;
-- 
1.7.2.5


^ permalink raw reply related

* [RFT PATCH 2/9] net: remove legacy ethtool ops
From: Michał Mirosław @ 2011-06-20 19:14 UTC (permalink / raw)
  To: netdev; +Cc: David S. Miller, Ben Hutchings
In-Reply-To: <cover.1308596962.git.mirq-linux@rere.qmqm.pl>

As all drivers are converted, we may now remove discrete offload setting
callback handling.

Signed-off-by: Michał Mirosław <mirq-linux@rere.qmqm.pl>
---
 include/linux/ethtool.h   |   53 ------
 include/linux/netdevice.h |   16 --
 net/8021q/vlan_dev.c      |    2 +-
 net/core/dev.c            |   12 +-
 net/core/ethtool.c        |  422 +++------------------------------------------
 5 files changed, 27 insertions(+), 478 deletions(-)

diff --git a/include/linux/ethtool.h b/include/linux/ethtool.h
index dfd3493..b1d1a68 100644
--- a/include/linux/ethtool.h
+++ b/include/linux/ethtool.h
@@ -711,9 +711,6 @@ enum ethtool_sfeatures_retval_bits {
 
 #include <linux/rculist.h>
 
-/* needed by dev_disable_lro() */
-extern int __ethtool_set_flags(struct net_device *dev, u32 flags);
-
 /**
  * enum ethtool_phys_id_state - indicator state for physical identification
  * @ETHTOOL_ID_INACTIVE: Physical ID indicator should be deactivated
@@ -734,19 +731,6 @@ struct net_device;
 
 /* Some generic methods drivers may use in their ethtool_ops */
 u32 ethtool_op_get_link(struct net_device *dev);
-u32 ethtool_op_get_tx_csum(struct net_device *dev);
-int ethtool_op_set_tx_csum(struct net_device *dev, u32 data);
-int ethtool_op_set_tx_hw_csum(struct net_device *dev, u32 data);
-int ethtool_op_set_tx_ipv6_csum(struct net_device *dev, u32 data);
-u32 ethtool_op_get_sg(struct net_device *dev);
-int ethtool_op_set_sg(struct net_device *dev, u32 data);
-u32 ethtool_op_get_tso(struct net_device *dev);
-int ethtool_op_set_tso(struct net_device *dev, u32 data);
-u32 ethtool_op_get_ufo(struct net_device *dev);
-int ethtool_op_set_ufo(struct net_device *dev, u32 data);
-u32 ethtool_op_get_flags(struct net_device *dev);
-int ethtool_op_set_flags(struct net_device *dev, u32 data, u32 supported);
-bool ethtool_invalid_flags(struct net_device *dev, u32 data, u32 supported);
 
 /**
  * struct ethtool_ops - optional netdev operations
@@ -791,22 +775,6 @@ bool ethtool_invalid_flags(struct net_device *dev, u32 data, u32 supported);
  * @get_pauseparam: Report pause parameters
  * @set_pauseparam: Set pause parameters.  Returns a negative error code
  *	or zero.
- * @get_rx_csum: Deprecated in favour of the netdev feature %NETIF_F_RXCSUM.
- *	Report whether receive checksums are turned on or off.
- * @set_rx_csum: Deprecated in favour of generic netdev features.  Turn
- *	receive checksum on or off.  Returns a negative error code or zero.
- * @get_tx_csum: Deprecated as redundant. Report whether transmit checksums
- *	are turned on or off.
- * @set_tx_csum: Deprecated in favour of generic netdev features.  Turn
- *	transmit checksums on or off.  Returns a egative error code or zero.
- * @get_sg: Deprecated as redundant.  Report whether scatter-gather is
- *	enabled.  
- * @set_sg: Deprecated in favour of generic netdev features.  Turn
- *	scatter-gather on or off. Returns a negative error code or zero.
- * @get_tso: Deprecated as redundant.  Report whether TCP segmentation
- *	offload is enabled.
- * @set_tso: Deprecated in favour of generic netdev features.  Turn TCP
- *	segmentation offload on or off.  Returns a negative error code or zero.
  * @self_test: Run specified self-tests
  * @get_strings: Return a set of strings that describe the requested objects
  * @set_phys_id: Identify the physical devices, e.g. by flashing an LED
@@ -828,15 +796,6 @@ bool ethtool_invalid_flags(struct net_device *dev, u32 data, u32 supported);
  *	negative error code or zero.
  * @complete: Function to be called after any other operation except
  *	@begin.  Will be called even if the other operation failed.
- * @get_ufo: Deprecated as redundant.  Report whether UDP fragmentation
- *	offload is enabled.
- * @set_ufo: Deprecated in favour of generic netdev features.  Turn UDP
- *	fragmentation offload on or off.  Returns a negative error code or zero.
- * @get_flags: Deprecated as redundant.  Report features included in
- *	&enum ethtool_flags that are enabled.  
- * @set_flags: Deprecated in favour of generic netdev features.  Turn
- *	features included in &enum ethtool_flags on or off.  Returns a
- *	negative error code or zero.
  * @get_priv_flags: Report driver-specific feature flags.
  * @set_priv_flags: Set driver-specific feature flags.  Returns a negative
  *	error code or zero.
@@ -901,14 +860,6 @@ struct ethtool_ops {
 				  struct ethtool_pauseparam*);
 	int	(*set_pauseparam)(struct net_device *,
 				  struct ethtool_pauseparam*);
-	u32	(*get_rx_csum)(struct net_device *);
-	int	(*set_rx_csum)(struct net_device *, u32);
-	u32	(*get_tx_csum)(struct net_device *);
-	int	(*set_tx_csum)(struct net_device *, u32);
-	u32	(*get_sg)(struct net_device *);
-	int	(*set_sg)(struct net_device *, u32);
-	u32	(*get_tso)(struct net_device *);
-	int	(*set_tso)(struct net_device *, u32);
 	void	(*self_test)(struct net_device *, struct ethtool_test *, u64 *);
 	void	(*get_strings)(struct net_device *, u32 stringset, u8 *);
 	int	(*set_phys_id)(struct net_device *, enum ethtool_phys_id_state);
@@ -916,10 +867,6 @@ struct ethtool_ops {
 				     struct ethtool_stats *, u64 *);
 	int	(*begin)(struct net_device *);
 	void	(*complete)(struct net_device *);
-	u32	(*get_ufo)(struct net_device *);
-	int	(*set_ufo)(struct net_device *, u32);
-	u32	(*get_flags)(struct net_device *);
-	int	(*set_flags)(struct net_device *, u32);
 	u32	(*get_priv_flags)(struct net_device *);
 	int	(*set_priv_flags)(struct net_device *, u32);
 	int	(*get_sset_count)(struct net_device *, int);
diff --git a/include/linux/netdevice.h b/include/linux/netdevice.h
index 6469fa9..3482ee9 100644
--- a/include/linux/netdevice.h
+++ b/include/linux/netdevice.h
@@ -2604,22 +2604,6 @@ extern struct pernet_operations __net_initdata loopback_net_ops;
 int dev_ethtool_get_settings(struct net_device *dev,
 			     struct ethtool_cmd *cmd);
 
-static inline u32 dev_ethtool_get_rx_csum(struct net_device *dev)
-{
-	if (dev->features & NETIF_F_RXCSUM)
-		return 1;
-	if (!dev->ethtool_ops || !dev->ethtool_ops->get_rx_csum)
-		return 0;
-	return dev->ethtool_ops->get_rx_csum(dev);
-}
-
-static inline u32 dev_ethtool_get_flags(struct net_device *dev)
-{
-	if (!dev->ethtool_ops || !dev->ethtool_ops->get_flags)
-		return 0;
-	return dev->ethtool_ops->get_flags(dev);
-}
-
 /* Logging, debugging and troubleshooting/diagnostic helpers. */
 
 /* netdev_printk helpers, similar to dev_printk */
diff --git a/net/8021q/vlan_dev.c b/net/8021q/vlan_dev.c
index 1c9aa8c..774bd22 100644
--- a/net/8021q/vlan_dev.c
+++ b/net/8021q/vlan_dev.c
@@ -591,7 +591,7 @@ static u32 vlan_dev_fix_features(struct net_device *dev, u32 features)
 
 	features &= real_dev->features;
 	features &= real_dev->vlan_features;
-	if (dev_ethtool_get_rx_csum(real_dev))
+	if (real_dev->features & NETIF_F_RXCSUM)
 		features |= NETIF_F_RXCSUM;
 	features |= NETIF_F_LLTX;
 
diff --git a/net/core/dev.c b/net/core/dev.c
index b3f52d2..3041b6ae 100644
--- a/net/core/dev.c
+++ b/net/core/dev.c
@@ -1306,8 +1306,6 @@ EXPORT_SYMBOL(dev_close);
  */
 void dev_disable_lro(struct net_device *dev)
 {
-	u32 flags;
-
 	/*
 	 * If we're trying to disable lro on a vlan device
 	 * use the underlying physical device instead
@@ -1315,15 +1313,9 @@ void dev_disable_lro(struct net_device *dev)
 	if (is_vlan_dev(dev))
 		dev = vlan_dev_real_dev(dev);
 
-	if (dev->ethtool_ops && dev->ethtool_ops->get_flags)
-		flags = dev->ethtool_ops->get_flags(dev);
-	else
-		flags = ethtool_op_get_flags(dev);
+	dev->wanted_features &= ~NETIF_F_LRO;
+	netdev_update_features(dev);
 
-	if (!(flags & ETH_FLAG_LRO))
-		return;
-
-	__ethtool_set_flags(dev, flags & ~ETH_FLAG_LRO);
 	if (unlikely(dev->features & NETIF_F_LRO))
 		netdev_WARN(dev, "failed to disable LRO!\n");
 }
diff --git a/net/core/ethtool.c b/net/core/ethtool.c
index b7c12a6..58d98c3 100644
--- a/net/core/ethtool.c
+++ b/net/core/ethtool.c
@@ -36,236 +36,10 @@ u32 ethtool_op_get_link(struct net_device *dev)
 }
 EXPORT_SYMBOL(ethtool_op_get_link);
 
-u32 ethtool_op_get_tx_csum(struct net_device *dev)
-{
-	return (dev->features & NETIF_F_ALL_CSUM) != 0;
-}
-EXPORT_SYMBOL(ethtool_op_get_tx_csum);
-
-int ethtool_op_set_tx_csum(struct net_device *dev, u32 data)
-{
-	if (data)
-		dev->features |= NETIF_F_IP_CSUM;
-	else
-		dev->features &= ~NETIF_F_IP_CSUM;
-
-	return 0;
-}
-EXPORT_SYMBOL(ethtool_op_set_tx_csum);
-
-int ethtool_op_set_tx_hw_csum(struct net_device *dev, u32 data)
-{
-	if (data)
-		dev->features |= NETIF_F_HW_CSUM;
-	else
-		dev->features &= ~NETIF_F_HW_CSUM;
-
-	return 0;
-}
-EXPORT_SYMBOL(ethtool_op_set_tx_hw_csum);
-
-int ethtool_op_set_tx_ipv6_csum(struct net_device *dev, u32 data)
-{
-	if (data)
-		dev->features |= NETIF_F_IP_CSUM | NETIF_F_IPV6_CSUM;
-	else
-		dev->features &= ~(NETIF_F_IP_CSUM | NETIF_F_IPV6_CSUM);
-
-	return 0;
-}
-EXPORT_SYMBOL(ethtool_op_set_tx_ipv6_csum);
-
-u32 ethtool_op_get_sg(struct net_device *dev)
-{
-	return (dev->features & NETIF_F_SG) != 0;
-}
-EXPORT_SYMBOL(ethtool_op_get_sg);
-
-int ethtool_op_set_sg(struct net_device *dev, u32 data)
-{
-	if (data)
-		dev->features |= NETIF_F_SG;
-	else
-		dev->features &= ~NETIF_F_SG;
-
-	return 0;
-}
-EXPORT_SYMBOL(ethtool_op_set_sg);
-
-u32 ethtool_op_get_tso(struct net_device *dev)
-{
-	return (dev->features & NETIF_F_TSO) != 0;
-}
-EXPORT_SYMBOL(ethtool_op_get_tso);
-
-int ethtool_op_set_tso(struct net_device *dev, u32 data)
-{
-	if (data)
-		dev->features |= NETIF_F_TSO;
-	else
-		dev->features &= ~NETIF_F_TSO;
-
-	return 0;
-}
-EXPORT_SYMBOL(ethtool_op_set_tso);
-
-u32 ethtool_op_get_ufo(struct net_device *dev)
-{
-	return (dev->features & NETIF_F_UFO) != 0;
-}
-EXPORT_SYMBOL(ethtool_op_get_ufo);
-
-int ethtool_op_set_ufo(struct net_device *dev, u32 data)
-{
-	if (data)
-		dev->features |= NETIF_F_UFO;
-	else
-		dev->features &= ~NETIF_F_UFO;
-	return 0;
-}
-EXPORT_SYMBOL(ethtool_op_set_ufo);
-
-/* the following list of flags are the same as their associated
- * NETIF_F_xxx values in include/linux/netdevice.h
- */
-static const u32 flags_dup_features =
-	(ETH_FLAG_LRO | ETH_FLAG_RXVLAN | ETH_FLAG_TXVLAN | ETH_FLAG_NTUPLE |
-	 ETH_FLAG_RXHASH);
-
-u32 ethtool_op_get_flags(struct net_device *dev)
-{
-	/* in the future, this function will probably contain additional
-	 * handling for flags which are not so easily handled
-	 * by a simple masking operation
-	 */
-
-	return dev->features & flags_dup_features;
-}
-EXPORT_SYMBOL(ethtool_op_get_flags);
-
-/* Check if device can enable (or disable) particular feature coded in "data"
- * argument. Flags "supported" describe features that can be toggled by device.
- * If feature can not be toggled, it state (enabled or disabled) must match
- * hardcoded device features state, otherwise flags are marked as invalid.
- */
-bool ethtool_invalid_flags(struct net_device *dev, u32 data, u32 supported)
-{
-	u32 features = dev->features & flags_dup_features;
-	/* "data" can contain only flags_dup_features bits,
-	 * see __ethtool_set_flags */
-
-	return (features & ~supported) != (data & ~supported);
-}
-EXPORT_SYMBOL(ethtool_invalid_flags);
-
-int ethtool_op_set_flags(struct net_device *dev, u32 data, u32 supported)
-{
-	if (ethtool_invalid_flags(dev, data, supported))
-		return -EINVAL;
-
-	dev->features = ((dev->features & ~flags_dup_features) |
-			 (data & flags_dup_features));
-	return 0;
-}
-EXPORT_SYMBOL(ethtool_op_set_flags);
-
 /* Handlers for each ethtool command */
 
 #define ETHTOOL_DEV_FEATURE_WORDS	1
 
-static void ethtool_get_features_compat(struct net_device *dev,
-	struct ethtool_get_features_block *features)
-{
-	if (!dev->ethtool_ops)
-		return;
-
-	/* getting RX checksum */
-	if (dev->ethtool_ops->get_rx_csum)
-		if (dev->ethtool_ops->get_rx_csum(dev))
-			features[0].active |= NETIF_F_RXCSUM;
-
-	/* mark legacy-changeable features */
-	if (dev->ethtool_ops->set_sg)
-		features[0].available |= NETIF_F_SG;
-	if (dev->ethtool_ops->set_tx_csum)
-		features[0].available |= NETIF_F_ALL_CSUM;
-	if (dev->ethtool_ops->set_tso)
-		features[0].available |= NETIF_F_ALL_TSO;
-	if (dev->ethtool_ops->set_rx_csum)
-		features[0].available |= NETIF_F_RXCSUM;
-	if (dev->ethtool_ops->set_flags)
-		features[0].available |= flags_dup_features;
-}
-
-static int ethtool_set_feature_compat(struct net_device *dev,
-	int (*legacy_set)(struct net_device *, u32),
-	struct ethtool_set_features_block *features, u32 mask)
-{
-	u32 do_set;
-
-	if (!legacy_set)
-		return 0;
-
-	if (!(features[0].valid & mask))
-		return 0;
-
-	features[0].valid &= ~mask;
-
-	do_set = !!(features[0].requested & mask);
-
-	if (legacy_set(dev, do_set) < 0)
-		netdev_info(dev,
-			"Legacy feature change (%s) failed for 0x%08x\n",
-			do_set ? "set" : "clear", mask);
-
-	return 1;
-}
-
-static int ethtool_set_flags_compat(struct net_device *dev,
-	int (*legacy_set)(struct net_device *, u32),
-	struct ethtool_set_features_block *features, u32 mask)
-{
-	u32 value;
-
-	if (!legacy_set)
-		return 0;
-
-	if (!(features[0].valid & mask))
-		return 0;
-
-	value = dev->features & ~features[0].valid;
-	value |= features[0].requested;
-
-	features[0].valid &= ~mask;
-
-	if (legacy_set(dev, value & mask) < 0)
-		netdev_info(dev, "Legacy flags change failed\n");
-
-	return 1;
-}
-
-static int ethtool_set_features_compat(struct net_device *dev,
-	struct ethtool_set_features_block *features)
-{
-	int compat;
-
-	if (!dev->ethtool_ops)
-		return 0;
-
-	compat  = ethtool_set_feature_compat(dev, dev->ethtool_ops->set_sg,
-		features, NETIF_F_SG);
-	compat |= ethtool_set_feature_compat(dev, dev->ethtool_ops->set_tx_csum,
-		features, NETIF_F_ALL_CSUM);
-	compat |= ethtool_set_feature_compat(dev, dev->ethtool_ops->set_tso,
-		features, NETIF_F_ALL_TSO);
-	compat |= ethtool_set_feature_compat(dev, dev->ethtool_ops->set_rx_csum,
-		features, NETIF_F_RXCSUM);
-	compat |= ethtool_set_flags_compat(dev, dev->ethtool_ops->set_flags,
-		features, flags_dup_features);
-
-	return compat;
-}
-
 static int ethtool_get_features(struct net_device *dev, void __user *useraddr)
 {
 	struct ethtool_gfeatures cmd = {
@@ -283,8 +57,6 @@ static int ethtool_get_features(struct net_device *dev, void __user *useraddr)
 	u32 __user *sizeaddr;
 	u32 copy_size;
 
-	ethtool_get_features_compat(dev, features);
-
 	sizeaddr = useraddr + offsetof(struct ethtool_gfeatures, size);
 	if (get_user(copy_size, sizeaddr))
 		return -EFAULT;
@@ -320,9 +92,6 @@ static int ethtool_set_features(struct net_device *dev, void __user *useraddr)
 	if (features[0].valid & ~NETIF_F_ETHTOOL_BITS)
 		return -EINVAL;
 
-	if (ethtool_set_features_compat(dev, features))
-		ret |= ETHTOOL_F_COMPAT;
-
 	if (features[0].valid & ~dev->hw_features) {
 		features[0].valid &= dev->hw_features;
 		ret |= ETHTOOL_F_UNSUPPORTED;
@@ -433,34 +202,6 @@ static u32 ethtool_get_feature_mask(u32 eth_cmd)
 	}
 }
 
-static void *__ethtool_get_one_feature_actor(struct net_device *dev, u32 ethcmd)
-{
-	const struct ethtool_ops *ops = dev->ethtool_ops;
-
-	if (!ops)
-		return NULL;
-
-	switch (ethcmd) {
-	case ETHTOOL_GTXCSUM:
-		return ops->get_tx_csum;
-	case ETHTOOL_GRXCSUM:
-		return ops->get_rx_csum;
-	case ETHTOOL_SSG:
-		return ops->get_sg;
-	case ETHTOOL_STSO:
-		return ops->get_tso;
-	case ETHTOOL_SUFO:
-		return ops->get_ufo;
-	default:
-		return NULL;
-	}
-}
-
-static u32 __ethtool_get_rx_csum_oldbug(struct net_device *dev)
-{
-	return !!(dev->features & NETIF_F_ALL_CSUM);
-}
-
 static int ethtool_get_one_feature(struct net_device *dev,
 	char __user *useraddr, u32 ethcmd)
 {
@@ -470,31 +211,11 @@ static int ethtool_get_one_feature(struct net_device *dev,
 		.data = !!(dev->features & mask),
 	};
 
-	/* compatibility with discrete get_ ops */
-	if (!(dev->hw_features & mask)) {
-		u32 (*actor)(struct net_device *);
-
-		actor = __ethtool_get_one_feature_actor(dev, ethcmd);
-
-		/* bug compatibility with old get_rx_csum */
-		if (ethcmd == ETHTOOL_GRXCSUM && !actor)
-			actor = __ethtool_get_rx_csum_oldbug;
-
-		if (actor)
-			edata.data = actor(dev);
-	}
-
 	if (copy_to_user(useraddr, &edata, sizeof(edata)))
 		return -EFAULT;
 	return 0;
 }
 
-static int __ethtool_set_tx_csum(struct net_device *dev, u32 data);
-static int __ethtool_set_rx_csum(struct net_device *dev, u32 data);
-static int __ethtool_set_sg(struct net_device *dev, u32 data);
-static int __ethtool_set_tso(struct net_device *dev, u32 data);
-static int __ethtool_set_ufo(struct net_device *dev, u32 data);
-
 static int ethtool_set_one_feature(struct net_device *dev,
 	void __user *useraddr, u32 ethcmd)
 {
@@ -506,56 +227,38 @@ static int ethtool_set_one_feature(struct net_device *dev,
 
 	mask = ethtool_get_feature_mask(ethcmd);
 	mask &= dev->hw_features;
-	if (mask) {
-		if (edata.data)
-			dev->wanted_features |= mask;
-		else
-			dev->wanted_features &= ~mask;
-
-		__netdev_update_features(dev);
-		return 0;
-	}
-
-	/* Driver is not converted to ndo_fix_features or does not
-	 * support changing this offload. In the latter case it won't
-	 * have corresponding ethtool_ops field set.
-	 *
-	 * Following part is to be removed after all drivers advertise
-	 * their changeable features in netdev->hw_features and stop
-	 * using discrete offload setting ops.
-	 */
-
-	switch (ethcmd) {
-	case ETHTOOL_STXCSUM:
-		return __ethtool_set_tx_csum(dev, edata.data);
-	case ETHTOOL_SRXCSUM:
-		return __ethtool_set_rx_csum(dev, edata.data);
-	case ETHTOOL_SSG:
-		return __ethtool_set_sg(dev, edata.data);
-	case ETHTOOL_STSO:
-		return __ethtool_set_tso(dev, edata.data);
-	case ETHTOOL_SUFO:
-		return __ethtool_set_ufo(dev, edata.data);
-	default:
+	if (!mask)
 		return -EOPNOTSUPP;
-	}
+
+	if (edata.data)
+		dev->wanted_features |= mask;
+	else
+		dev->wanted_features &= ~mask;
+
+	__netdev_update_features(dev);
+
+	return 0;
+}
+
+/* the following list of flags are the same as their associated
+ * NETIF_F_xxx values in include/linux/netdevice.h
+ */
+static const u32 flags_dup_features =
+	(ETH_FLAG_LRO | ETH_FLAG_RXVLAN | ETH_FLAG_TXVLAN | ETH_FLAG_NTUPLE |
+	 ETH_FLAG_RXHASH);
+
+static u32 __ethtool_get_flags(struct net_device *dev)
+{
+	return dev->features & flags_dup_features;
 }
 
-int __ethtool_set_flags(struct net_device *dev, u32 data)
+static int __ethtool_set_flags(struct net_device *dev, u32 data)
 {
 	u32 changed;
 
 	if (data & ~flags_dup_features)
 		return -EINVAL;
 
-	/* legacy set_flags() op */
-	if (dev->ethtool_ops->set_flags) {
-		if (unlikely(dev->hw_features & flags_dup_features))
-			netdev_warn(dev,
-				"driver BUG: mixed hw_features and set_flags()\n");
-		return dev->ethtool_ops->set_flags(dev, data);
-	}
-
 	/* allow changing only bits set in hw_features */
 	changed = (data ^ dev->features) & flags_dup_features;
 	if (changed & ~dev->hw_features)
@@ -1221,81 +924,6 @@ static int ethtool_set_pauseparam(struct net_device *dev, void __user *useraddr)
 	return dev->ethtool_ops->set_pauseparam(dev, &pauseparam);
 }
 
-static int __ethtool_set_sg(struct net_device *dev, u32 data)
-{
-	int err;
-
-	if (!dev->ethtool_ops->set_sg)
-		return -EOPNOTSUPP;
-
-	if (data && !(dev->features & NETIF_F_ALL_CSUM))
-		return -EINVAL;
-
-	if (!data && dev->ethtool_ops->set_tso) {
-		err = dev->ethtool_ops->set_tso(dev, 0);
-		if (err)
-			return err;
-	}
-
-	if (!data && dev->ethtool_ops->set_ufo) {
-		err = dev->ethtool_ops->set_ufo(dev, 0);
-		if (err)
-			return err;
-	}
-	return dev->ethtool_ops->set_sg(dev, data);
-}
-
-static int __ethtool_set_tx_csum(struct net_device *dev, u32 data)
-{
-	int err;
-
-	if (!dev->ethtool_ops->set_tx_csum)
-		return -EOPNOTSUPP;
-
-	if (!data && dev->ethtool_ops->set_sg) {
-		err = __ethtool_set_sg(dev, 0);
-		if (err)
-			return err;
-	}
-
-	return dev->ethtool_ops->set_tx_csum(dev, data);
-}
-
-static int __ethtool_set_rx_csum(struct net_device *dev, u32 data)
-{
-	if (!dev->ethtool_ops->set_rx_csum)
-		return -EOPNOTSUPP;
-
-	if (!data)
-		dev->features &= ~NETIF_F_GRO;
-
-	return dev->ethtool_ops->set_rx_csum(dev, data);
-}
-
-static int __ethtool_set_tso(struct net_device *dev, u32 data)
-{
-	if (!dev->ethtool_ops->set_tso)
-		return -EOPNOTSUPP;
-
-	if (data && !(dev->features & NETIF_F_SG))
-		return -EINVAL;
-
-	return dev->ethtool_ops->set_tso(dev, data);
-}
-
-static int __ethtool_set_ufo(struct net_device *dev, u32 data)
-{
-	if (!dev->ethtool_ops->set_ufo)
-		return -EOPNOTSUPP;
-	if (data && !(dev->features & NETIF_F_SG))
-		return -EINVAL;
-	if (data && !((dev->features & NETIF_F_GEN_CSUM) ||
-		(dev->features & (NETIF_F_IP_CSUM|NETIF_F_IPV6_CSUM))
-			== (NETIF_F_IP_CSUM|NETIF_F_IPV6_CSUM)))
-		return -EINVAL;
-	return dev->ethtool_ops->set_ufo(dev, data);
-}
-
 static int ethtool_self_test(struct net_device *dev, char __user *useraddr)
 {
 	struct ethtool_test test;
@@ -1761,9 +1389,7 @@ int dev_ethtool(struct net *net, struct ifreq *ifr)
 		break;
 	case ETHTOOL_GFLAGS:
 		rc = ethtool_get_value(dev, useraddr, ethcmd,
-				       (dev->ethtool_ops->get_flags ?
-					dev->ethtool_ops->get_flags :
-					ethtool_op_get_flags));
+					__ethtool_get_flags);
 		break;
 	case ETHTOOL_SFLAGS:
 		rc = ethtool_set_value(dev, useraddr, __ethtool_set_flags);
-- 
1.7.2.5


^ permalink raw reply related

* [RFT PATCH 4/9] net: introduce and use netdev_features_t for device features sets
From: Michał Mirosław @ 2011-06-20 19:14 UTC (permalink / raw)
  To: netdev; +Cc: David S. Miller, Ben Hutchings
In-Reply-To: <cover.1308596962.git.mirq-linux@rere.qmqm.pl>

The type and bits definitions are moved to separate header so that
linux/skbuff.h won't need to include linux/netdevice.h.

Signed-off-by: Michał Mirosław <mirq-linux@rere.qmqm.pl>
---
 drivers/net/8139cp.c                  |    2 +-
 drivers/net/bnx2.c                    |    6 +-
 drivers/net/bnx2x/bnx2x_cmn.c         |    5 +-
 drivers/net/bnx2x/bnx2x_cmn.h         |    5 +-
 drivers/net/bonding/bond_main.c       |    9 ++-
 drivers/net/cxgb4/cxgb4_main.c        |   12 ++--
 drivers/net/dm9000.c                  |    3 +-
 drivers/net/e1000/e1000_main.c        |    5 +-
 drivers/net/forcedeth.c               |    7 +-
 drivers/net/gianfar.h                 |    2 +-
 drivers/net/gianfar_ethtool.c         |    4 +-
 drivers/net/ibmveth.c                 |    6 +-
 drivers/net/ixgbe/ixgbe_ethtool.c     |    7 +-
 drivers/net/ixgbe/ixgbe_main.c        |    5 +-
 drivers/net/jme.c                     |    8 +-
 drivers/net/ksz884x.c                 |    3 +-
 drivers/net/mv643xx_eth.c             |    2 +-
 drivers/net/myri10ge/myri10ge.c       |    2 +-
 drivers/net/netxen/netxen_nic_main.c  |    6 +-
 drivers/net/pch_gbe/pch_gbe_main.c    |    5 +-
 drivers/net/qlcnic/qlcnic.h           |    5 +-
 drivers/net/qlcnic/qlcnic_hw.c        |    9 ++-
 drivers/net/qlcnic/qlcnic_main.c      |    2 +-
 drivers/net/r8169.c                   |    6 +-
 drivers/net/s2io.c                    |    4 +-
 drivers/net/sfc/efx.c                 |    2 +-
 drivers/net/sky2.c                    |    5 +-
 drivers/net/tg3.c                     |    7 +-
 drivers/net/usb/smsc75xx.c            |    3 +-
 drivers/net/usb/smsc95xx.c            |    3 +-
 drivers/net/vmxnet3/vmxnet3_ethtool.c |    4 +-
 drivers/net/vmxnet3/vmxnet3_int.h     |    2 +-
 drivers/net/vxge/vxge-main.c          |    9 ++-
 drivers/net/xen-netfront.c            |    8 ++-
 drivers/s390/net/qeth_l3_main.c       |    6 +-
 include/linux/netdev_features.h       |   98 ++++++++++++++++++++++++++
 include/linux/netdevice.h             |  125 ++++++---------------------------
 include/linux/skbuff.h                |    4 +-
 include/net/protocol.h                |    4 +-
 include/net/tcp.h                     |    3 +-
 include/net/udp.h                     |    3 +-
 net/8021q/vlan_dev.c                  |    3 +-
 net/bridge/br_if.c                    |    5 +-
 net/core/dev.c                        |   34 +++++----
 net/core/ethtool.c                    |    9 +--
 net/core/net-sysfs.c                  |    2 +-
 net/core/skbuff.c                     |    2 +-
 net/ipv4/af_inet.c                    |    3 +-
 net/ipv4/tcp.c                        |    2 +-
 net/ipv4/udp.c                        |    3 +-
 net/ipv6/af_inet6.c                   |    3 +-
 net/ipv6/udp.c                        |    2 +-
 52 files changed, 271 insertions(+), 213 deletions(-)

diff --git a/drivers/net/8139cp.c b/drivers/net/8139cp.c
index 73b10b0..a14bdf4 100644
--- a/drivers/net/8139cp.c
+++ b/drivers/net/8139cp.c
@@ -1416,7 +1416,7 @@ static void cp_set_msglevel(struct net_device *dev, u32 value)
 	cp->msg_enable = value;
 }
 
-static int cp_set_features(struct net_device *dev, u32 features)
+static int cp_set_features(struct net_device *dev, netdev_features_t features)
 {
 	struct cp_private *cp = netdev_priv(dev);
 	unsigned long flags;
diff --git a/drivers/net/bnx2.c b/drivers/net/bnx2.c
index 74580bb..35f0c8a 100644
--- a/drivers/net/bnx2.c
+++ b/drivers/net/bnx2.c
@@ -7502,8 +7502,8 @@ bnx2_set_phys_id(struct net_device *dev, enum ethtool_phys_id_state state)
 	return 0;
 }
 
-static u32
-bnx2_fix_features(struct net_device *dev, u32 features)
+static netdev_features_t
+bnx2_fix_features(struct net_device *dev, netdev_features_t features)
 {
 	struct bnx2 *bp = netdev_priv(dev);
 
@@ -7514,7 +7514,7 @@ bnx2_fix_features(struct net_device *dev, u32 features)
 }
 
 static int
-bnx2_set_features(struct net_device *dev, u32 features)
+bnx2_set_features(struct net_device *dev, netdev_features_t features)
 {
 	struct bnx2 *bp = netdev_priv(dev);
 
diff --git a/drivers/net/bnx2x/bnx2x_cmn.c b/drivers/net/bnx2x/bnx2x_cmn.c
index bb75560..c7da8ac 100644
--- a/drivers/net/bnx2x/bnx2x_cmn.c
+++ b/drivers/net/bnx2x/bnx2x_cmn.c
@@ -3177,7 +3177,8 @@ int bnx2x_change_mtu(struct net_device *dev, int new_mtu)
 	return bnx2x_reload_if_running(dev);
 }
 
-u32 bnx2x_fix_features(struct net_device *dev, u32 features)
+netdev_features_t bnx2x_fix_features(struct net_device *dev,
+	netdev_features_t features)
 {
 	struct bnx2x *bp = netdev_priv(dev);
 
@@ -3188,7 +3189,7 @@ u32 bnx2x_fix_features(struct net_device *dev, u32 features)
 	return features;
 }
 
-int bnx2x_set_features(struct net_device *dev, u32 features)
+int bnx2x_set_features(struct net_device *dev, netdev_features_t features)
 {
 	struct bnx2x *bp = netdev_priv(dev);
 	u32 flags = bp->flags;
diff --git a/drivers/net/bnx2x/bnx2x_cmn.h b/drivers/net/bnx2x/bnx2x_cmn.h
index c016e20..33095fb 100644
--- a/drivers/net/bnx2x/bnx2x_cmn.h
+++ b/drivers/net/bnx2x/bnx2x_cmn.h
@@ -519,8 +519,9 @@ void bnx2x_free_mem_bp(struct bnx2x *bp);
  */
 int bnx2x_change_mtu(struct net_device *dev, int new_mtu);
 
-u32 bnx2x_fix_features(struct net_device *dev, u32 features);
-int bnx2x_set_features(struct net_device *dev, u32 features);
+netdev_features_t bnx2x_fix_features(struct net_device *dev,
+	netdev_features_t features);
+int bnx2x_set_features(struct net_device *dev, netdev_features_t features);
 
 /**
  * bnx2x_tx_timeout - tx timeout netdev callback
diff --git a/drivers/net/bonding/bond_main.c b/drivers/net/bonding/bond_main.c
index 07e866d..f99c8b2 100644
--- a/drivers/net/bonding/bond_main.c
+++ b/drivers/net/bonding/bond_main.c
@@ -1375,11 +1375,12 @@ static int bond_sethwaddr(struct net_device *bond_dev,
 	return 0;
 }
 
-static u32 bond_fix_features(struct net_device *dev, u32 features)
+static netdev_features_t bond_fix_features(struct net_device *dev,
+	netdev_features_t features)
 {
 	struct slave *slave;
 	struct bonding *bond = netdev_priv(dev);
-	u32 mask;
+	netdev_features_t mask;
 	int i;
 
 	read_lock(&bond->lock);
@@ -1413,7 +1414,7 @@ static void bond_compute_features(struct bonding *bond)
 {
 	struct slave *slave;
 	struct net_device *bond_dev = bond->dev;
-	u32 vlan_features = BOND_VLAN_FEATURES;
+	netdev_features_t vlan_features = BOND_VLAN_FEATURES;
 	unsigned short max_hard_header_len = ETH_HLEN;
 	int i;
 
@@ -1951,7 +1952,7 @@ int bond_release(struct net_device *bond_dev, struct net_device *slave_dev)
 	struct bonding *bond = netdev_priv(bond_dev);
 	struct slave *slave, *oldcurrent;
 	struct sockaddr addr;
-	u32 old_features = bond_dev->features;
+	netdev_features_t old_features = bond_dev->features;
 
 	/* slave is not a slave or master is not master of this slave */
 	if (!(slave_dev->flags & IFF_SLAVE) ||
diff --git a/drivers/net/cxgb4/cxgb4_main.c b/drivers/net/cxgb4/cxgb4_main.c
index c9957b7..255f9f0 100644
--- a/drivers/net/cxgb4/cxgb4_main.c
+++ b/drivers/net/cxgb4/cxgb4_main.c
@@ -1854,10 +1854,10 @@ static int set_wol(struct net_device *dev, struct ethtool_wolinfo *wol)
 	return err;
 }
 
-static int cxgb_set_features(struct net_device *dev, u32 features)
+static int cxgb_set_features(struct net_device *dev, netdev_features_t features)
 {
 	const struct port_info *pi = netdev_priv(dev);
-	u32 changed = dev->features ^ features;
+	netdev_features_t changed = dev->features ^ features;
 	int err;
 
 	if (!(changed & NETIF_F_HW_VLAN_RX))
@@ -3536,7 +3536,7 @@ static int __devinit init_one(struct pci_dev *pdev,
 {
 	int func, i, err;
 	struct port_info *pi;
-	unsigned int highdma = 0;
+	bool highdma = false;
 	struct adapter *adapter = NULL;
 
 	printk_once(KERN_INFO "%s - version %s\n", DRV_DESC, DRV_VERSION);
@@ -3562,7 +3562,7 @@ static int __devinit init_one(struct pci_dev *pdev,
 	}
 
 	if (!pci_set_dma_mask(pdev, DMA_BIT_MASK(64))) {
-		highdma = NETIF_F_HIGHDMA;
+		highdma = true;
 		err = pci_set_consistent_dma_mask(pdev, DMA_BIT_MASK(64));
 		if (err) {
 			dev_err(&pdev->dev, "unable to obtain 64-bit DMA for "
@@ -3636,7 +3636,9 @@ static int __devinit init_one(struct pci_dev *pdev,
 			NETIF_F_IP_CSUM | NETIF_F_IPV6_CSUM |
 			NETIF_F_RXCSUM | NETIF_F_RXHASH |
 			NETIF_F_HW_VLAN_TX | NETIF_F_HW_VLAN_RX;
-		netdev->features |= netdev->hw_features | highdma;
+		if (highdma)
+			netdev->hw_features |= NETIF_F_HIGHDMA;
+		netdev->features |= netdev->hw_features;
 		netdev->vlan_features = netdev->features & VLAN_FEAT;
 
 		netdev->netdev_ops = &cxgb4_netdev_ops;
diff --git a/drivers/net/dm9000.c b/drivers/net/dm9000.c
index 8ef31dc..45bcefc 100644
--- a/drivers/net/dm9000.c
+++ b/drivers/net/dm9000.c
@@ -469,7 +469,8 @@ static int dm9000_nway_reset(struct net_device *dev)
 	return mii_nway_restart(&dm->mii);
 }
 
-static int dm9000_set_features(struct net_device *dev, u32 features)
+static int dm9000_set_features(struct net_device *dev,
+	netdev_features_t features)
 {
 	board_info_t *dm = to_dm9000_board(dev);
 	u32 changed = dev->features ^ features;
diff --git a/drivers/net/e1000/e1000_main.c b/drivers/net/e1000/e1000_main.c
index 188d99a..fab2ef6 100644
--- a/drivers/net/e1000/e1000_main.c
+++ b/drivers/net/e1000/e1000_main.c
@@ -797,10 +797,11 @@ static int e1000_is_need_ioport(struct pci_dev *pdev)
 	}
 }
 
-static int e1000_set_features(struct net_device *netdev, u32 features)
+static int e1000_set_features(struct net_device *netdev,
+	netdev_features_t features)
 {
 	struct e1000_adapter *adapter = netdev_priv(netdev);
-	u32 changed = features ^ netdev->features;
+	netdev_features_t changed = features ^ netdev->features;
 
 	if (!(changed & NETIF_F_RXCSUM))
 		return 0;
diff --git a/drivers/net/forcedeth.c b/drivers/net/forcedeth.c
index 537b695..c542766 100644
--- a/drivers/net/forcedeth.c
+++ b/drivers/net/forcedeth.c
@@ -4475,7 +4475,8 @@ static int nv_set_pauseparam(struct net_device *dev, struct ethtool_pauseparam*
 	return 0;
 }
 
-static u32 nv_fix_features(struct net_device *dev, u32 features)
+static netdev_features_t nv_fix_features(struct net_device *dev,
+	netdev_features_t features)
 {
 	/* vlan is dependent on rx checksum offload */
 	if (features & (NETIF_F_HW_VLAN_TX|NETIF_F_HW_VLAN_RX))
@@ -4484,11 +4485,11 @@ static u32 nv_fix_features(struct net_device *dev, u32 features)
 	return features;
 }
 
-static int nv_set_features(struct net_device *dev, u32 features)
+static int nv_set_features(struct net_device *dev, netdev_features_t features)
 {
 	struct fe_priv *np = netdev_priv(dev);
 	u8 __iomem *base = get_hwbase(dev);
-	u32 changed = dev->features ^ features;
+	netdev_features_t changed = dev->features ^ features;
 
 	if (changed & NETIF_F_RXCSUM) {
 		spin_lock_irq(&np->lock);
diff --git a/drivers/net/gianfar.h b/drivers/net/gianfar.h
index fc86f51..3b980a2 100644
--- a/drivers/net/gianfar.h
+++ b/drivers/net/gianfar.h
@@ -1153,7 +1153,7 @@ extern void gfar_phy_test(struct mii_bus *bus, struct phy_device *phydev,
 extern void gfar_configure_coalescing(struct gfar_private *priv,
 		unsigned long tx_mask, unsigned long rx_mask);
 void gfar_init_sysfs(struct net_device *dev);
-int gfar_set_features(struct net_device *dev, u32 features);
+int gfar_set_features(struct net_device *dev, netdev_features_t features);
 
 extern const struct ethtool_ops gfar_ethtool_ops;
 
diff --git a/drivers/net/gianfar_ethtool.c b/drivers/net/gianfar_ethtool.c
index 92d7ac0..4176b90 100644
--- a/drivers/net/gianfar_ethtool.c
+++ b/drivers/net/gianfar_ethtool.c
@@ -517,12 +517,12 @@ static int gfar_sringparam(struct net_device *dev, struct ethtool_ringparam *rva
 	return err;
 }
 
-int gfar_set_features(struct net_device *dev, u32 features)
+int gfar_set_features(struct net_device *dev, netdev_features_t features)
 {
 	struct gfar_private *priv = netdev_priv(dev);
 	unsigned long flags;
 	int err = 0, i = 0;
-	u32 changed = dev->features ^ features;
+	netdev_features_t changed = dev->features ^ features;
 
 	if (!(changed & NETIF_F_RXCSUM))
 		return 0;
diff --git a/drivers/net/ibmveth.c b/drivers/net/ibmveth.c
index 838c5b6..06514bc 100644
--- a/drivers/net/ibmveth.c
+++ b/drivers/net/ibmveth.c
@@ -730,7 +730,8 @@ static void netdev_get_drvinfo(struct net_device *dev,
 		sizeof(info->version) - 1);
 }
 
-static u32 ibmveth_fix_features(struct net_device *dev, u32 features)
+static netdev_features_t ibmveth_fix_features(struct net_device *dev,
+	netdev_features_t features)
 {
 	/*
 	 * Since the ibmveth firmware interface does not have the
@@ -824,7 +825,8 @@ static int ibmveth_set_csum_offload(struct net_device *dev, u32 data)
 	return rc1 ? rc1 : rc2;
 }
 
-static int ibmveth_set_features(struct net_device *dev, u32 features)
+static int ibmveth_set_features(struct net_device *dev,
+	netdev_features_t features)
 {
 	struct ibmveth_adapter *adapter = netdev_priv(dev);
 	int rx_csum = !!(features & NETIF_F_RXCSUM);
diff --git a/drivers/net/ixgbe/ixgbe_ethtool.c b/drivers/net/ixgbe/ixgbe_ethtool.c
index 38ee164..438c5b8 100644
--- a/drivers/net/ixgbe/ixgbe_ethtool.c
+++ b/drivers/net/ixgbe/ixgbe_ethtool.c
@@ -2188,7 +2188,8 @@ static int ixgbe_set_coalesce(struct net_device *netdev,
 	return 0;
 }
 
-u32 ixgbe_fix_features(struct net_device *netdev, u32 features)
+netdev_features_t ixgbe_fix_features(struct net_device *netdev,
+	netdev_features_t features)
 {
 	struct ixgbe_adapter *adapter = netdev_priv(netdev);
 
@@ -2211,10 +2212,10 @@ u32 ixgbe_fix_features(struct net_device *netdev, u32 features)
 	return features;
 }
 
-int ixgbe_set_features(struct net_device *netdev, u32 features)
+int ixgbe_set_features(struct net_device *netdev, netdev_features_t features)
 {
 	struct ixgbe_adapter *adapter = netdev_priv(netdev);
-	u32 changed = netdev->features ^ features;
+	netdev_features_t changed = netdev->features ^ features;
 	bool need_reset = !!(changed & NETIF_F_HW_VLAN_RX);
 
 	if (features & NETIF_F_RXCSUM)
diff --git a/drivers/net/ixgbe/ixgbe_main.c b/drivers/net/ixgbe/ixgbe_main.c
index 1a77310..c720710 100644
--- a/drivers/net/ixgbe/ixgbe_main.c
+++ b/drivers/net/ixgbe/ixgbe_main.c
@@ -7199,8 +7199,9 @@ static struct rtnl_link_stats64 *ixgbe_get_stats64(struct net_device *netdev,
 	return stats;
 }
 
-u32 ixgbe_fix_features(struct net_device *netdev, u32 features);
-int ixgbe_set_features(struct net_device *netdev, u32 features);
+netdev_features_t ixgbe_fix_features(struct net_device *netdev,
+	netdev_features_t features);
+int ixgbe_set_features(struct net_device *netdev, netdev_features_t features);
 
 static const struct net_device_ops ixgbe_netdev_ops = {
 	.ndo_open		= ixgbe_open,
diff --git a/drivers/net/jme.c b/drivers/net/jme.c
index b5b174a..44f230a 100644
--- a/drivers/net/jme.c
+++ b/drivers/net/jme.c
@@ -1917,7 +1917,7 @@ jme_map_tx_skb(struct jme_adapter *jme, struct sk_buff *skb, int idx)
 	struct jme_ring *txring = &(jme->txring[0]);
 	struct txdesc *txdesc = txring->desc, *ctxdesc;
 	struct jme_buffer_info *txbi = txring->bufinf, *ctxbi;
-	u8 hidma = jme->dev->features & NETIF_F_HIGHDMA;
+	u8 hidma = !!(jme->dev->features & NETIF_F_HIGHDMA);
 	int i, nr_frags = skb_shinfo(skb)->nr_frags;
 	int mask = jme->tx_ring_mask;
 	struct skb_frag_struct *frag;
@@ -2632,8 +2632,8 @@ jme_set_msglevel(struct net_device *netdev, u32 value)
 	jme->msg_enable = value;
 }
 
-static u32
-jme_fix_features(struct net_device *netdev, u32 features)
+static netdev_features_t
+jme_fix_features(struct net_device *netdev, netdev_features_t features)
 {
 	if (netdev->mtu > 1900)
 		features &= ~(NETIF_F_ALL_TSO | NETIF_F_ALL_CSUM);
@@ -2641,7 +2641,7 @@ jme_fix_features(struct net_device *netdev, u32 features)
 }
 
 static int
-jme_set_features(struct net_device *netdev, u32 features)
+jme_set_features(struct net_device *netdev, netdev_features_t features)
 {
 	struct jme_adapter *jme = netdev_priv(netdev);
 
diff --git a/drivers/net/ksz884x.c b/drivers/net/ksz884x.c
index 2ac6c6c..9e2f8c9 100644
--- a/drivers/net/ksz884x.c
+++ b/drivers/net/ksz884x.c
@@ -6590,7 +6590,8 @@ static void netdev_get_ethtool_stats(struct net_device *dev,
  *
  * Return 0 if successful; otherwise an error code.
  */
-static int netdev_set_features(struct net_device *dev, u32 features)
+static int netdev_set_features(struct net_device *dev,
+	netdev_features_t features)
 {
 	struct dev_priv *priv = netdev_priv(dev);
 	struct dev_info *hw_priv = priv->adapter;
diff --git a/drivers/net/mv643xx_eth.c b/drivers/net/mv643xx_eth.c
index a5d9b1c..39ba830 100644
--- a/drivers/net/mv643xx_eth.c
+++ b/drivers/net/mv643xx_eth.c
@@ -1577,7 +1577,7 @@ mv643xx_eth_set_ringparam(struct net_device *dev, struct ethtool_ringparam *er)
 
 
 static int
-mv643xx_eth_set_features(struct net_device *dev, u32 features)
+mv643xx_eth_set_features(struct net_device *dev, netdev_features_t features)
 {
 	struct mv643xx_eth_private *mp = netdev_priv(dev);
 	u32 rx_csum = features & NETIF_F_RXCSUM;
diff --git a/drivers/net/myri10ge/myri10ge.c b/drivers/net/myri10ge/myri10ge.c
index 04e10f4..6d0be83 100644
--- a/drivers/net/myri10ge/myri10ge.c
+++ b/drivers/net/myri10ge/myri10ge.c
@@ -1489,7 +1489,7 @@ myri10ge_clean_rx_done(struct myri10ge_slice_state *ss, int budget)
 	 * access to avoid theoretical race condition with functions that
 	 * change NETIF_F_LRO flag at runtime.
 	 */
-	bool lro_enabled = ACCESS_ONCE(mgp->dev->features) & NETIF_F_LRO;
+	bool lro_enabled = !!(ACCESS_ONCE(mgp->dev->features) & NETIF_F_LRO);
 
 	while (rx_done->entry[idx].length != 0 && work_done < budget) {
 		length = ntohs(rx_done->entry[idx].length);
diff --git a/drivers/net/netxen/netxen_nic_main.c b/drivers/net/netxen/netxen_nic_main.c
index 684cace..75c4405 100644
--- a/drivers/net/netxen/netxen_nic_main.c
+++ b/drivers/net/netxen/netxen_nic_main.c
@@ -486,7 +486,8 @@ static void netxen_set_multicast_list(struct net_device *dev)
 	adapter->set_multi(dev);
 }
 
-static u32 netxen_fix_features(struct net_device *dev, u32 features)
+static netdev_features_t netxen_fix_features(struct net_device *dev,
+	netdev_features_t features)
 {
 	if (!(features & NETIF_F_RXCSUM)) {
 		netdev_info(dev, "disabling LRO as RXCSUM is off\n");
@@ -497,7 +498,8 @@ static u32 netxen_fix_features(struct net_device *dev, u32 features)
 	return features;
 }
 
-static int netxen_set_features(struct net_device *dev, u32 features)
+static int netxen_set_features(struct net_device *dev,
+	netdev_features_t features)
 {
 	struct netxen_adapter *adapter = netdev_priv(dev);
 	int hw_lro;
diff --git a/drivers/net/pch_gbe/pch_gbe_main.c b/drivers/net/pch_gbe/pch_gbe_main.c
index eac3c5c..3684281 100644
--- a/drivers/net/pch_gbe/pch_gbe_main.c
+++ b/drivers/net/pch_gbe/pch_gbe_main.c
@@ -2040,10 +2040,11 @@ static int pch_gbe_change_mtu(struct net_device *netdev, int new_mtu)
  * Returns
  *	0:		HW state updated successfully
  */
-static int pch_gbe_set_features(struct net_device *netdev, u32 features)
+static int pch_gbe_set_features(struct net_device *netdev,
+	netdev_features_t features)
 {
 	struct pch_gbe_adapter *adapter = netdev_priv(netdev);
-	u32 changed = features ^ netdev->features;
+	netdev_features_t changed = features ^ netdev->features;
 
 	if (!(changed & NETIF_F_RXCSUM))
 		return 0;
diff --git a/drivers/net/qlcnic/qlcnic.h b/drivers/net/qlcnic/qlcnic.h
index 480ef5c..49ed30d 100644
--- a/drivers/net/qlcnic/qlcnic.h
+++ b/drivers/net/qlcnic/qlcnic.h
@@ -1420,8 +1420,9 @@ void qlcnic_advert_link_change(struct qlcnic_adapter *adapter, int linkup);
 
 int qlcnic_fw_cmd_set_mtu(struct qlcnic_adapter *adapter, int mtu);
 int qlcnic_change_mtu(struct net_device *netdev, int new_mtu);
-u32 qlcnic_fix_features(struct net_device *netdev, u32 features);
-int qlcnic_set_features(struct net_device *netdev, u32 features);
+netdev_features_t qlcnic_fix_features(struct net_device *netdev,
+	netdev_features_t features);
+int qlcnic_set_features(struct net_device *netdev, netdev_features_t features);
 int qlcnic_config_hw_lro(struct qlcnic_adapter *adapter, int enable);
 int qlcnic_config_bridged_mode(struct qlcnic_adapter *adapter, u32 enable);
 int qlcnic_send_lro_cleanup(struct qlcnic_adapter *adapter);
diff --git a/drivers/net/qlcnic/qlcnic_hw.c b/drivers/net/qlcnic/qlcnic_hw.c
index e965661..d0cc78e 100644
--- a/drivers/net/qlcnic/qlcnic_hw.c
+++ b/drivers/net/qlcnic/qlcnic_hw.c
@@ -760,12 +760,13 @@ int qlcnic_change_mtu(struct net_device *netdev, int mtu)
 }
 
 
-u32 qlcnic_fix_features(struct net_device *netdev, u32 features)
+netdev_features_t qlcnic_fix_features(struct net_device *netdev,
+	netdev_features_t features)
 {
 	struct qlcnic_adapter *adapter = netdev_priv(netdev);
 
 	if ((adapter->flags & QLCNIC_ESWITCH_ENABLED)) {
-		u32 changed = features ^ netdev->features;
+		netdev_features_t changed = features ^ netdev->features;
 		features ^= changed & (NETIF_F_ALL_CSUM | NETIF_F_RXCSUM);
 	}
 
@@ -776,10 +777,10 @@ u32 qlcnic_fix_features(struct net_device *netdev, u32 features)
 }
 
 
-int qlcnic_set_features(struct net_device *netdev, u32 features)
+int qlcnic_set_features(struct net_device *netdev, netdev_features_t features)
 {
 	struct qlcnic_adapter *adapter = netdev_priv(netdev);
-	u32 changed = netdev->features ^ features;
+	netdev_features_t changed = netdev->features ^ features;
 	int hw_lro = (features & NETIF_F_LRO) ? QLCNIC_LRO_ENABLED : 0;
 
 	if (!(changed & NETIF_F_LRO))
diff --git a/drivers/net/qlcnic/qlcnic_main.c b/drivers/net/qlcnic/qlcnic_main.c
index 3ab7d2c..979bca3 100644
--- a/drivers/net/qlcnic/qlcnic_main.c
+++ b/drivers/net/qlcnic/qlcnic_main.c
@@ -781,7 +781,7 @@ qlcnic_set_netdev_features(struct qlcnic_adapter *adapter,
 		struct qlcnic_esw_func_cfg *esw_cfg)
 {
 	struct net_device *netdev = adapter->netdev;
-	unsigned long features, vlan_features;
+	netdev_features_t features, vlan_features;
 
 	features = (NETIF_F_SG | NETIF_F_IP_CSUM | NETIF_F_RXCSUM |
 			NETIF_F_IPV6_CSUM | NETIF_F_GRO);
diff --git a/drivers/net/r8169.c b/drivers/net/r8169.c
index bc5bb37..78184ac 100644
--- a/drivers/net/r8169.c
+++ b/drivers/net/r8169.c
@@ -1384,7 +1384,8 @@ static int rtl8169_set_settings(struct net_device *dev, struct ethtool_cmd *cmd)
 	return ret;
 }
 
-static u32 rtl8169_fix_features(struct net_device *dev, u32 features)
+static netdev_features_t rtl8169_fix_features(struct net_device *dev,
+	netdev_features_t features)
 {
 	if (dev->mtu > TD_MSS_MAX)
 		features &= ~NETIF_F_ALL_TSO;
@@ -1392,7 +1393,8 @@ static u32 rtl8169_fix_features(struct net_device *dev, u32 features)
 	return features;
 }
 
-static int rtl8169_set_features(struct net_device *dev, u32 features)
+static int rtl8169_set_features(struct net_device *dev,
+	netdev_features_t features)
 {
 	struct rtl8169_private *tp = netdev_priv(dev);
 	void __iomem *ioaddr = tp->mmio_addr;
diff --git a/drivers/net/s2io.c b/drivers/net/s2io.c
index df0d2c8..698fbfa 100644
--- a/drivers/net/s2io.c
+++ b/drivers/net/s2io.c
@@ -6670,10 +6670,10 @@ static void s2io_ethtool_get_strings(struct net_device *dev,
 	}
 }
 
-static int s2io_set_features(struct net_device *dev, u32 features)
+static int s2io_set_features(struct net_device *dev, netdev_features_t features)
 {
 	struct s2io_nic *sp = netdev_priv(dev);
-	u32 changed = (features ^ dev->features) & NETIF_F_LRO;
+	netdev_features_t changed = (features ^ dev->features) & NETIF_F_LRO;
 
 	if (changed && netif_running(dev)) {
 		int rc;
diff --git a/drivers/net/sfc/efx.c b/drivers/net/sfc/efx.c
index c914729..ca869c0 100644
--- a/drivers/net/sfc/efx.c
+++ b/drivers/net/sfc/efx.c
@@ -1883,7 +1883,7 @@ static void efx_set_multicast_list(struct net_device *net_dev)
 	/* Otherwise efx_start_port() will do this */
 }
 
-static int efx_set_features(struct net_device *net_dev, u32 data)
+static int efx_set_features(struct net_device *net_dev, netdev_features_t data)
 {
 	struct efx_nic *efx = netdev_priv(net_dev);
 
diff --git a/drivers/net/sky2.c b/drivers/net/sky2.c
index d252cb1..6068f49 100644
--- a/drivers/net/sky2.c
+++ b/drivers/net/sky2.c
@@ -4168,7 +4168,8 @@ static int sky2_set_eeprom(struct net_device *dev, struct ethtool_eeprom *eeprom
 	return sky2_vpd_write(sky2->hw, cap, data, eeprom->offset, eeprom->len);
 }
 
-static u32 sky2_fix_features(struct net_device *dev, u32 features)
+static netdev_features_t sky2_fix_features(struct net_device *dev,
+	netdev_features_t features)
 {
 	const struct sky2_port *sky2 = netdev_priv(dev);
 	const struct sky2_hw *hw = sky2->hw;
@@ -4182,7 +4183,7 @@ static u32 sky2_fix_features(struct net_device *dev, u32 features)
 	return features;
 }
 
-static int sky2_set_features(struct net_device *dev, u32 features)
+static int sky2_set_features(struct net_device *dev, netdev_features_t features)
 {
 	struct sky2_port *sky2 = netdev_priv(dev);
 	u32 changed = dev->features ^ features;
diff --git a/drivers/net/tg3.c b/drivers/net/tg3.c
index 97cd02d..67692b5 100644
--- a/drivers/net/tg3.c
+++ b/drivers/net/tg3.c
@@ -6186,7 +6186,8 @@ static void tg3_set_loopback(struct net_device *dev, u32 features)
 	}
 }
 
-static u32 tg3_fix_features(struct net_device *dev, u32 features)
+static netdev_features_t tg3_fix_features(struct net_device *dev,
+	netdev_features_t features)
 {
 	struct tg3 *tp = netdev_priv(dev);
 
@@ -6196,9 +6197,9 @@ static u32 tg3_fix_features(struct net_device *dev, u32 features)
 	return features;
 }
 
-static int tg3_set_features(struct net_device *dev, u32 features)
+static int tg3_set_features(struct net_device *dev, netdev_features_t features)
 {
-	u32 changed = dev->features ^ features;
+	netdev_features_t changed = dev->features ^ features;
 
 	if ((changed & NETIF_F_LOOPBACK) && netif_running(dev))
 		tg3_set_loopback(dev, features);
diff --git a/drivers/net/usb/smsc75xx.c b/drivers/net/usb/smsc75xx.c
index 15b3d68..f59b51f 100644
--- a/drivers/net/usb/smsc75xx.c
+++ b/drivers/net/usb/smsc75xx.c
@@ -727,7 +727,8 @@ static int smsc75xx_change_mtu(struct net_device *netdev, int new_mtu)
 }
 
 /* Enable or disable Rx checksum offload engine */
-static int smsc75xx_set_features(struct net_device *netdev, u32 features)
+static int smsc75xx_set_features(struct net_device *netdev,
+	netdev_features_t features)
 {
 	struct usbnet *dev = netdev_priv(netdev);
 	struct smsc75xx_priv *pdata = (struct smsc75xx_priv *)(dev->data[0]);
diff --git a/drivers/net/usb/smsc95xx.c b/drivers/net/usb/smsc95xx.c
index f74f3ce..071a5cf 100644
--- a/drivers/net/usb/smsc95xx.c
+++ b/drivers/net/usb/smsc95xx.c
@@ -516,7 +516,8 @@ static void smsc95xx_status(struct usbnet *dev, struct urb *urb)
 }
 
 /* Enable or disable Tx & Rx checksum offload engines */
-static int smsc95xx_set_features(struct net_device *netdev, u32 features)
+static int smsc95xx_set_features(struct net_device *netdev,
+	netdev_features_t features)
 {
 	struct usbnet *dev = netdev_priv(netdev);
 	u32 read_buf;
diff --git a/drivers/net/vmxnet3/vmxnet3_ethtool.c b/drivers/net/vmxnet3/vmxnet3_ethtool.c
index bba7c15..704c527 100644
--- a/drivers/net/vmxnet3/vmxnet3_ethtool.c
+++ b/drivers/net/vmxnet3/vmxnet3_ethtool.c
@@ -262,11 +262,11 @@ vmxnet3_get_strings(struct net_device *netdev, u32 stringset, u8 *buf)
 	}
 }
 
-int vmxnet3_set_features(struct net_device *netdev, u32 features)
+int vmxnet3_set_features(struct net_device *netdev, netdev_features_t features)
 {
 	struct vmxnet3_adapter *adapter = netdev_priv(netdev);
 	unsigned long flags;
-	u32 changed = features ^ netdev->features;
+	netdev_features_t changed = features ^ netdev->features;
 
 	if (changed & (NETIF_F_RXCSUM|NETIF_F_LRO)) {
 		if (features & NETIF_F_RXCSUM)
diff --git a/drivers/net/vmxnet3/vmxnet3_int.h b/drivers/net/vmxnet3/vmxnet3_int.h
index 0e567c24..35e2b9b 100644
--- a/drivers/net/vmxnet3/vmxnet3_int.h
+++ b/drivers/net/vmxnet3/vmxnet3_int.h
@@ -399,7 +399,7 @@ void
 vmxnet3_rq_destroy_all(struct vmxnet3_adapter *adapter);
 
 int
-vmxnet3_set_features(struct net_device *netdev, u32 features);
+vmxnet3_set_features(struct net_device *netdev, netdev_features_t features);
 
 int
 vmxnet3_create_queues(struct vmxnet3_adapter *adapter,
diff --git a/drivers/net/vxge/vxge-main.c b/drivers/net/vxge/vxge-main.c
index e658edd..7d3040c 100644
--- a/drivers/net/vxge/vxge-main.c
+++ b/drivers/net/vxge/vxge-main.c
@@ -2662,9 +2662,10 @@ static void vxge_poll_vp_lockup(unsigned long data)
 	mod_timer(&vdev->vp_lockup_timer, jiffies + HZ / 1000);
 }
 
-static u32 vxge_fix_features(struct net_device *dev, u32 features)
+static netdev_features_t vxge_fix_features(struct net_device *dev,
+	netdev_features_t features)
 {
-	u32 changed = dev->features ^ features;
+	netdev_features_t changed = dev->features ^ features;
 
 	/* Enabling RTH requires some of the logic in vxge_device_register and a
 	 * vpath reset.  Due to these restrictions, only allow modification
@@ -2676,10 +2677,10 @@ static u32 vxge_fix_features(struct net_device *dev, u32 features)
 	return features;
 }
 
-static int vxge_set_features(struct net_device *dev, u32 features)
+static int vxge_set_features(struct net_device *dev, netdev_features_t features)
 {
 	struct vxgedev *vdev = netdev_priv(dev);
-	u32 changed = dev->features ^ features;
+	netdev_features_t changed = dev->features ^ features;
 
 	if (!(changed & NETIF_F_RXHASH))
 		return 0;
diff --git a/drivers/net/xen-netfront.c b/drivers/net/xen-netfront.c
index d29365a..bfb5cf9 100644
--- a/drivers/net/xen-netfront.c
+++ b/drivers/net/xen-netfront.c
@@ -193,7 +193,7 @@ static void xennet_sysfs_delif(struct net_device *netdev);
 
 static int xennet_can_sg(struct net_device *dev)
 {
-	return dev->features & NETIF_F_SG;
+	return !!(dev->features & NETIF_F_SG);
 }
 
 
@@ -1140,7 +1140,8 @@ static void xennet_uninit(struct net_device *dev)
 	gnttab_free_grant_references(np->gref_rx_head);
 }
 
-static u32 xennet_fix_features(struct net_device *dev, u32 features)
+static netdev_features_t xennet_fix_features(struct net_device *dev,
+	netdev_features_t features)
 {
 	struct netfront_info *np = netdev_priv(dev);
 	int val;
@@ -1166,7 +1167,8 @@ static u32 xennet_fix_features(struct net_device *dev, u32 features)
 	return features;
 }
 
-static int xennet_set_features(struct net_device *dev, u32 features)
+static int xennet_set_features(struct net_device *dev,
+	netdev_features_t features)
 {
 	if (!(features & NETIF_F_SG) && dev->mtu > ETH_DATA_LEN) {
 		netdev_info(dev, "Reducing MTU because no SG offload");
diff --git a/drivers/s390/net/qeth_l3_main.c b/drivers/s390/net/qeth_l3_main.c
index fd69da3..3225a4d 100644
--- a/drivers/s390/net/qeth_l3_main.c
+++ b/drivers/s390/net/qeth_l3_main.c
@@ -3148,7 +3148,8 @@ static int qeth_l3_stop(struct net_device *dev)
 	return 0;
 }
 
-static u32 qeth_l3_fix_features(struct net_device *dev, u32 features)
+static netdev_features_t qeth_l3_fix_features(struct net_device *dev,
+	netdev_features_t features)
 {
 	struct qeth_card *card = dev->ml_priv;
 
@@ -3162,7 +3163,8 @@ static u32 qeth_l3_fix_features(struct net_device *dev, u32 features)
 	return features;
 }
 
-static int qeth_l3_set_features(struct net_device *dev, u32 features)
+static int qeth_l3_set_features(struct net_device *dev,
+	netdev_features_t features)
 {
 	struct qeth_card *card = dev->ml_priv;
 	u32 changed = dev->features ^ features;
diff --git a/include/linux/netdev_features.h b/include/linux/netdev_features.h
new file mode 100644
index 0000000..d36bdcd
--- /dev/null
+++ b/include/linux/netdev_features.h
@@ -0,0 +1,98 @@
+/*
+ * Network device features.
+ *
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version
+ * 2 of the License, or (at your option) any later version.
+ */
+#ifndef _LINUX_NETDEV_FEATURES_H
+#define _LINUX_NETDEV_FEATURES_H
+
+#include <linux/types.h>
+
+typedef u32 netdev_features_t;
+
+#define NETIF_F_SG		1	/* Scatter/gather IO. */
+#define NETIF_F_IP_CSUM		2	/* Can checksum TCP/UDP over IPv4. */
+#define NETIF_F_NO_CSUM		4	/* Does not require checksum. F.e. loopack. */
+#define NETIF_F_HW_CSUM		8	/* Can checksum all the packets. */
+#define NETIF_F_IPV6_CSUM	16	/* Can checksum TCP/UDP over IPV6 */
+#define NETIF_F_HIGHDMA		32	/* Can DMA to high memory. */
+#define NETIF_F_FRAGLIST	64	/* Scatter/gather IO. */
+#define NETIF_F_HW_VLAN_TX	128	/* Transmit VLAN hw acceleration */
+#define NETIF_F_HW_VLAN_RX	256	/* Receive VLAN hw acceleration */
+#define NETIF_F_HW_VLAN_FILTER	512	/* Receive filtering on VLAN */
+#define NETIF_F_VLAN_CHALLENGED	1024	/* Device cannot handle VLAN packets */
+#define NETIF_F_GSO		2048	/* Enable software GSO. */
+#define NETIF_F_LLTX		4096	/* LockLess TX - deprecated. Please */
+					/* do not use LLTX in new drivers */
+#define NETIF_F_NETNS_LOCAL	8192	/* Does not change network namespaces */
+#define NETIF_F_GRO		16384	/* Generic receive offload */
+#define NETIF_F_LRO		32768	/* large receive offload */
+
+/* the GSO_MASK reserves bits 16 through 23 */
+#define NETIF_F_FCOE_CRC	(1 << 24) /* FCoE CRC32 */
+#define NETIF_F_SCTP_CSUM	(1 << 25) /* SCTP checksum offload */
+#define NETIF_F_FCOE_MTU	(1 << 26) /* Supports max FCoE MTU, 2158 bytes*/
+#define NETIF_F_NTUPLE		(1 << 27) /* N-tuple filters supported */
+#define NETIF_F_RXHASH		(1 << 28) /* Receive hashing offload */
+#define NETIF_F_RXCSUM		(1 << 29) /* Receive checksumming offload */
+#define NETIF_F_NOCACHE_COPY	(1 << 30) /* Use no-cache copyfromuser */
+#define NETIF_F_LOOPBACK	(1 << 31) /* Enable loopback */
+
+	/* Segmentation offload features */
+#define NETIF_F_GSO_SHIFT	16
+#define NETIF_F_GSO_MASK	0x00ff0000
+#define NETIF_F_TSO		(SKB_GSO_TCPV4 << NETIF_F_GSO_SHIFT)
+#define NETIF_F_UFO		(SKB_GSO_UDP << NETIF_F_GSO_SHIFT)
+#define NETIF_F_GSO_ROBUST	(SKB_GSO_DODGY << NETIF_F_GSO_SHIFT)
+#define NETIF_F_TSO_ECN		(SKB_GSO_TCP_ECN << NETIF_F_GSO_SHIFT)
+#define NETIF_F_TSO6		(SKB_GSO_TCPV6 << NETIF_F_GSO_SHIFT)
+#define NETIF_F_FSO		(SKB_GSO_FCOE << NETIF_F_GSO_SHIFT)
+
+	/* Features valid for ethtool to change */
+	/* = all defined minus driver/device-class-related */
+#define NETIF_F_NEVER_CHANGE	(NETIF_F_VLAN_CHALLENGED | \
+				  NETIF_F_LLTX | NETIF_F_NETNS_LOCAL)
+#define NETIF_F_ETHTOOL_BITS	(0xff3fffff & ~NETIF_F_NEVER_CHANGE)
+
+	/* List of features with software fallbacks. */
+#define NETIF_F_GSO_SOFTWARE	(NETIF_F_TSO | NETIF_F_TSO_ECN | \
+				 NETIF_F_TSO6 | NETIF_F_UFO)
+
+
+#define NETIF_F_GEN_CSUM	(NETIF_F_NO_CSUM | NETIF_F_HW_CSUM)
+#define NETIF_F_V4_CSUM		(NETIF_F_GEN_CSUM | NETIF_F_IP_CSUM)
+#define NETIF_F_V6_CSUM		(NETIF_F_GEN_CSUM | NETIF_F_IPV6_CSUM)
+#define NETIF_F_ALL_CSUM	(NETIF_F_V4_CSUM | NETIF_F_V6_CSUM)
+
+#define NETIF_F_ALL_TSO 	(NETIF_F_TSO | NETIF_F_TSO6 | NETIF_F_TSO_ECN)
+
+#define NETIF_F_ALL_FCOE	(NETIF_F_FCOE_CRC | NETIF_F_FCOE_MTU | \
+				 NETIF_F_FSO)
+
+#define NETIF_F_ALL_TX_OFFLOADS	(NETIF_F_ALL_CSUM | NETIF_F_SG | \
+				 NETIF_F_FRAGLIST | NETIF_F_ALL_TSO | \
+				 NETIF_F_HIGHDMA | \
+				 NETIF_F_SCTP_CSUM | \
+				 NETIF_F_ALL_FCOE)
+
+	/*
+	 * If one device supports one of these features, then enable them
+	 * for all in netdev_increment_features.
+	 */
+#define NETIF_F_ONE_FOR_ALL	(NETIF_F_GSO_SOFTWARE | NETIF_F_GSO_ROBUST | \
+				 NETIF_F_SG | NETIF_F_HIGHDMA |		\
+				 NETIF_F_FRAGLIST | NETIF_F_VLAN_CHALLENGED)
+	/*
+	 * If one device doesn't support one of these features, then disable it
+	 * for all in netdev_increment_features.
+	 */
+#define NETIF_F_ALL_FOR_ALL	(NETIF_F_NOCACHE_COPY | NETIF_F_FSO)
+
+	/* changeable features with no special hardware requirements */
+#define NETIF_F_SOFT_FEATURES	(NETIF_F_GSO | NETIF_F_GRO)
+
+#endif	/* _LINUX_NETDEV_FEATURES_H */
diff --git a/include/linux/netdevice.h b/include/linux/netdevice.h
index 3482ee9..5e0e086 100644
--- a/include/linux/netdevice.h
+++ b/include/linux/netdevice.h
@@ -52,6 +52,8 @@
 #include <net/dcbnl.h>
 #endif
 
+#include <linux/netdev_features.h>
+
 struct vlan_group;
 struct netpoll_info;
 struct phy_device;
@@ -877,12 +879,12 @@ struct netdev_tc_txq {
  *	Called to release previously enslaved netdev.
  *
  *      Feature/offload setting functions.
- * u32 (*ndo_fix_features)(struct net_device *dev, u32 features);
+ * netdev_features_t (*ndo_fix_features)(struct net_device *dev, netdev_features_t features);
  *	Adjusts the requested feature flags according to device-specific
  *	constraints, and returns the resulting flags. Must not modify
  *	the device state.
  *
- * int (*ndo_set_features)(struct net_device *dev, u32 features);
+ * int (*ndo_set_features)(struct net_device *dev, netdev_features_t features);
  *	Called to update device configuration to new features. Passed
  *	feature set might be less than what was returned by ndo_fix_features()).
  *	Must return >0 or -errno if it changed dev->features itself.
@@ -974,10 +976,10 @@ struct net_device_ops {
 						 struct net_device *slave_dev);
 	int			(*ndo_del_slave)(struct net_device *dev,
 						 struct net_device *slave_dev);
-	u32			(*ndo_fix_features)(struct net_device *dev,
-						    u32 features);
+	netdev_features_t	(*ndo_fix_features)(struct net_device *dev,
+						    netdev_features_t features);
 	int			(*ndo_set_features)(struct net_device *dev,
-						    u32 features);
+						    netdev_features_t features);
 };
 
 /*
@@ -1027,97 +1029,13 @@ struct net_device {
 	struct list_head	unreg_list;
 
 	/* currently active device features */
-	u32			features;
+	netdev_features_t	features;
 	/* user-changeable features */
-	u32			hw_features;
+	netdev_features_t	hw_features;
 	/* user-requested features */
-	u32			wanted_features;
+	netdev_features_t	wanted_features;
 	/* mask of features inheritable by VLAN devices */
-	u32			vlan_features;
-
-	/* Net device feature bits; if you change something,
-	 * also update netdev_features_strings[] in ethtool.c */
-
-#define NETIF_F_SG		1	/* Scatter/gather IO. */
-#define NETIF_F_IP_CSUM		2	/* Can checksum TCP/UDP over IPv4. */
-#define NETIF_F_NO_CSUM		4	/* Does not require checksum. F.e. loopack. */
-#define NETIF_F_HW_CSUM		8	/* Can checksum all the packets. */
-#define NETIF_F_IPV6_CSUM	16	/* Can checksum TCP/UDP over IPV6 */
-#define NETIF_F_HIGHDMA		32	/* Can DMA to high memory. */
-#define NETIF_F_FRAGLIST	64	/* Scatter/gather IO. */
-#define NETIF_F_HW_VLAN_TX	128	/* Transmit VLAN hw acceleration */
-#define NETIF_F_HW_VLAN_RX	256	/* Receive VLAN hw acceleration */
-#define NETIF_F_HW_VLAN_FILTER	512	/* Receive filtering on VLAN */
-#define NETIF_F_VLAN_CHALLENGED	1024	/* Device cannot handle VLAN packets */
-#define NETIF_F_GSO		2048	/* Enable software GSO. */
-#define NETIF_F_LLTX		4096	/* LockLess TX - deprecated. Please */
-					/* do not use LLTX in new drivers */
-#define NETIF_F_NETNS_LOCAL	8192	/* Does not change network namespaces */
-#define NETIF_F_GRO		16384	/* Generic receive offload */
-#define NETIF_F_LRO		32768	/* large receive offload */
-
-/* the GSO_MASK reserves bits 16 through 23 */
-#define NETIF_F_FCOE_CRC	(1 << 24) /* FCoE CRC32 */
-#define NETIF_F_SCTP_CSUM	(1 << 25) /* SCTP checksum offload */
-#define NETIF_F_FCOE_MTU	(1 << 26) /* Supports max FCoE MTU, 2158 bytes*/
-#define NETIF_F_NTUPLE		(1 << 27) /* N-tuple filters supported */
-#define NETIF_F_RXHASH		(1 << 28) /* Receive hashing offload */
-#define NETIF_F_RXCSUM		(1 << 29) /* Receive checksumming offload */
-#define NETIF_F_NOCACHE_COPY	(1 << 30) /* Use no-cache copyfromuser */
-#define NETIF_F_LOOPBACK	(1 << 31) /* Enable loopback */
-
-	/* Segmentation offload features */
-#define NETIF_F_GSO_SHIFT	16
-#define NETIF_F_GSO_MASK	0x00ff0000
-#define NETIF_F_TSO		(SKB_GSO_TCPV4 << NETIF_F_GSO_SHIFT)
-#define NETIF_F_UFO		(SKB_GSO_UDP << NETIF_F_GSO_SHIFT)
-#define NETIF_F_GSO_ROBUST	(SKB_GSO_DODGY << NETIF_F_GSO_SHIFT)
-#define NETIF_F_TSO_ECN		(SKB_GSO_TCP_ECN << NETIF_F_GSO_SHIFT)
-#define NETIF_F_TSO6		(SKB_GSO_TCPV6 << NETIF_F_GSO_SHIFT)
-#define NETIF_F_FSO		(SKB_GSO_FCOE << NETIF_F_GSO_SHIFT)
-
-	/* Features valid for ethtool to change */
-	/* = all defined minus driver/device-class-related */
-#define NETIF_F_NEVER_CHANGE	(NETIF_F_VLAN_CHALLENGED | \
-				  NETIF_F_LLTX | NETIF_F_NETNS_LOCAL)
-#define NETIF_F_ETHTOOL_BITS	(0xff3fffff & ~NETIF_F_NEVER_CHANGE)
-
-	/* List of features with software fallbacks. */
-#define NETIF_F_GSO_SOFTWARE	(NETIF_F_TSO | NETIF_F_TSO_ECN | \
-				 NETIF_F_TSO6 | NETIF_F_UFO)
-
-
-#define NETIF_F_GEN_CSUM	(NETIF_F_NO_CSUM | NETIF_F_HW_CSUM)
-#define NETIF_F_V4_CSUM		(NETIF_F_GEN_CSUM | NETIF_F_IP_CSUM)
-#define NETIF_F_V6_CSUM		(NETIF_F_GEN_CSUM | NETIF_F_IPV6_CSUM)
-#define NETIF_F_ALL_CSUM	(NETIF_F_V4_CSUM | NETIF_F_V6_CSUM)
-
-#define NETIF_F_ALL_TSO 	(NETIF_F_TSO | NETIF_F_TSO6 | NETIF_F_TSO_ECN)
-
-#define NETIF_F_ALL_FCOE	(NETIF_F_FCOE_CRC | NETIF_F_FCOE_MTU | \
-				 NETIF_F_FSO)
-
-#define NETIF_F_ALL_TX_OFFLOADS	(NETIF_F_ALL_CSUM | NETIF_F_SG | \
-				 NETIF_F_FRAGLIST | NETIF_F_ALL_TSO | \
-				 NETIF_F_HIGHDMA | \
-				 NETIF_F_SCTP_CSUM | \
-				 NETIF_F_ALL_FCOE)
-
-	/*
-	 * If one device supports one of these features, then enable them
-	 * for all in netdev_increment_features.
-	 */
-#define NETIF_F_ONE_FOR_ALL	(NETIF_F_GSO_SOFTWARE | NETIF_F_GSO_ROBUST | \
-				 NETIF_F_SG | NETIF_F_HIGHDMA |		\
-				 NETIF_F_FRAGLIST | NETIF_F_VLAN_CHALLENGED)
-	/*
-	 * If one device doesn't support one of these features, then disable it
-	 * for all in netdev_increment_features.
-	 */
-#define NETIF_F_ALL_FOR_ALL	(NETIF_F_NOCACHE_COPY | NETIF_F_FSO)
-
-	/* changeable features with no special hardware requirements */
-#define NETIF_F_SOFT_FEATURES	(NETIF_F_GSO | NETIF_F_GRO)
+	netdev_features_t	vlan_features;
 
 	/* Interface index. Unique device identifier	*/
 	int			ifindex;
@@ -1551,7 +1469,7 @@ struct packet_type {
 					 struct packet_type *,
 					 struct net_device *);
 	struct sk_buff		*(*gso_segment)(struct sk_buff *skb,
-						u32 features);
+						netdev_features_t features);
 	int			(*gso_send_check)(struct sk_buff *skb);
 	struct sk_buff		**(*gro_receive)(struct sk_buff **head,
 					       struct sk_buff *skb);
@@ -2528,7 +2446,7 @@ extern int		netdev_set_master(struct net_device *dev, struct net_device *master)
 extern int netdev_set_bond_master(struct net_device *dev,
 				  struct net_device *master);
 extern int skb_checksum_help(struct sk_buff *skb);
-extern struct sk_buff *skb_gso_segment(struct sk_buff *skb, u32 features);
+extern struct sk_buff *skb_gso_segment(struct sk_buff *skb, netdev_features_t features);
 #ifdef CONFIG_BUG
 extern void netdev_rx_csum_fault(struct net_device *dev);
 #else
@@ -2555,12 +2473,12 @@ extern char *netdev_drivername(const struct net_device *dev, char *buffer, int l
 
 extern void linkwatch_run_queue(void);
 
-static inline u32 netdev_get_wanted_features(struct net_device *dev)
+static inline netdev_features_t netdev_get_wanted_features(struct net_device *dev)
 {
 	return (dev->features & ~dev->hw_features) | dev->wanted_features;
 }
-u32 netdev_increment_features(u32 all, u32 one, u32 mask);
-u32 netdev_fix_features(struct net_device *dev, u32 features);
+netdev_features_t netdev_increment_features(netdev_features_t all,
+	netdev_features_t one, netdev_features_t mask);
 int __netdev_update_features(struct net_device *dev);
 void netdev_update_features(struct net_device *dev);
 void netdev_change_features(struct net_device *dev);
@@ -2568,21 +2486,22 @@ void netdev_change_features(struct net_device *dev);
 void netif_stacked_transfer_operstate(const struct net_device *rootdev,
 					struct net_device *dev);
 
-u32 netif_skb_features(struct sk_buff *skb);
+netdev_features_t netif_skb_features(struct sk_buff *skb);
 
-static inline int net_gso_ok(u32 features, int gso_type)
+static inline int net_gso_ok(netdev_features_t features, int gso_type)
 {
-	int feature = gso_type << NETIF_F_GSO_SHIFT;
+	netdev_features_t feature = gso_type << NETIF_F_GSO_SHIFT;
 	return (features & feature) == feature;
 }
 
-static inline int skb_gso_ok(struct sk_buff *skb, u32 features)
+static inline int skb_gso_ok(struct sk_buff *skb, netdev_features_t features)
 {
 	return net_gso_ok(features, skb_shinfo(skb)->gso_type) &&
 	       (!skb_has_frag_list(skb) || (features & NETIF_F_FRAGLIST));
 }
 
-static inline int netif_needs_gso(struct sk_buff *skb, int features)
+static inline int netif_needs_gso(struct sk_buff *skb,
+	netdev_features_t features)
 {
 	return skb_is_gso(skb) && (!skb_gso_ok(skb, features) ||
 		unlikely(skb->ip_summed != CHECKSUM_PARTIAL));
diff --git a/include/linux/skbuff.h b/include/linux/skbuff.h
index f3af147..6aec265 100644
--- a/include/linux/skbuff.h
+++ b/include/linux/skbuff.h
@@ -29,6 +29,7 @@
 #include <linux/rcupdate.h>
 #include <linux/dmaengine.h>
 #include <linux/hrtimer.h>
+#include <linux/netdev_features.h>
 
 /* Don't change this without changing skb_csum_unnecessary! */
 #define CHECKSUM_NONE 0
@@ -1880,7 +1881,8 @@ extern void	       skb_split(struct sk_buff *skb,
 extern int	       skb_shift(struct sk_buff *tgt, struct sk_buff *skb,
 				 int shiftlen);
 
-extern struct sk_buff *skb_segment(struct sk_buff *skb, u32 features);
+extern struct sk_buff *skb_segment(struct sk_buff *skb,
+				   netdev_features_t features);
 
 static inline void *skb_header_pointer(const struct sk_buff *skb, int offset,
 				       int len, void *buffer)
diff --git a/include/net/protocol.h b/include/net/protocol.h
index 6f7eb80..e182e13 100644
--- a/include/net/protocol.h
+++ b/include/net/protocol.h
@@ -38,7 +38,7 @@ struct net_protocol {
 	void			(*err_handler)(struct sk_buff *skb, u32 info);
 	int			(*gso_send_check)(struct sk_buff *skb);
 	struct sk_buff	       *(*gso_segment)(struct sk_buff *skb,
-					       u32 features);
+					       netdev_features_t features);
 	struct sk_buff	      **(*gro_receive)(struct sk_buff **head,
 					       struct sk_buff *skb);
 	int			(*gro_complete)(struct sk_buff *skb);
@@ -57,7 +57,7 @@ struct inet6_protocol {
 
 	int	(*gso_send_check)(struct sk_buff *skb);
 	struct sk_buff *(*gso_segment)(struct sk_buff *skb,
-				       u32 features);
+				       netdev_features_t features);
 	struct sk_buff **(*gro_receive)(struct sk_buff **head,
 					struct sk_buff *skb);
 	int	(*gro_complete)(struct sk_buff *skb);
diff --git a/include/net/tcp.h b/include/net/tcp.h
index 149a415..0c49be2 100644
--- a/include/net/tcp.h
+++ b/include/net/tcp.h
@@ -1403,7 +1403,8 @@ extern struct request_sock_ops tcp6_request_sock_ops;
 extern void tcp_v4_destroy_sock(struct sock *sk);
 
 extern int tcp_v4_gso_send_check(struct sk_buff *skb);
-extern struct sk_buff *tcp_tso_segment(struct sk_buff *skb, u32 features);
+extern struct sk_buff *tcp_tso_segment(struct sk_buff *skb,
+				       netdev_features_t features);
 extern struct sk_buff **tcp_gro_receive(struct sk_buff **head,
 					struct sk_buff *skb);
 extern struct sk_buff **tcp4_gro_receive(struct sk_buff **head,
diff --git a/include/net/udp.h b/include/net/udp.h
index 67ea6fc..691ca16 100644
--- a/include/net/udp.h
+++ b/include/net/udp.h
@@ -256,5 +256,6 @@ extern void udp4_proc_exit(void);
 extern void udp_init(void);
 
 extern int udp4_ufo_send_check(struct sk_buff *skb);
-extern struct sk_buff *udp4_ufo_fragment(struct sk_buff *skb, u32 features);
+extern struct sk_buff *udp4_ufo_fragment(struct sk_buff *skb,
+	netdev_features_t features);
 #endif	/* _UDP_H */
diff --git a/net/8021q/vlan_dev.c b/net/8021q/vlan_dev.c
index 774bd22..e47c1c8 100644
--- a/net/8021q/vlan_dev.c
+++ b/net/8021q/vlan_dev.c
@@ -585,7 +585,8 @@ static void vlan_dev_uninit(struct net_device *dev)
 	}
 }
 
-static u32 vlan_dev_fix_features(struct net_device *dev, u32 features)
+static netdev_features_t vlan_dev_fix_features(struct net_device *dev,
+	netdev_features_t features)
 {
 	struct net_device *real_dev = vlan_dev_info(dev)->real_dev;
 
diff --git a/net/bridge/br_if.c b/net/bridge/br_if.c
index 1bacca4..c4908b7 100644
--- a/net/bridge/br_if.c
+++ b/net/bridge/br_if.c
@@ -292,10 +292,11 @@ int br_min_mtu(const struct net_bridge *br)
 /*
  * Recomputes features using slave's features
  */
-u32 br_features_recompute(struct net_bridge *br, u32 features)
+netdev_features_t br_features_recompute(struct net_bridge *br,
+	netdev_features_t features)
 {
 	struct net_bridge_port *p;
-	u32 mask;
+	netdev_features_t mask;
 
 	if (list_empty(&br->port_list))
 		return features;
diff --git a/net/core/dev.c b/net/core/dev.c
index 3041b6ae..a5a0e76 100644
--- a/net/core/dev.c
+++ b/net/core/dev.c
@@ -1842,7 +1842,7 @@ EXPORT_SYMBOL(skb_checksum_help);
  *	It may return NULL if the skb requires no segmentation.  This is
  *	only possible when GSO is used for verifying header integrity.
  */
-struct sk_buff *skb_gso_segment(struct sk_buff *skb, u32 features)
+struct sk_buff *skb_gso_segment(struct sk_buff *skb, netdev_features_t features)
 {
 	struct sk_buff *segs = ERR_PTR(-EPROTONOSUPPORT);
 	struct packet_type *ptype;
@@ -1872,8 +1872,8 @@ struct sk_buff *skb_gso_segment(struct sk_buff *skb, u32 features)
 		if (dev && dev->ethtool_ops && dev->ethtool_ops->get_drvinfo)
 			dev->ethtool_ops->get_drvinfo(dev, &info);
 
-		WARN(1, "%s: caps=(0x%lx, 0x%lx) len=%d data_len=%d ip_summed=%d\n",
-		     info.driver, dev ? dev->features : 0L,
+		WARN(1, "%s: caps=(0x%llx, 0x%lx) len=%d data_len=%d ip_summed=%d\n",
+		     info.driver, dev ? (long long)dev->features : 0LL,
 		     skb->sk ? skb->sk->sk_route_caps : 0L,
 		     skb->len, skb->data_len, skb->ip_summed);
 
@@ -1980,7 +1980,7 @@ static void dev_gso_skb_destructor(struct sk_buff *skb)
  *	This function segments the given skb and stores the list of segments
  *	in skb->next.
  */
-static int dev_gso_segment(struct sk_buff *skb, int features)
+static int dev_gso_segment(struct sk_buff *skb, netdev_features_t features)
 {
 	struct sk_buff *segs;
 
@@ -2019,7 +2019,7 @@ static inline void skb_orphan_try(struct sk_buff *skb)
 	}
 }
 
-static bool can_checksum_protocol(unsigned long features, __be16 protocol)
+static bool can_checksum_protocol(netdev_features_t features, __be16 protocol)
 {
 	return ((features & NETIF_F_GEN_CSUM) ||
 		((features & NETIF_F_V4_CSUM) &&
@@ -2030,7 +2030,8 @@ static bool can_checksum_protocol(unsigned long features, __be16 protocol)
 		 protocol == htons(ETH_P_FCOE)));
 }
 
-static u32 harmonize_features(struct sk_buff *skb, __be16 protocol, u32 features)
+static netdev_features_t harmonize_features(struct sk_buff *skb,
+	__be16 protocol, netdev_features_t features)
 {
 	if (!can_checksum_protocol(features, protocol)) {
 		features &= ~NETIF_F_ALL_CSUM;
@@ -2042,10 +2043,10 @@ static u32 harmonize_features(struct sk_buff *skb, __be16 protocol, u32 features
 	return features;
 }
 
-u32 netif_skb_features(struct sk_buff *skb)
+netdev_features_t netif_skb_features(struct sk_buff *skb)
 {
 	__be16 protocol = skb->protocol;
-	u32 features = skb->dev->features;
+	netdev_features_t features = skb->dev->features;
 
 	if (protocol == htons(ETH_P_8021Q)) {
 		struct vlan_ethhdr *veh = (struct vlan_ethhdr *)skb->data;
@@ -2091,7 +2092,7 @@ int dev_hard_start_xmit(struct sk_buff *skb, struct net_device *dev,
 	unsigned int skb_len;
 
 	if (likely(!skb->next)) {
-		u32 features;
+		netdev_features_t features;
 
 		/*
 		 * If device doesn't need skb->dst, release it right now while
@@ -5191,7 +5192,8 @@ static void rollback_registered(struct net_device *dev)
 	list_del(&single);
 }
 
-u32 netdev_fix_features(struct net_device *dev, u32 features)
+static netdev_features_t netdev_fix_features(struct net_device *dev,
+	netdev_features_t features)
 {
 	/* Fix illegal checksum combinations */
 	if ((features & NETIF_F_HW_CSUM) &&
@@ -5250,11 +5252,10 @@ u32 netdev_fix_features(struct net_device *dev, u32 features)
 
 	return features;
 }
-EXPORT_SYMBOL(netdev_fix_features);
 
 int __netdev_update_features(struct net_device *dev)
 {
-	u32 features;
+	netdev_features_t features;
 	int err = 0;
 
 	ASSERT_RTNL();
@@ -5270,8 +5271,10 @@ int __netdev_update_features(struct net_device *dev)
 	if (dev->features == features)
 		return 0;
 
+	BUILD_BUG_ON(sizeof(features) != sizeof(u32));	/* XXX: need: %Fx */
+
 	netdev_dbg(dev, "Features changed: 0x%08x -> 0x%08x\n",
-		dev->features, features);
+		(u32)dev->features, (u32)features);
 
 	if (dev->netdev_ops->ndo_set_features)
 		err = dev->netdev_ops->ndo_set_features(dev, features);
@@ -5279,7 +5282,7 @@ int __netdev_update_features(struct net_device *dev)
 	if (unlikely(err < 0)) {
 		netdev_err(dev,
 			"set_features() failed (%d); wanted 0x%08x, left 0x%08x\n",
-			err, features, dev->features);
+			err, (u32)features, (u32)dev->features);
 		return -1;
 	}
 
@@ -6193,7 +6196,8 @@ static int dev_cpu_callback(struct notifier_block *nfb,
  *	@one to the master device with current feature set @all.  Will not
  *	enable anything that is off in @mask. Returns the new feature set.
  */
-u32 netdev_increment_features(u32 all, u32 one, u32 mask)
+netdev_features_t netdev_increment_features(netdev_features_t all,
+	netdev_features_t one, netdev_features_t mask)
 {
 	if (mask & NETIF_F_GEN_CSUM)
 		mask |= NETIF_F_ALL_CSUM;
diff --git a/net/core/ethtool.c b/net/core/ethtool.c
index 9214e54..17f5f96 100644
--- a/net/core/ethtool.c
+++ b/net/core/ethtool.c
@@ -171,7 +171,7 @@ static void __ethtool_get_strings(struct net_device *dev,
 		ops->get_strings(dev, stringset, data);
 }
 
-static u32 ethtool_get_feature_mask(u32 eth_cmd)
+static netdev_features_t ethtool_get_feature_mask(u32 eth_cmd)
 {
 	/* feature masks of legacy discrete ethtool ops */
 
@@ -205,7 +205,7 @@ static u32 ethtool_get_feature_mask(u32 eth_cmd)
 static int ethtool_get_one_feature(struct net_device *dev,
 	char __user *useraddr, u32 ethcmd)
 {
-	u32 mask = ethtool_get_feature_mask(ethcmd);
+	netdev_features_t mask = ethtool_get_feature_mask(ethcmd);
 	struct ethtool_value edata = {
 		.cmd = ethcmd,
 		.data = !!(dev->features & mask),
@@ -220,7 +220,7 @@ static int ethtool_set_one_feature(struct net_device *dev,
 	void __user *useraddr, u32 ethcmd)
 {
 	struct ethtool_value edata;
-	u32 mask;
+	netdev_features_t mask;
 
 	if (copy_from_user(&edata, useraddr, sizeof(edata)))
 		return -EFAULT;
@@ -260,8 +260,7 @@ static u32 __ethtool_get_flags(struct net_device *dev)
 
 static int __ethtool_set_flags(struct net_device *dev, u32 data)
 {
-	u32 features = 0;
-	u32 changed;
+	netdev_features_t features = 0, changed;
 
 	if (data & ~ETH_ALL_FLAGS)
 		return -EINVAL;
diff --git a/net/core/net-sysfs.c b/net/core/net-sysfs.c
index 11b98bc..af35d90 100644
--- a/net/core/net-sysfs.c
+++ b/net/core/net-sysfs.c
@@ -100,7 +100,7 @@ NETDEVICE_SHOW(addr_assign_type, fmt_dec);
 NETDEVICE_SHOW(addr_len, fmt_dec);
 NETDEVICE_SHOW(iflink, fmt_dec);
 NETDEVICE_SHOW(ifindex, fmt_dec);
-NETDEVICE_SHOW(features, fmt_hex);
+NETDEVICE_SHOW(features, fmt_hex);	/* XXX: need %Fx */
 NETDEVICE_SHOW(type, fmt_dec);
 NETDEVICE_SHOW(link_mode, fmt_dec);
 
diff --git a/net/core/skbuff.c b/net/core/skbuff.c
index 46cbd28..76edd5b 100644
--- a/net/core/skbuff.c
+++ b/net/core/skbuff.c
@@ -2495,7 +2495,7 @@ EXPORT_SYMBOL_GPL(skb_pull_rcsum);
  *	a pointer to the first in a list of new skbs for the segments.
  *	In case of error it returns ERR_PTR(err).
  */
-struct sk_buff *skb_segment(struct sk_buff *skb, u32 features)
+struct sk_buff *skb_segment(struct sk_buff *skb, netdev_features_t features)
 {
 	struct sk_buff *segs = NULL;
 	struct sk_buff *tail = NULL;
diff --git a/net/ipv4/af_inet.c b/net/ipv4/af_inet.c
index 83673d2..7c9a33f 100644
--- a/net/ipv4/af_inet.c
+++ b/net/ipv4/af_inet.c
@@ -1242,7 +1242,8 @@ out:
 	return err;
 }
 
-static struct sk_buff *inet_gso_segment(struct sk_buff *skb, u32 features)
+static struct sk_buff *inet_gso_segment(struct sk_buff *skb,
+	netdev_features_t features)
 {
 	struct sk_buff *segs = ERR_PTR(-EINVAL);
 	struct iphdr *iph;
diff --git a/net/ipv4/tcp.c b/net/ipv4/tcp.c
index 054a59d..ff9104f 100644
--- a/net/ipv4/tcp.c
+++ b/net/ipv4/tcp.c
@@ -2654,7 +2654,7 @@ int compat_tcp_getsockopt(struct sock *sk, int level, int optname,
 EXPORT_SYMBOL(compat_tcp_getsockopt);
 #endif
 
-struct sk_buff *tcp_tso_segment(struct sk_buff *skb, u32 features)
+struct sk_buff *tcp_tso_segment(struct sk_buff *skb, netdev_features_t features)
 {
 	struct sk_buff *segs = ERR_PTR(-EINVAL);
 	struct tcphdr *th;
diff --git a/net/ipv4/udp.c b/net/ipv4/udp.c
index abca870..2842993 100644
--- a/net/ipv4/udp.c
+++ b/net/ipv4/udp.c
@@ -2244,7 +2244,8 @@ int udp4_ufo_send_check(struct sk_buff *skb)
 	return 0;
 }
 
-struct sk_buff *udp4_ufo_fragment(struct sk_buff *skb, u32 features)
+struct sk_buff *udp4_ufo_fragment(struct sk_buff *skb,
+	netdev_features_t features)
 {
 	struct sk_buff *segs = ERR_PTR(-EINVAL);
 	unsigned int mss;
diff --git a/net/ipv6/af_inet6.c b/net/ipv6/af_inet6.c
index b7919f9..34088f7 100644
--- a/net/ipv6/af_inet6.c
+++ b/net/ipv6/af_inet6.c
@@ -765,7 +765,8 @@ out:
 	return err;
 }
 
-static struct sk_buff *ipv6_gso_segment(struct sk_buff *skb, u32 features)
+static struct sk_buff *ipv6_gso_segment(struct sk_buff *skb,
+	netdev_features_t features)
 {
 	struct sk_buff *segs = ERR_PTR(-EINVAL);
 	struct ipv6hdr *ipv6h;
diff --git a/net/ipv6/udp.c b/net/ipv6/udp.c
index 41f8c9c..1df53db 100644
--- a/net/ipv6/udp.c
+++ b/net/ipv6/udp.c
@@ -1295,7 +1295,7 @@ static int udp6_ufo_send_check(struct sk_buff *skb)
 	return 0;
 }
 
-static struct sk_buff *udp6_ufo_fragment(struct sk_buff *skb, u32 features)
+static struct sk_buff *udp6_ufo_fragment(struct sk_buff *skb, netdev_features_t features)
 {
 	struct sk_buff *segs = ERR_PTR(-EINVAL);
 	unsigned int mss;
-- 
1.7.2.5


^ permalink raw reply related

* [RFT PATCH 5/9] net: Define enum for net device features.
From: Michał Mirosław @ 2011-06-20 19:14 UTC (permalink / raw)
  To: netdev; +Cc: David S. Miller, Ben Hutchings
In-Reply-To: <cover.1308596962.git.mirq-linux@rere.qmqm.pl>

Define feature values by bit position instead of direct 2**i values
and force the values to be of type netdev_features_t.

Cleaned and extended from patch by Mahesh Bandewar <maheshb@google.com>:
+ added netdev_features_t casts
+ included bits under NETIF_F_GSO_MASK
+ moved feature #defines out of struct net_device definition

Signed-off-by: Michał Mirosław <mirq-linux@rere.qmqm.pl>
---
 include/linux/netdev_features.h |  125 +++++++++++++++++++++++++++-----------
 1 files changed, 89 insertions(+), 36 deletions(-)

diff --git a/include/linux/netdev_features.h b/include/linux/netdev_features.h
index d36bdcd..2361e3ee 100644
--- a/include/linux/netdev_features.h
+++ b/include/linux/netdev_features.h
@@ -14,55 +14,108 @@
 
 typedef u32 netdev_features_t;
 
-#define NETIF_F_SG		1	/* Scatter/gather IO. */
-#define NETIF_F_IP_CSUM		2	/* Can checksum TCP/UDP over IPv4. */
-#define NETIF_F_NO_CSUM		4	/* Does not require checksum. F.e. loopack. */
-#define NETIF_F_HW_CSUM		8	/* Can checksum all the packets. */
-#define NETIF_F_IPV6_CSUM	16	/* Can checksum TCP/UDP over IPV6 */
-#define NETIF_F_HIGHDMA		32	/* Can DMA to high memory. */
-#define NETIF_F_FRAGLIST	64	/* Scatter/gather IO. */
-#define NETIF_F_HW_VLAN_TX	128	/* Transmit VLAN hw acceleration */
-#define NETIF_F_HW_VLAN_RX	256	/* Receive VLAN hw acceleration */
-#define NETIF_F_HW_VLAN_FILTER	512	/* Receive filtering on VLAN */
-#define NETIF_F_VLAN_CHALLENGED	1024	/* Device cannot handle VLAN packets */
-#define NETIF_F_GSO		2048	/* Enable software GSO. */
-#define NETIF_F_LLTX		4096	/* LockLess TX - deprecated. Please */
+enum {
+	NETIF_F_SG_BIT,			/* Scatter/gather IO. */
+	NETIF_F_IP_CSUM_BIT,		/* Can checksum TCP/UDP over IPv4. */
+	NETIF_F_NO_CSUM_BIT,		/* Does not require checksum. F.e. loopack. */
+	NETIF_F_HW_CSUM_BIT,		/* Can checksum all the packets. */
+	NETIF_F_IPV6_CSUM_BIT,		/* Can checksum TCP/UDP over IPV6 */
+	NETIF_F_HIGHDMA_BIT,		/* Can DMA to high memory. */
+	NETIF_F_FRAGLIST_BIT,		/* Scatter/gather IO. */
+	NETIF_F_HW_VLAN_TX_BIT,		/* Transmit VLAN hw acceleration */
+	NETIF_F_HW_VLAN_RX_BIT,		/* Receive VLAN hw acceleration */
+	NETIF_F_HW_VLAN_FILTER_BIT,	/* Receive filtering on VLAN */
+	NETIF_F_VLAN_CHALLENGED_BIT,	/* Device cannot handle VLAN packets */
+	NETIF_F_GSO_BIT,		/* Enable software GSO. */
+	NETIF_F_LLTX_BIT,		/* LockLess TX - deprecated. Please */
 					/* do not use LLTX in new drivers */
-#define NETIF_F_NETNS_LOCAL	8192	/* Does not change network namespaces */
-#define NETIF_F_GRO		16384	/* Generic receive offload */
-#define NETIF_F_LRO		32768	/* large receive offload */
+	NETIF_F_NETNS_LOCAL_BIT,	/* Does not change network namespaces */
+	NETIF_F_GRO_BIT,		/* Generic receive offload */
+	NETIF_F_LRO_BIT,		/* large receive offload */
 
-/* the GSO_MASK reserves bits 16 through 23 */
-#define NETIF_F_FCOE_CRC	(1 << 24) /* FCoE CRC32 */
-#define NETIF_F_SCTP_CSUM	(1 << 25) /* SCTP checksum offload */
-#define NETIF_F_FCOE_MTU	(1 << 26) /* Supports max FCoE MTU, 2158 bytes*/
-#define NETIF_F_NTUPLE		(1 << 27) /* N-tuple filters supported */
-#define NETIF_F_RXHASH		(1 << 28) /* Receive hashing offload */
-#define NETIF_F_RXCSUM		(1 << 29) /* Receive checksumming offload */
-#define NETIF_F_NOCACHE_COPY	(1 << 30) /* Use no-cache copyfromuser */
-#define NETIF_F_LOOPBACK	(1 << 31) /* Enable loopback */
+	/**/NETIF_F_GSO_SHIFT,		/* keep the order of SKB_GSO_* bits */
+	NETIF_F_TSO_BIT			/* ... TCPv4 segmentation */
+		= NETIF_F_GSO_SHIFT,
+	NETIF_F_UFO_BIT,		/* ... UDPv4 fragmentation */
+	NETIF_F_GSO_ROBUST_BIT,		/* ... ->SKB_GSO_DODGY */
+	NETIF_F_TSO_ECN_BIT,		/* ... TCP ECN support */
+	NETIF_F_TSO6_BIT,		/* ... TCPv6 segmentation */
+	NETIF_F_FSO_BIT,		/* ... FCoE segmentation */
+	NETIF_F_GSO_RESERVED1,		/* ... free (fill GSO_MASK to 8 bits) */
+	/**/NETIF_F_GSO_LAST,		/* [can't be last bit, see GSO_MASK] */
+	NETIF_F_GSO_RESERVED2		/* ... free (fill GSO_MASK to 8 bits) */
+		= NETIF_F_GSO_LAST,
 
-	/* Segmentation offload features */
-#define NETIF_F_GSO_SHIFT	16
-#define NETIF_F_GSO_MASK	0x00ff0000
-#define NETIF_F_TSO		(SKB_GSO_TCPV4 << NETIF_F_GSO_SHIFT)
-#define NETIF_F_UFO		(SKB_GSO_UDP << NETIF_F_GSO_SHIFT)
-#define NETIF_F_GSO_ROBUST	(SKB_GSO_DODGY << NETIF_F_GSO_SHIFT)
-#define NETIF_F_TSO_ECN		(SKB_GSO_TCP_ECN << NETIF_F_GSO_SHIFT)
-#define NETIF_F_TSO6		(SKB_GSO_TCPV6 << NETIF_F_GSO_SHIFT)
-#define NETIF_F_FSO		(SKB_GSO_FCOE << NETIF_F_GSO_SHIFT)
+	NETIF_F_FCOE_CRC_BIT,		/* FCoE CRC32 */
+	NETIF_F_SCTP_CSUM_BIT,		/* SCTP checksum offload */
+	NETIF_F_FCOE_MTU_BIT,		/* Supports max FCoE MTU, 2158 bytes*/
+	NETIF_F_NTUPLE_BIT,		/* N-tuple filters supported */
+	NETIF_F_RXHASH_BIT,		/* Receive hashing offload */
+	NETIF_F_RXCSUM_BIT,		/* Receive checksumming offload */
+	NETIF_F_NOCACHE_COPY_BIT,	/* Use no-cache copyfromuser */
+	NETIF_F_LOOPBACK_BIT,		/* Enable loopback */
+
+	/*
+	 * Add your fresh new feature above and remember to update
+	 * netdev_features_strings[] in net/core/ethtool.c and maybe
+	 * some feature mask #defines below.
+	 */
+
+	/**/NETDEV_FEATURE_COUNT
+};
+
+/* copy'n'paste compression ;) */
+#define __NETIF_F_BIT(bit)	((netdev_features_t)1 << (bit))
+#define __NETIF_F(name)		__NETIF_F_BIT(NETIF_F_##name##_BIT)
+
+#define NETIF_F_SG		__NETIF_F(SG)
+#define NETIF_F_IP_CSUM		__NETIF_F(IP_CSUM)
+#define NETIF_F_NO_CSUM		__NETIF_F(NO_CSUM)
+#define NETIF_F_HW_CSUM		__NETIF_F(HW_CSUM)
+#define NETIF_F_IPV6_CSUM	__NETIF_F(IPV6_CSUM)
+#define NETIF_F_HIGHDMA		__NETIF_F(HIGHDMA)
+#define NETIF_F_FRAGLIST	__NETIF_F(FRAGLIST)
+#define NETIF_F_HW_VLAN_TX	__NETIF_F(HW_VLAN_TX)
+#define NETIF_F_HW_VLAN_RX	__NETIF_F(HW_VLAN_RX)
+#define NETIF_F_HW_VLAN_FILTER	__NETIF_F(HW_VLAN_FILTER)
+#define NETIF_F_VLAN_CHALLENGED	__NETIF_F(VLAN_CHALLENGED)
+#define NETIF_F_GSO		__NETIF_F(GSO)
+#define NETIF_F_LLTX		__NETIF_F(LLTX)
+#define NETIF_F_NETNS_LOCAL	__NETIF_F(NETNS_LOCAL)
+#define NETIF_F_GRO		__NETIF_F(GRO)
+#define NETIF_F_LRO		__NETIF_F(LRO)
+#define NETIF_F_TSO		__NETIF_F(TSO)
+#define NETIF_F_UFO		__NETIF_F(UFO)
+#define NETIF_F_GSO_ROBUST	__NETIF_F(GSO_ROBUST)
+#define NETIF_F_TSO_ECN		__NETIF_F(TSO_ECN)
+#define NETIF_F_TSO6		__NETIF_F(TSO6)
+#define NETIF_F_FSO		__NETIF_F(FSO)
+#define NETIF_F_FCOE_CRC	__NETIF_F(FCOE_CRC)
+#define NETIF_F_SCTP_CSUM	__NETIF_F(SCTP_CSUM)
+#define NETIF_F_FCOE_MTU	__NETIF_F(FCOE_MTU)
+#define NETIF_F_NTUPLE		__NETIF_F(NTUPLE)
+#define NETIF_F_RXHASH		__NETIF_F(RXHASH)
+#define NETIF_F_RXCSUM		__NETIF_F(RXCSUM)
+#define NETIF_F_NOCACHE_COPY	__NETIF_F(NOCACHE_COPY)
+#define NETIF_F_LOOPBACK	__NETIF_F(LOOPBACK)
 
 	/* Features valid for ethtool to change */
 	/* = all defined minus driver/device-class-related */
 #define NETIF_F_NEVER_CHANGE	(NETIF_F_VLAN_CHALLENGED | \
 				  NETIF_F_LLTX | NETIF_F_NETNS_LOCAL)
-#define NETIF_F_ETHTOOL_BITS	(0xff3fffff & ~NETIF_F_NEVER_CHANGE)
+	/* remember that ((t)1 << t_BITS) is undefined in C99 */
+#define NETIF_F_ETHTOOL_BITS	((__NETIF_F_BIT(NETDEV_FEATURE_COUNT - 1) | \
+		(__NETIF_F_BIT(NETDEV_FEATURE_COUNT - 1) - 1)) & \
+		~NETIF_F_NEVER_CHANGE)
+
+	/* Segmentation offload feature mask */
+#define NETIF_F_GSO_MASK	(__NETIF_F_BIT(NETIF_F_GSO_LAST + 1) - \
+		__NETIF_F_BIT(NETIF_F_GSO_SHIFT))
 
 	/* List of features with software fallbacks. */
 #define NETIF_F_GSO_SOFTWARE	(NETIF_F_TSO | NETIF_F_TSO_ECN | \
 				 NETIF_F_TSO6 | NETIF_F_UFO)
 
-
 #define NETIF_F_GEN_CSUM	(NETIF_F_NO_CSUM | NETIF_F_HW_CSUM)
 #define NETIF_F_V4_CSUM		(NETIF_F_GEN_CSUM | NETIF_F_IP_CSUM)
 #define NETIF_F_V6_CSUM		(NETIF_F_GEN_CSUM | NETIF_F_IPV6_CSUM)
-- 
1.7.2.5


^ permalink raw reply related

* [RFT PATCH 7/9] ethtool: prepare for larger netdev_features_t type
From: Michał Mirosław @ 2011-06-20 19:14 UTC (permalink / raw)
  To: netdev; +Cc: David S. Miller, Ben Hutchings
In-Reply-To: <cover.1308596962.git.mirq-linux@rere.qmqm.pl>

Signed-off-by: Michał Mirosław <mirq-linux@rere.qmqm.pl>
---
 net/core/ethtool.c |   45 +++++++++++++++++++++++++++++----------------
 1 files changed, 29 insertions(+), 16 deletions(-)

diff --git a/net/core/ethtool.c b/net/core/ethtool.c
index 97bbf25..3a93932 100644
--- a/net/core/ethtool.c
+++ b/net/core/ethtool.c
@@ -38,7 +38,7 @@ EXPORT_SYMBOL(ethtool_op_get_link);
 
 /* Handlers for each ethtool command */
 
-#define ETHTOOL_DEV_FEATURE_WORDS	1
+#define ETHTOOL_DEV_FEATURE_WORDS	((NETDEV_FEATURE_COUNT + 31) / 32)
 
 static const char netdev_features_strings[NETDEV_FEATURE_COUNT][ETH_GSTRING_LEN] = {
 	[NETIF_F_SG_BIT] =               "tx-scatter-gather",
@@ -82,16 +82,21 @@ static int ethtool_get_features(struct net_device *dev, void __user *useraddr)
 		.cmd = ETHTOOL_GFEATURES,
 		.size = ETHTOOL_DEV_FEATURE_WORDS,
 	};
-	struct ethtool_get_features_block features[ETHTOOL_DEV_FEATURE_WORDS] = {
-		{
-			.available = dev->hw_features,
-			.requested = dev->wanted_features,
-			.active = dev->features,
-			.never_changed = NETIF_F_NEVER_CHANGE,
-		},
-	};
+	struct ethtool_get_features_block features[ETHTOOL_DEV_FEATURE_WORDS];
 	u32 __user *sizeaddr;
 	u32 copy_size;
+	int i;
+
+	/* in case feature bits run out again */
+	BUILD_BUG_ON(ETHTOOL_DEV_FEATURE_WORDS*sizeof(u32) > sizeof(netdev_features_t));
+
+	/* this should get loop-unrolled easily by compiler */
+	for (i = 0; i < ETHTOOL_DEV_FEATURE_WORDS; ++i) {
+		features[i].available = (u32)(dev->hw_features >> (32*i));
+		features[i].requested = (u32)(dev->wanted_features >> (32*i));
+		features[i].active = (u32)(dev->features >> (32*i));
+		features[i].never_changed = (u32)(NETIF_F_NEVER_CHANGE >> (32*i));
+	}
 
 	sizeaddr = useraddr + offsetof(struct ethtool_gfeatures, size);
 	if (get_user(copy_size, sizeaddr))
@@ -113,7 +118,8 @@ static int ethtool_set_features(struct net_device *dev, void __user *useraddr)
 {
 	struct ethtool_sfeatures cmd;
 	struct ethtool_set_features_block features[ETHTOOL_DEV_FEATURE_WORDS];
-	int ret = 0;
+	netdev_features_t wanted = 0, valid = 0;
+	int i, ret = 0;
 
 	if (copy_from_user(&cmd, useraddr, sizeof(cmd)))
 		return -EFAULT;
@@ -125,19 +131,26 @@ static int ethtool_set_features(struct net_device *dev, void __user *useraddr)
 	if (copy_from_user(features, useraddr, sizeof(features)))
 		return -EFAULT;
 
-	if (features[0].valid & ~NETIF_F_ETHTOOL_BITS)
+	/* I wonder if the compiler will be smart enough to loop-unroll
+	 * and optimize this... (no worries if not) --mq */
+	for (i = ETHTOOL_DEV_FEATURE_WORDS; i-- > 0; ) {
+		valid = (valid << 32)|features[i].valid;
+		wanted = (wanted << 32)|features[i].requested;
+	}
+
+	if (valid & ~NETIF_F_ETHTOOL_BITS)
 		return -EINVAL;
 
-	if (features[0].valid & ~dev->hw_features) {
-		features[0].valid &= dev->hw_features;
+	if (valid & ~dev->hw_features) {
+		valid &= dev->hw_features;
 		ret |= ETHTOOL_F_UNSUPPORTED;
 	}
 
-	dev->wanted_features &= ~features[0].valid;
-	dev->wanted_features |= features[0].valid & features[0].requested;
+	dev->wanted_features &= ~valid;
+	dev->wanted_features |= wanted & valid;
 	__netdev_update_features(dev);
 
-	if ((dev->wanted_features ^ dev->features) & features[0].valid)
+	if ((dev->wanted_features ^ dev->features) & valid)
 		ret |= ETHTOOL_F_WISH;
 
 	return ret;
-- 
1.7.2.5


^ permalink raw reply related

* [RFT PATCH 9/9] net: move NOCACHE_COPY checks to netdev_fix_features()
From: Michał Mirosław @ 2011-06-20 19:14 UTC (permalink / raw)
  To: netdev; +Cc: David S. Miller, Ben Hutchings
In-Reply-To: <cover.1308596962.git.mirq-linux@rere.qmqm.pl>

Signed-off-by: Michał Mirosław <mirq-linux@rere.qmqm.pl>
---
 include/linux/netdev_features.h |    3 ++-
 net/core/dev.c                  |   21 +++++++++++++--------
 2 files changed, 15 insertions(+), 9 deletions(-)

diff --git a/include/linux/netdev_features.h b/include/linux/netdev_features.h
index 86d6193..9f24781 100644
--- a/include/linux/netdev_features.h
+++ b/include/linux/netdev_features.h
@@ -146,6 +146,7 @@ enum {
 #define NETIF_F_ALL_FOR_ALL	(NETIF_F_NOCACHE_COPY | NETIF_F_FSO)
 
 	/* changeable features with no special hardware requirements */
-#define NETIF_F_SOFT_FEATURES	(NETIF_F_GSO | NETIF_F_GRO)
+#define NETIF_F_SOFT_FEATURES	(NETIF_F_GSO | NETIF_F_GRO | \
+				 NETIF_F_NOCACHE_COPY)
 
 #endif	/* _LINUX_NETDEV_FEATURES_H */
diff --git a/net/core/dev.c b/net/core/dev.c
index 7e58353..30782b7 100644
--- a/net/core/dev.c
+++ b/net/core/dev.c
@@ -5250,6 +5250,19 @@ static netdev_features_t netdev_fix_features(struct net_device *dev,
 		}
 	}
 
+	/* No cache copy is a win only with real HW with HW checksumming */
+	if (features & NETIF_F_NOCACHE_COPY) {
+		if (!(features & NETIF_F_ALL_CSUM)) {
+			netdev_dbg(dev,
+				"Dropping NETIF_F_NOCACHE_COPY since it needs HW checksumming.\n");
+			features &= ~NETIF_F_NOCACHE_COPY;
+		} else if (features & NETIF_F_NO_CSUM) {
+			netdev_dbg(dev,
+				"Dropping NETIF_F_NOCACHE_COPY for virtual device.\n");
+			features &= ~NETIF_F_NOCACHE_COPY;
+		}
+	}
+
 	return features;
 }
 
@@ -5465,14 +5478,6 @@ int register_netdevice(struct net_device *dev)
 	dev->features |= NETIF_F_SOFT_FEATURES;
 	dev->wanted_features = dev->features & dev->hw_features;
 
-	/* Turn on no cache copy if HW is doing checksum */
-	dev->hw_features |= NETIF_F_NOCACHE_COPY;
-	if ((dev->features & NETIF_F_ALL_CSUM) &&
-	    !(dev->features & NETIF_F_NO_CSUM)) {
-		dev->wanted_features |= NETIF_F_NOCACHE_COPY;
-		dev->features |= NETIF_F_NOCACHE_COPY;
-	}
-
 	/* Enable GRO and NETIF_F_HIGHDMA for vlans by default,
 	 * vlan_dev_init() will do the dev->features check, so these features
 	 * are enabled only if supported by underlying device.
-- 
1.7.2.5


^ permalink raw reply related

* [RFT PATCH 8/9] net: extend netdev_features_t to 64 bits
From: Michał Mirosław @ 2011-06-20 19:14 UTC (permalink / raw)
  To: netdev; +Cc: David S. Miller, Ben Hutchings
In-Reply-To: <cover.1308596962.git.mirq-linux@rere.qmqm.pl>

Signed-off-by: Michał Mirosław <mirq-linux@rere.qmqm.pl>
---
 include/linux/netdev_features.h |    2 +-
 net/core/dev.c                  |   10 +++++-----
 net/core/net-sysfs.c            |    3 ++-
 3 files changed, 8 insertions(+), 7 deletions(-)

diff --git a/include/linux/netdev_features.h b/include/linux/netdev_features.h
index 2361e3ee..86d6193 100644
--- a/include/linux/netdev_features.h
+++ b/include/linux/netdev_features.h
@@ -12,7 +12,7 @@
 
 #include <linux/types.h>
 
-typedef u32 netdev_features_t;
+typedef u64 netdev_features_t;
 
 enum {
 	NETIF_F_SG_BIT,			/* Scatter/gather IO. */
diff --git a/net/core/dev.c b/net/core/dev.c
index a5a0e76..7e58353 100644
--- a/net/core/dev.c
+++ b/net/core/dev.c
@@ -5271,18 +5271,18 @@ int __netdev_update_features(struct net_device *dev)
 	if (dev->features == features)
 		return 0;
 
-	BUILD_BUG_ON(sizeof(features) != sizeof(u32));	/* XXX: need: %Fx */
+	BUILD_BUG_ON(sizeof(features) != sizeof(u64));	/* XXX: need: %Fx */
 
-	netdev_dbg(dev, "Features changed: 0x%08x -> 0x%08x\n",
-		(u32)dev->features, (u32)features);
+	netdev_dbg(dev, "Features changed: 0x%016llx -> 0x%016llx\n",
+		(u64)dev->features, (u64)features);
 
 	if (dev->netdev_ops->ndo_set_features)
 		err = dev->netdev_ops->ndo_set_features(dev, features);
 
 	if (unlikely(err < 0)) {
 		netdev_err(dev,
-			"set_features() failed (%d); wanted 0x%08x, left 0x%08x\n",
-			err, (u32)features, (u32)dev->features);
+			"set_features() failed (%d); wanted 0x%016llx, left 0x%016llx\n",
+			err, (u64)features, (u64)dev->features);
 		return -1;
 	}
 
diff --git a/net/core/net-sysfs.c b/net/core/net-sysfs.c
index af35d90..b7feeab 100644
--- a/net/core/net-sysfs.c
+++ b/net/core/net-sysfs.c
@@ -27,6 +27,7 @@
 #ifdef CONFIG_SYSFS
 static const char fmt_hex[] = "%#x\n";
 static const char fmt_long_hex[] = "%#lx\n";
+static const char fmt_long_long_hex[] = "%#llx\n";
 static const char fmt_dec[] = "%d\n";
 static const char fmt_udec[] = "%u\n";
 static const char fmt_ulong[] = "%lu\n";
@@ -100,7 +101,7 @@ NETDEVICE_SHOW(addr_assign_type, fmt_dec);
 NETDEVICE_SHOW(addr_len, fmt_dec);
 NETDEVICE_SHOW(iflink, fmt_dec);
 NETDEVICE_SHOW(ifindex, fmt_dec);
-NETDEVICE_SHOW(features, fmt_hex);	/* XXX: need %Fx */
+NETDEVICE_SHOW(features, fmt_long_long_hex);	/* XXX: need %Fx */
 NETDEVICE_SHOW(type, fmt_dec);
 NETDEVICE_SHOW(link_mode, fmt_dec);
 
-- 
1.7.2.5


^ permalink raw reply related

* [RESENT PATCH] net: tuntap: Fix tun_net_fix_features()
From: Michał Mirosław @ 2011-06-20 19:14 UTC (permalink / raw)
  To: netdev; +Cc: Herbert Xu, Michael S. Tsirkin, Ben Hutchings, Shan Wei
In-Reply-To: <20110517081954.A227013A6A@rere.qmqm.pl>

tun->set_features are meant to limit not force the features.

Signed-off-by: Michał Mirosław <mirq-linux@rere.qmqm.pl>
Acked-by: Michael S. Tsirkin <mst@redhat.com>

---
 drivers/net/tun.c |    2 +-
 1 files changed, 1 insertions(+), 1 deletions(-)

diff --git a/drivers/net/tun.c b/drivers/net/tun.c
index 4dab85e..56981c2 100644
--- a/drivers/net/tun.c
+++ b/drivers/net/tun.c
@@ -458,7 +458,7 @@ static u32 tun_net_fix_features(struct net_device *dev, u32 features)
 {
 	struct tun_struct *tun = netdev_priv(dev);
 
-	return (features & tun->set_features) | (features & ~TUN_USER_FEATURES);
+	return features & (tun->set_features | ~TUN_USER_FEATURES);
 }
 
 static const struct net_device_ops tun_netdev_ops = {
-- 
1.7.2.5


^ permalink raw reply related

* [RFT PATCH 0/9] Cleanup and extension of netdev features
From: Michał Mirosław @ 2011-06-20 19:14 UTC (permalink / raw)
  To: netdev; +Cc: David S. Miller, Ben Hutchings

This is a preview of the cleanups pending after getting rid of old
ethtool ops from remaining drivers.

Patches inside:
 1. (placeholder for Intel patches)
 2. removal of old ethtool ops
	(most further patches depend on this one)
 3. break association of ETH_FLAG_* with netdev features
	this will allow to change the representation and access pattern
	of the feature sets if later needed; as a bonus, the features
	can be (almost) freely rearranged
 4. introducing netdev_features_t
	use new type wherever features are passed around (this needed
	new include - otherwise linux/skbuff.h would need linux/netdevice.h)
 5. cleanup of feature bits
 6. cleanup of feature name table
	(depends on #5)
 7. prepare ethtool [GS]FEATURES for larger netdev_features_t
 8. tadaaa: 64 bits for features
 9. a lone cleanup patch for NOCACHE_COPY feature

Bear in mind, that I only compile tested the whole series (x86 allyesconfig).
I'll do per-patch builds after all needed patches are in net-next.

Note about netdev_features_t: I don't like the idea of converting it to
bitmap type and building wrappers around, so I won't even try to
implement it. Nevertheless, this series will make the conversion easier
if someone ever wants to go that way.

Best Regards,
Michał Mirosław

---

Michał Mirosław (9):
  [NOT SENT] Intel net drivers: convert to ndo_fix_features
  net: remove legacy ethtool ops
  net: ethtool: break association of ETH_FLAG_* with NETIF_F_*
  net: introduce and use netdev_features_t for device features sets
  net: Define enum for net device features.
  net: ethtool: use C99 array initialization for feature-names table
  ethtool: prepare for larger netdev_features_t type
  net: extend netdev_features_t to 64 bits
  net: move NOCACHE_COPY checks to netdev_fix_features()

 drivers/net/8139cp.c                  |    2 +-
 drivers/net/bnx2.c                    |    6 +-
 drivers/net/bnx2x/bnx2x_cmn.c         |    5 +-
 drivers/net/bnx2x/bnx2x_cmn.h         |    5 +-
 drivers/net/bonding/bond_main.c       |    9 +-
 drivers/net/cxgb4/cxgb4_main.c        |   12 +-
 drivers/net/dm9000.c                  |    3 +-
 drivers/net/e1000/e1000_ethtool.c     |   69 ----
 drivers/net/e1000/e1000_main.c        |   31 ++-
 drivers/net/e1000e/ethtool.c          |   88 -----
 drivers/net/e1000e/netdev.c           |   35 ++-
 drivers/net/forcedeth.c               |    7 +-
 drivers/net/gianfar.h                 |    2 +-
 drivers/net/gianfar_ethtool.c         |    4 +-
 drivers/net/ibmveth.c                 |    6 +-
 drivers/net/igb/igb_ethtool.c         |   67 ----
 drivers/net/igb/igb_main.c            |   33 ++-
 drivers/net/igbvf/ethtool.c           |   57 ----
 drivers/net/igbvf/netdev.c            |   25 ++-
 drivers/net/ixgb/ixgb.h               |    2 +
 drivers/net/ixgb/ixgb_ethtool.c       |   98 +------
 drivers/net/ixgb/ixgb_main.c          |   44 +++-
 drivers/net/ixgbe/ixgbe_ethtool.c     |  183 ++++--------
 drivers/net/ixgbe/ixgbe_main.c        |   42 ++-
 drivers/net/ixgbevf/ethtool.c         |   46 ---
 drivers/net/ixgbevf/ixgbevf_main.c    |   26 ++-
 drivers/net/jme.c                     |    8 +-
 drivers/net/ksz884x.c                 |    3 +-
 drivers/net/mv643xx_eth.c             |    2 +-
 drivers/net/myri10ge/myri10ge.c       |    2 +-
 drivers/net/netxen/netxen_nic_main.c  |    6 +-
 drivers/net/pch_gbe/pch_gbe_main.c    |    5 +-
 drivers/net/qlcnic/qlcnic.h           |    5 +-
 drivers/net/qlcnic/qlcnic_hw.c        |    9 +-
 drivers/net/qlcnic/qlcnic_main.c      |    2 +-
 drivers/net/r8169.c                   |    6 +-
 drivers/net/s2io.c                    |    4 +-
 drivers/net/sfc/efx.c                 |    2 +-
 drivers/net/sky2.c                    |    5 +-
 drivers/net/tg3.c                     |    7 +-
 drivers/net/usb/smsc75xx.c            |    3 +-
 drivers/net/usb/smsc95xx.c            |    3 +-
 drivers/net/vmxnet3/vmxnet3_ethtool.c |    4 +-
 drivers/net/vmxnet3/vmxnet3_int.h     |    2 +-
 drivers/net/vxge/vxge-main.c          |    9 +-
 drivers/net/xen-netfront.c            |    8 +-
 drivers/s390/net/qeth_l3_main.c       |    6 +-
 include/linux/ethtool.h               |   53 ---
 include/linux/netdev_features.h       |  152 +++++++++
 include/linux/netdevice.h             |  141 ++-------
 include/linux/skbuff.h                |    4 +-
 include/net/protocol.h                |    4 +-
 include/net/tcp.h                     |    3 +-
 include/net/udp.h                     |    3 +-
 net/8021q/vlan_dev.c                  |    5 +-
 net/bridge/br_if.c                    |    5 +-
 net/core/dev.c                        |   71 ++--
 net/core/ethtool.c                    |  563 ++++++--------------------------
 net/core/net-sysfs.c                  |    3 +-
 net/core/skbuff.c                     |    2 +-
 net/ipv4/af_inet.c                    |    3 +-
 net/ipv4/tcp.c                        |    2 +-
 net/ipv4/udp.c                        |    3 +-
 net/ipv6/af_inet6.c                   |    3 +-
 net/ipv6/udp.c                        |    2 +-
 65 files changed, 683 insertions(+), 1347 deletions(-)
 create mode 100644 include/linux/netdev_features.h

-- 
1.7.2.5


^ permalink raw reply

* Re: [RESENT PATCH] net: tuntap: Fix tun_net_fix_features()
From: Ben Hutchings @ 2011-06-20 19:25 UTC (permalink / raw)
  To: Michał Mirosław
  Cc: netdev, Herbert Xu, Michael S. Tsirkin, Shan Wei
In-Reply-To: <d66c8380b6c50fdcfe2dce344b39bb470a75ba3f.1308595725.git.mirq-linux@rere.qmqm.pl>

On Mon, 2011-06-20 at 21:14 +0200, Michał Mirosław wrote:
> tun->set_features are meant to limit not force the features.
>
> Signed-off-by: Michał Mirosław <mirq-linux@rere.qmqm.pl>
> Acked-by: Michael S. Tsirkin <mst@redhat.com>
> 
> ---
>  drivers/net/tun.c |    2 +-
>  1 files changed, 1 insertions(+), 1 deletions(-)
> 
> diff --git a/drivers/net/tun.c b/drivers/net/tun.c
> index 4dab85e..56981c2 100644
> --- a/drivers/net/tun.c
> +++ b/drivers/net/tun.c
> @@ -458,7 +458,7 @@ static u32 tun_net_fix_features(struct net_device *dev, u32 features)
>  {
>  	struct tun_struct *tun = netdev_priv(dev);
>  
> -	return (features & tun->set_features) | (features & ~TUN_USER_FEATURES);
> +	return features & (tun->set_features | ~TUN_USER_FEATURES);

(A & B) | (A & C) <=> A & (B | C)

This is a cosmetic change, not a fix.  Maybe you think it is clearer but
then you should say that in the commit message.

Ben.

>  }
>  
>  static const struct net_device_ops tun_netdev_ops = {

-- 
Ben Hutchings, Senior Software Engineer, Solarflare
Not speaking for my employer; that's the marketing department's job.
They asked us to note that Solarflare product names are trademarked.


^ permalink raw reply

* Re: [Bugme-new] [Bug 37992] New: It's not possible to compile kernel if CONFIG_NETCONSOLE_DYNAMIC is turned on
From: Andrew Morton @ 2011-06-20 19:28 UTC (permalink / raw)
  To: netdev; +Cc: bugme-daemon, hilld
In-Reply-To: <bug-37992-10286@https.bugzilla.kernel.org/>


(switched to email.  Please respond via emailed reply-to-all, not via the
bugzilla web interface).

On Mon, 20 Jun 2011 19:09:49 GMT
bugzilla-daemon@bugzilla.kernel.org wrote:

> https://bugzilla.kernel.org/show_bug.cgi?id=37992
> 
>            Summary: It's not possible to compile kernel if
>                     CONFIG_NETCONSOLE_DYNAMIC is turned on
>            Product: Drivers
>            Version: 2.5
>     Kernel Version: 3.0-rc3+
>           Platform: All
>         OS/Version: Linux
>               Tree: Mainline
>             Status: NEW
>           Severity: high
>           Priority: P1
>          Component: Network
>         AssignedTo: drivers_network@kernel-bugs.osdl.org
>         ReportedBy: hilld@binarystorm.net
>         Regression: No
> 
> 
> Hello guys,
> 
>     It's not possible to compile kernel if CONFIG_NETCONSOLE_DYNAMIC is turned
> on ...
> 
> drivers/built-in.o: In function `netconsole_target_put':
> /usr/src/linux-3.0/drivers/net/netconsole.c:133: undefined reference to
> `config_item_put'
> drivers/built-in.o: In function `netconsole_target_get':
> /usr/src/linux-3.0/drivers/net/netconsole.c:127: undefined reference to
> `config_item_get'
> drivers/built-in.o: In function `netconsole_target_put':
> /usr/src/linux-3.0/drivers/net/netconsole.c:133: undefined reference to
> `config_item_put'
> drivers/built-in.o: In function `netconsole_target_get':
> /usr/src/linux-3.0/drivers/net/netconsole.c:127: undefined reference to
> `config_item_get'
> drivers/built-in.o: In function `netconsole_target_put':
> /usr/src/linux-3.0/drivers/net/netconsole.c:133: undefined reference to
> `config_item_put'
> drivers/built-in.o: In function `drop_netconsole_target':
> /usr/src/linux-3.0/drivers/net/netconsole.c:588: undefined reference to
> `config_item_put'
> drivers/built-in.o: In function `make_netconsole_target':
> /usr/src/linux-3.0/drivers/net/netconsole.c:561: undefined reference to
> `config_item_init_type_name'
> drivers/built-in.o: In function `dynamic_netconsole_init':
> /usr/src/linux-3.0/drivers/net/netconsole.c:109: undefined reference to
> `config_group_init'
> /usr/src/linux-3.0/drivers/net/netconsole.c:111: undefined reference to
> `configfs_register_subsystem'
> drivers/built-in.o: In function `dynamic_netconsole_exit':
> /usr/src/linux-3.0/drivers/net/netconsole.c:116: undefined reference to
> `configfs_unregister_subsystem'
> make: *** [.tmp_vmlinux1] Error 1


^ permalink raw reply

* Re: [RFT PATCH 0/9] Cleanup and extension of netdev features
From: David Miller @ 2011-06-20 19:35 UTC (permalink / raw)
  To: mirq-linux; +Cc: netdev, bhutchings
In-Reply-To: <cover.1308596962.git.mirq-linux@rere.qmqm.pl>


Patch #1 was not sent out.

^ permalink raw reply

* [PATCH] myri_sbus: remove driver
From: Jon Mason @ 2011-06-20 19:39 UTC (permalink / raw)
  To: David Miller; +Cc: netdev, Jeff Kirsher, Andrew Gallatin

Remove the myri_sbus driver. Why?
* There is no possibility of ethernet mode on this adapter, so it's
  Myrinet only.
* It won't inter-op with modern versions of Myrinet, and thus can only
  work with legacy adapters.
* There are no in-kernel Linux drivers for the PCI version of this
  adapter, so it only can work on ~15 year old Sun hardware.

It's long in the tooth, let's take it to the knackers.

Signed-off-by: Jon Mason <mason@myri.com>
---
 drivers/net/Kconfig     |    9 -
 drivers/net/Makefile    |    1 -
 drivers/net/myri_sbus.c | 1187 -----------------------------------------------
 drivers/net/myri_sbus.h |  311 -------------
 4 files changed, 0 insertions(+), 1508 deletions(-)
 delete mode 100644 drivers/net/myri_sbus.c
 delete mode 100644 drivers/net/myri_sbus.h

diff --git a/drivers/net/Kconfig b/drivers/net/Kconfig
index 399cf4b..f5919c2 100644
--- a/drivers/net/Kconfig
+++ b/drivers/net/Kconfig
@@ -2196,15 +2196,6 @@ config IGBVF
 
 source "drivers/net/ixp2000/Kconfig"
 
-config MYRI_SBUS
-	tristate "MyriCOM Gigabit Ethernet support"
-	depends on SBUS
-	help
-	  This driver supports MyriCOM Sbus gigabit Ethernet cards.
-
-	  To compile this driver as a module, choose M here: the module
-	  will be called myri_sbus.  This is recommended.
-
 config NS83820
 	tristate "National Semiconductor DP83820 support"
 	depends on PCI
diff --git a/drivers/net/Makefile b/drivers/net/Makefile
index 8006841..86f6c8d 100644
--- a/drivers/net/Makefile
+++ b/drivers/net/Makefile
@@ -59,7 +59,6 @@ obj-$(CONFIG_HAPPYMEAL) += sunhme.o
 obj-$(CONFIG_SUNLANCE) += sunlance.o
 obj-$(CONFIG_SUNQE) += sunqe.o
 obj-$(CONFIG_SUNBMAC) += sunbmac.o
-obj-$(CONFIG_MYRI_SBUS) += myri_sbus.o
 obj-$(CONFIG_SUNGEM) += sungem.o sungem_phy.o
 obj-$(CONFIG_CASSINI) += cassini.o
 obj-$(CONFIG_SUNVNET) += sunvnet.o
diff --git a/drivers/net/myri_sbus.c b/drivers/net/myri_sbus.c
deleted file mode 100644
index 53aeea4..0000000
--- a/drivers/net/myri_sbus.c
+++ /dev/null
@@ -1,1187 +0,0 @@
-/* myri_sbus.c: MyriCOM MyriNET SBUS card driver.
- *
- * Copyright (C) 1996, 1999, 2006, 2008 David S. Miller (davem@davemloft.net)
- */
-
-static char version[] =
-        "myri_sbus.c:v2.0 June 23, 2006 David S. Miller (davem@davemloft.net)\n";
-
-#include <linux/module.h>
-#include <linux/errno.h>
-#include <linux/kernel.h>
-#include <linux/types.h>
-#include <linux/fcntl.h>
-#include <linux/interrupt.h>
-#include <linux/ioport.h>
-#include <linux/in.h>
-#include <linux/string.h>
-#include <linux/delay.h>
-#include <linux/init.h>
-#include <linux/netdevice.h>
-#include <linux/etherdevice.h>
-#include <linux/skbuff.h>
-#include <linux/bitops.h>
-#include <linux/dma-mapping.h>
-#include <linux/of.h>
-#include <linux/of_device.h>
-#include <linux/firmware.h>
-#include <linux/gfp.h>
-
-#include <net/dst.h>
-#include <net/arp.h>
-#include <net/sock.h>
-#include <net/ipv6.h>
-
-#include <asm/system.h>
-#include <asm/io.h>
-#include <asm/dma.h>
-#include <asm/byteorder.h>
-#include <asm/idprom.h>
-#include <asm/openprom.h>
-#include <asm/oplib.h>
-#include <asm/auxio.h>
-#include <asm/pgtable.h>
-#include <asm/irq.h>
-
-#include "myri_sbus.h"
-
-/* #define DEBUG_DETECT */
-/* #define DEBUG_IRQ */
-/* #define DEBUG_TRANSMIT */
-/* #define DEBUG_RECEIVE */
-/* #define DEBUG_HEADER */
-
-#ifdef DEBUG_DETECT
-#define DET(x)   printk x
-#else
-#define DET(x)
-#endif
-
-#ifdef DEBUG_IRQ
-#define DIRQ(x)  printk x
-#else
-#define DIRQ(x)
-#endif
-
-#ifdef DEBUG_TRANSMIT
-#define DTX(x)  printk x
-#else
-#define DTX(x)
-#endif
-
-#ifdef DEBUG_RECEIVE
-#define DRX(x)  printk x
-#else
-#define DRX(x)
-#endif
-
-#ifdef DEBUG_HEADER
-#define DHDR(x) printk x
-#else
-#define DHDR(x)
-#endif
-
-/* Firmware name */
-#define FWNAME		"myricom/lanai.bin"
-
-static void myri_reset_off(void __iomem *lp, void __iomem *cregs)
-{
-	/* Clear IRQ mask. */
-	sbus_writel(0, lp + LANAI_EIMASK);
-
-	/* Turn RESET function off. */
-	sbus_writel(CONTROL_ROFF, cregs + MYRICTRL_CTRL);
-}
-
-static void myri_reset_on(void __iomem *cregs)
-{
-	/* Enable RESET function. */
-	sbus_writel(CONTROL_RON, cregs + MYRICTRL_CTRL);
-
-	/* Disable IRQ's. */
-	sbus_writel(CONTROL_DIRQ, cregs + MYRICTRL_CTRL);
-}
-
-static void myri_disable_irq(void __iomem *lp, void __iomem *cregs)
-{
-	sbus_writel(CONTROL_DIRQ, cregs + MYRICTRL_CTRL);
-	sbus_writel(0, lp + LANAI_EIMASK);
-	sbus_writel(ISTAT_HOST, lp + LANAI_ISTAT);
-}
-
-static void myri_enable_irq(void __iomem *lp, void __iomem *cregs)
-{
-	sbus_writel(CONTROL_EIRQ, cregs + MYRICTRL_CTRL);
-	sbus_writel(ISTAT_HOST, lp + LANAI_EIMASK);
-}
-
-static inline void bang_the_chip(struct myri_eth *mp)
-{
-	struct myri_shmem __iomem *shmem = mp->shmem;
-	void __iomem *cregs		= mp->cregs;
-
-	sbus_writel(1, &shmem->send);
-	sbus_writel(CONTROL_WON, cregs + MYRICTRL_CTRL);
-}
-
-static int myri_do_handshake(struct myri_eth *mp)
-{
-	struct myri_shmem __iomem *shmem = mp->shmem;
-	void __iomem *cregs = mp->cregs;
-	struct myri_channel __iomem *chan = &shmem->channel;
-	int tick 			= 0;
-
-	DET(("myri_do_handshake: "));
-	if (sbus_readl(&chan->state) == STATE_READY) {
-		DET(("Already STATE_READY, failed.\n"));
-		return -1;	/* We're hosed... */
-	}
-
-	myri_disable_irq(mp->lregs, cregs);
-
-	while (tick++ < 25) {
-		u32 softstate;
-
-		/* Wake it up. */
-		DET(("shakedown, CONTROL_WON, "));
-		sbus_writel(1, &shmem->shakedown);
-		sbus_writel(CONTROL_WON, cregs + MYRICTRL_CTRL);
-
-		softstate = sbus_readl(&chan->state);
-		DET(("chanstate[%08x] ", softstate));
-		if (softstate == STATE_READY) {
-			DET(("wakeup successful, "));
-			break;
-		}
-
-		if (softstate != STATE_WFN) {
-			DET(("not WFN setting that, "));
-			sbus_writel(STATE_WFN, &chan->state);
-		}
-
-		udelay(20);
-	}
-
-	myri_enable_irq(mp->lregs, cregs);
-
-	if (tick > 25) {
-		DET(("25 ticks we lose, failure.\n"));
-		return -1;
-	}
-	DET(("success\n"));
-	return 0;
-}
-
-static int __devinit myri_load_lanai(struct myri_eth *mp)
-{
-	const struct firmware	*fw;
-	struct net_device	*dev = mp->dev;
-	struct myri_shmem __iomem *shmem = mp->shmem;
-	void __iomem		*rptr;
-	int 			i, lanai4_data_size;
-
-	myri_disable_irq(mp->lregs, mp->cregs);
-	myri_reset_on(mp->cregs);
-
-	rptr = mp->lanai;
-	for (i = 0; i < mp->eeprom.ramsz; i++)
-		sbus_writeb(0, rptr + i);
-
-	if (mp->eeprom.cpuvers >= CPUVERS_3_0)
-		sbus_writel(mp->eeprom.cval, mp->lregs + LANAI_CVAL);
-
-	i = request_firmware(&fw, FWNAME, &mp->myri_op->dev);
-	if (i) {
-		printk(KERN_ERR "Failed to load image \"%s\" err %d\n",
-		       FWNAME, i);
-		return i;
-	}
-	if (fw->size < 2) {
-		printk(KERN_ERR "Bogus length %zu in image \"%s\"\n",
-		       fw->size, FWNAME);
-		release_firmware(fw);
-		return -EINVAL;
-	}
-	lanai4_data_size = fw->data[0] << 8 | fw->data[1];
-
-	/* Load executable code. */
-	for (i = 2; i < fw->size; i++)
-		sbus_writeb(fw->data[i], rptr++);
-
-	/* Load data segment. */
-	for (i = 0; i < lanai4_data_size; i++)
-		sbus_writeb(0, rptr++);
-
-	/* Set device address. */
-	sbus_writeb(0, &shmem->addr[0]);
-	sbus_writeb(0, &shmem->addr[1]);
-	for (i = 0; i < 6; i++)
-		sbus_writeb(dev->dev_addr[i],
-			    &shmem->addr[i + 2]);
-
-	/* Set SBUS bursts and interrupt mask. */
-	sbus_writel(((mp->myri_bursts & 0xf8) >> 3), &shmem->burst);
-	sbus_writel(SHMEM_IMASK_RX, &shmem->imask);
-
-	/* Release the LANAI. */
-	myri_disable_irq(mp->lregs, mp->cregs);
-	myri_reset_off(mp->lregs, mp->cregs);
-	myri_disable_irq(mp->lregs, mp->cregs);
-
-	/* Wait for the reset to complete. */
-	for (i = 0; i < 5000; i++) {
-		if (sbus_readl(&shmem->channel.state) != STATE_READY)
-			break;
-		else
-			udelay(10);
-	}
-
-	if (i == 5000)
-		printk(KERN_ERR "myricom: Chip would not reset after firmware load.\n");
-
-	i = myri_do_handshake(mp);
-	if (i)
-		printk(KERN_ERR "myricom: Handshake with LANAI failed.\n");
-
-	if (mp->eeprom.cpuvers == CPUVERS_4_0)
-		sbus_writel(0, mp->lregs + LANAI_VERS);
-
-	release_firmware(fw);
-	return i;
-}
-
-static void myri_clean_rings(struct myri_eth *mp)
-{
-	struct sendq __iomem *sq = mp->sq;
-	struct recvq __iomem *rq = mp->rq;
-	int i;
-
-	sbus_writel(0, &rq->tail);
-	sbus_writel(0, &rq->head);
-	for (i = 0; i < (RX_RING_SIZE+1); i++) {
-		if (mp->rx_skbs[i] != NULL) {
-			struct myri_rxd __iomem *rxd = &rq->myri_rxd[i];
-			u32 dma_addr;
-
-			dma_addr = sbus_readl(&rxd->myri_scatters[0].addr);
-			dma_unmap_single(&mp->myri_op->dev, dma_addr,
-					 RX_ALLOC_SIZE, DMA_FROM_DEVICE);
-			dev_kfree_skb(mp->rx_skbs[i]);
-			mp->rx_skbs[i] = NULL;
-		}
-	}
-
-	mp->tx_old = 0;
-	sbus_writel(0, &sq->tail);
-	sbus_writel(0, &sq->head);
-	for (i = 0; i < TX_RING_SIZE; i++) {
-		if (mp->tx_skbs[i] != NULL) {
-			struct sk_buff *skb = mp->tx_skbs[i];
-			struct myri_txd __iomem *txd = &sq->myri_txd[i];
-			u32 dma_addr;
-
-			dma_addr = sbus_readl(&txd->myri_gathers[0].addr);
-			dma_unmap_single(&mp->myri_op->dev, dma_addr,
-					 (skb->len + 3) & ~3,
-					 DMA_TO_DEVICE);
-			dev_kfree_skb(mp->tx_skbs[i]);
-			mp->tx_skbs[i] = NULL;
-		}
-	}
-}
-
-static void myri_init_rings(struct myri_eth *mp, int from_irq)
-{
-	struct recvq __iomem *rq = mp->rq;
-	struct myri_rxd __iomem *rxd = &rq->myri_rxd[0];
-	struct net_device *dev = mp->dev;
-	gfp_t gfp_flags = GFP_KERNEL;
-	int i;
-
-	if (from_irq || in_interrupt())
-		gfp_flags = GFP_ATOMIC;
-
-	myri_clean_rings(mp);
-	for (i = 0; i < RX_RING_SIZE; i++) {
-		struct sk_buff *skb = myri_alloc_skb(RX_ALLOC_SIZE, gfp_flags);
-		u32 dma_addr;
-
-		if (!skb)
-			continue;
-		mp->rx_skbs[i] = skb;
-		skb->dev = dev;
-		skb_put(skb, RX_ALLOC_SIZE);
-
-		dma_addr = dma_map_single(&mp->myri_op->dev,
-					  skb->data, RX_ALLOC_SIZE,
-					  DMA_FROM_DEVICE);
-		sbus_writel(dma_addr, &rxd[i].myri_scatters[0].addr);
-		sbus_writel(RX_ALLOC_SIZE, &rxd[i].myri_scatters[0].len);
-		sbus_writel(i, &rxd[i].ctx);
-		sbus_writel(1, &rxd[i].num_sg);
-	}
-	sbus_writel(0, &rq->head);
-	sbus_writel(RX_RING_SIZE, &rq->tail);
-}
-
-static int myri_init(struct myri_eth *mp, int from_irq)
-{
-	myri_init_rings(mp, from_irq);
-	return 0;
-}
-
-static void myri_is_not_so_happy(struct myri_eth *mp)
-{
-}
-
-#ifdef DEBUG_HEADER
-static void dump_ehdr(struct ethhdr *ehdr)
-{
-	printk("ehdr[h_dst(%pM)"
-	       "h_source(%pM)"
-	       "h_proto(%04x)]\n",
-	       ehdr->h_dest, ehdr->h_source, ehdr->h_proto);
-}
-
-static void dump_ehdr_and_myripad(unsigned char *stuff)
-{
-	struct ethhdr *ehdr = (struct ethhdr *) (stuff + 2);
-
-	printk("pad[%02x:%02x]", stuff[0], stuff[1]);
-	dump_ehdr(ehdr);
-}
-#endif
-
-static void myri_tx(struct myri_eth *mp, struct net_device *dev)
-{
-	struct sendq __iomem *sq= mp->sq;
-	int entry		= mp->tx_old;
-	int limit		= sbus_readl(&sq->head);
-
-	DTX(("entry[%d] limit[%d] ", entry, limit));
-	if (entry == limit)
-		return;
-	while (entry != limit) {
-		struct sk_buff *skb = mp->tx_skbs[entry];
-		u32 dma_addr;
-
-		DTX(("SKB[%d] ", entry));
-		dma_addr = sbus_readl(&sq->myri_txd[entry].myri_gathers[0].addr);
-		dma_unmap_single(&mp->myri_op->dev, dma_addr,
-				 skb->len, DMA_TO_DEVICE);
-		dev_kfree_skb(skb);
-		mp->tx_skbs[entry] = NULL;
-		dev->stats.tx_packets++;
-		entry = NEXT_TX(entry);
-	}
-	mp->tx_old = entry;
-}
-
-/* Determine the packet's protocol ID. The rule here is that we
- * assume 802.3 if the type field is short enough to be a length.
- * This is normal practice and works for any 'now in use' protocol.
- */
-static __be16 myri_type_trans(struct sk_buff *skb, struct net_device *dev)
-{
-	struct ethhdr *eth;
-	unsigned char *rawp;
-
-	skb_set_mac_header(skb, MYRI_PAD_LEN);
-	skb_pull(skb, dev->hard_header_len);
-	eth = eth_hdr(skb);
-
-#ifdef DEBUG_HEADER
-	DHDR(("myri_type_trans: "));
-	dump_ehdr(eth);
-#endif
-	if (*eth->h_dest & 1) {
-		if (memcmp(eth->h_dest, dev->broadcast, ETH_ALEN)==0)
-			skb->pkt_type = PACKET_BROADCAST;
-		else
-			skb->pkt_type = PACKET_MULTICAST;
-	} else if (dev->flags & (IFF_PROMISC|IFF_ALLMULTI)) {
-		if (memcmp(eth->h_dest, dev->dev_addr, ETH_ALEN))
-			skb->pkt_type = PACKET_OTHERHOST;
-	}
-
-	if (ntohs(eth->h_proto) >= 1536)
-		return eth->h_proto;
-
-	rawp = skb->data;
-
-	/* This is a magic hack to spot IPX packets. Older Novell breaks
-	 * the protocol design and runs IPX over 802.3 without an 802.2 LLC
-	 * layer. We look for FFFF which isn't a used 802.2 SSAP/DSAP. This
-	 * won't work for fault tolerant netware but does for the rest.
-	 */
-	if (*(unsigned short *)rawp == 0xFFFF)
-		return htons(ETH_P_802_3);
-
-	/* Real 802.2 LLC */
-	return htons(ETH_P_802_2);
-}
-
-static void myri_rx(struct myri_eth *mp, struct net_device *dev)
-{
-	struct recvq __iomem *rq = mp->rq;
-	struct recvq __iomem *rqa = mp->rqack;
-	int entry		= sbus_readl(&rqa->head);
-	int limit		= sbus_readl(&rqa->tail);
-	int drops;
-
-	DRX(("entry[%d] limit[%d] ", entry, limit));
-	if (entry == limit)
-		return;
-	drops = 0;
-	DRX(("\n"));
-	while (entry != limit) {
-		struct myri_rxd __iomem *rxdack = &rqa->myri_rxd[entry];
-		u32 csum		= sbus_readl(&rxdack->csum);
-		int len			= sbus_readl(&rxdack->myri_scatters[0].len);
-		int index		= sbus_readl(&rxdack->ctx);
-		struct myri_rxd __iomem *rxd = &rq->myri_rxd[sbus_readl(&rq->tail)];
-		struct sk_buff *skb	= mp->rx_skbs[index];
-
-		/* Ack it. */
-		sbus_writel(NEXT_RX(entry), &rqa->head);
-
-		/* Check for errors. */
-		DRX(("rxd[%d]: %p len[%d] csum[%08x] ", entry, rxd, len, csum));
-		dma_sync_single_for_cpu(&mp->myri_op->dev,
-					sbus_readl(&rxd->myri_scatters[0].addr),
-					RX_ALLOC_SIZE, DMA_FROM_DEVICE);
-		if (len < (ETH_HLEN + MYRI_PAD_LEN) || (skb->data[0] != MYRI_PAD_LEN)) {
-			DRX(("ERROR["));
-			dev->stats.rx_errors++;
-			if (len < (ETH_HLEN + MYRI_PAD_LEN)) {
-				DRX(("BAD_LENGTH] "));
-				dev->stats.rx_length_errors++;
-			} else {
-				DRX(("NO_PADDING] "));
-				dev->stats.rx_frame_errors++;
-			}
-
-			/* Return it to the LANAI. */
-	drop_it:
-			drops++;
-			DRX(("DROP "));
-			dev->stats.rx_dropped++;
-			dma_sync_single_for_device(&mp->myri_op->dev,
-						   sbus_readl(&rxd->myri_scatters[0].addr),
-						   RX_ALLOC_SIZE,
-						   DMA_FROM_DEVICE);
-			sbus_writel(RX_ALLOC_SIZE, &rxd->myri_scatters[0].len);
-			sbus_writel(index, &rxd->ctx);
-			sbus_writel(1, &rxd->num_sg);
-			sbus_writel(NEXT_RX(sbus_readl(&rq->tail)), &rq->tail);
-			goto next;
-		}
-
-		DRX(("len[%d] ", len));
-		if (len > RX_COPY_THRESHOLD) {
-			struct sk_buff *new_skb;
-			u32 dma_addr;
-
-			DRX(("BIGBUFF "));
-			new_skb = myri_alloc_skb(RX_ALLOC_SIZE, GFP_ATOMIC);
-			if (new_skb == NULL) {
-				DRX(("skb_alloc(FAILED) "));
-				goto drop_it;
-			}
-			dma_unmap_single(&mp->myri_op->dev,
-					 sbus_readl(&rxd->myri_scatters[0].addr),
-					 RX_ALLOC_SIZE,
-					 DMA_FROM_DEVICE);
-			mp->rx_skbs[index] = new_skb;
-			new_skb->dev = dev;
-			skb_put(new_skb, RX_ALLOC_SIZE);
-			dma_addr = dma_map_single(&mp->myri_op->dev,
-						  new_skb->data,
-						  RX_ALLOC_SIZE,
-						  DMA_FROM_DEVICE);
-			sbus_writel(dma_addr, &rxd->myri_scatters[0].addr);
-			sbus_writel(RX_ALLOC_SIZE, &rxd->myri_scatters[0].len);
-			sbus_writel(index, &rxd->ctx);
-			sbus_writel(1, &rxd->num_sg);
-			sbus_writel(NEXT_RX(sbus_readl(&rq->tail)), &rq->tail);
-
-			/* Trim the original skb for the netif. */
-			DRX(("trim(%d) ", len));
-			skb_trim(skb, len);
-		} else {
-			struct sk_buff *copy_skb = dev_alloc_skb(len);
-
-			DRX(("SMALLBUFF "));
-			if (copy_skb == NULL) {
-				DRX(("dev_alloc_skb(FAILED) "));
-				goto drop_it;
-			}
-			/* DMA sync already done above. */
-			copy_skb->dev = dev;
-			DRX(("resv_and_put "));
-			skb_put(copy_skb, len);
-			skb_copy_from_linear_data(skb, copy_skb->data, len);
-
-			/* Reuse original ring buffer. */
-			DRX(("reuse "));
-			dma_sync_single_for_device(&mp->myri_op->dev,
-						   sbus_readl(&rxd->myri_scatters[0].addr),
-						   RX_ALLOC_SIZE,
-						   DMA_FROM_DEVICE);
-			sbus_writel(RX_ALLOC_SIZE, &rxd->myri_scatters[0].len);
-			sbus_writel(index, &rxd->ctx);
-			sbus_writel(1, &rxd->num_sg);
-			sbus_writel(NEXT_RX(sbus_readl(&rq->tail)), &rq->tail);
-
-			skb = copy_skb;
-		}
-
-		/* Just like the happy meal we get checksums from this card. */
-		skb->csum = csum;
-		skb->ip_summed = CHECKSUM_UNNECESSARY; /* XXX */
-
-		skb->protocol = myri_type_trans(skb, dev);
-		DRX(("prot[%04x] netif_rx ", skb->protocol));
-		netif_rx(skb);
-
-		dev->stats.rx_packets++;
-		dev->stats.rx_bytes += len;
-	next:
-		DRX(("NEXT\n"));
-		entry = NEXT_RX(entry);
-	}
-}
-
-static irqreturn_t myri_interrupt(int irq, void *dev_id)
-{
-	struct net_device *dev		= (struct net_device *) dev_id;
-	struct myri_eth *mp		= netdev_priv(dev);
-	void __iomem *lregs		= mp->lregs;
-	struct myri_channel __iomem *chan = &mp->shmem->channel;
-	unsigned long flags;
-	u32 status;
-	int handled = 0;
-
-	spin_lock_irqsave(&mp->irq_lock, flags);
-
-	status = sbus_readl(lregs + LANAI_ISTAT);
-	DIRQ(("myri_interrupt: status[%08x] ", status));
-	if (status & ISTAT_HOST) {
-		u32 softstate;
-
-		handled = 1;
-		DIRQ(("IRQ_DISAB "));
-		myri_disable_irq(lregs, mp->cregs);
-		softstate = sbus_readl(&chan->state);
-		DIRQ(("state[%08x] ", softstate));
-		if (softstate != STATE_READY) {
-			DIRQ(("myri_not_so_happy "));
-			myri_is_not_so_happy(mp);
-		}
-		DIRQ(("\nmyri_rx: "));
-		myri_rx(mp, dev);
-		DIRQ(("\nistat=ISTAT_HOST "));
-		sbus_writel(ISTAT_HOST, lregs + LANAI_ISTAT);
-		DIRQ(("IRQ_ENAB "));
-		myri_enable_irq(lregs, mp->cregs);
-	}
-	DIRQ(("\n"));
-
-	spin_unlock_irqrestore(&mp->irq_lock, flags);
-
-	return IRQ_RETVAL(handled);
-}
-
-static int myri_open(struct net_device *dev)
-{
-	struct myri_eth *mp = netdev_priv(dev);
-
-	return myri_init(mp, in_interrupt());
-}
-
-static int myri_close(struct net_device *dev)
-{
-	struct myri_eth *mp = netdev_priv(dev);
-
-	myri_clean_rings(mp);
-	return 0;
-}
-
-static void myri_tx_timeout(struct net_device *dev)
-{
-	struct myri_eth *mp = netdev_priv(dev);
-
-	printk(KERN_ERR "%s: transmit timed out, resetting\n", dev->name);
-
-	dev->stats.tx_errors++;
-	myri_init(mp, 0);
-	netif_wake_queue(dev);
-}
-
-static int myri_start_xmit(struct sk_buff *skb, struct net_device *dev)
-{
-	struct myri_eth *mp = netdev_priv(dev);
-	struct sendq __iomem *sq = mp->sq;
-	struct myri_txd __iomem *txd;
-	unsigned long flags;
-	unsigned int head, tail;
-	int len, entry;
-	u32 dma_addr;
-
-	DTX(("myri_start_xmit: "));
-
-	myri_tx(mp, dev);
-
-	netif_stop_queue(dev);
-
-	/* This is just to prevent multiple PIO reads for TX_BUFFS_AVAIL. */
-	head = sbus_readl(&sq->head);
-	tail = sbus_readl(&sq->tail);
-
-	if (!TX_BUFFS_AVAIL(head, tail)) {
-		DTX(("no buffs available, returning 1\n"));
-		return NETDEV_TX_BUSY;
-	}
-
-	spin_lock_irqsave(&mp->irq_lock, flags);
-
-	DHDR(("xmit[skbdata(%p)]\n", skb->data));
-#ifdef DEBUG_HEADER
-	dump_ehdr_and_myripad(((unsigned char *) skb->data));
-#endif
-
-	/* XXX Maybe this can go as well. */
-	len = skb->len;
-	if (len & 3) {
-		DTX(("len&3 "));
-		len = (len + 4) & (~3);
-	}
-
-	entry = sbus_readl(&sq->tail);
-
-	txd = &sq->myri_txd[entry];
-	mp->tx_skbs[entry] = skb;
-
-	/* Must do this before we sbus map it. */
-	if (skb->data[MYRI_PAD_LEN] & 0x1) {
-		sbus_writew(0xffff, &txd->addr[0]);
-		sbus_writew(0xffff, &txd->addr[1]);
-		sbus_writew(0xffff, &txd->addr[2]);
-		sbus_writew(0xffff, &txd->addr[3]);
-	} else {
-		sbus_writew(0xffff, &txd->addr[0]);
-		sbus_writew((skb->data[0] << 8) | skb->data[1], &txd->addr[1]);
-		sbus_writew((skb->data[2] << 8) | skb->data[3], &txd->addr[2]);
-		sbus_writew((skb->data[4] << 8) | skb->data[5], &txd->addr[3]);
-	}
-
-	dma_addr = dma_map_single(&mp->myri_op->dev, skb->data,
-				  len, DMA_TO_DEVICE);
-	sbus_writel(dma_addr, &txd->myri_gathers[0].addr);
-	sbus_writel(len, &txd->myri_gathers[0].len);
-	sbus_writel(1, &txd->num_sg);
-	sbus_writel(KERNEL_CHANNEL, &txd->chan);
-	sbus_writel(len, &txd->len);
-	sbus_writel((u32)-1, &txd->csum_off);
-	sbus_writel(0, &txd->csum_field);
-
-	sbus_writel(NEXT_TX(entry), &sq->tail);
-	DTX(("BangTheChip "));
-	bang_the_chip(mp);
-
-	DTX(("tbusy=0, returning 0\n"));
-	netif_start_queue(dev);
-	spin_unlock_irqrestore(&mp->irq_lock, flags);
-	return NETDEV_TX_OK;
-}
-
-/* Create the MyriNet MAC header for an arbitrary protocol layer
- *
- * saddr=NULL	means use device source address
- * daddr=NULL	means leave destination address (eg unresolved arp)
- */
-static int myri_header(struct sk_buff *skb, struct net_device *dev,
-		       unsigned short type, const void *daddr,
-		       const void *saddr, unsigned len)
-{
-	struct ethhdr *eth = (struct ethhdr *) skb_push(skb, ETH_HLEN);
-	unsigned char *pad = (unsigned char *) skb_push(skb, MYRI_PAD_LEN);
-
-#ifdef DEBUG_HEADER
-	DHDR(("myri_header: pad[%02x,%02x] ", pad[0], pad[1]));
-	dump_ehdr(eth);
-#endif
-
-	/* Set the MyriNET padding identifier. */
-	pad[0] = MYRI_PAD_LEN;
-	pad[1] = 0xab;
-
-	/* Set the protocol type. For a packet of type ETH_P_802_3/2 we put the
-	 * length in here instead.
-	 */
-	if (type != ETH_P_802_3 && type != ETH_P_802_2)
-		eth->h_proto = htons(type);
-	else
-		eth->h_proto = htons(len);
-
-	/* Set the source hardware address. */
-	if (saddr)
-		memcpy(eth->h_source, saddr, dev->addr_len);
-	else
-		memcpy(eth->h_source, dev->dev_addr, dev->addr_len);
-
-	/* Anyway, the loopback-device should never use this function... */
-	if (dev->flags & IFF_LOOPBACK) {
-		int i;
-		for (i = 0; i < dev->addr_len; i++)
-			eth->h_dest[i] = 0;
-		return dev->hard_header_len;
-	}
-
-	if (daddr) {
-		memcpy(eth->h_dest, daddr, dev->addr_len);
-		return dev->hard_header_len;
-	}
-	return -dev->hard_header_len;
-}
-
-/* Rebuild the MyriNet MAC header. This is called after an ARP
- * (or in future other address resolution) has completed on this
- * sk_buff. We now let ARP fill in the other fields.
- */
-static int myri_rebuild_header(struct sk_buff *skb)
-{
-	unsigned char *pad = (unsigned char *) skb->data;
-	struct ethhdr *eth = (struct ethhdr *) (pad + MYRI_PAD_LEN);
-	struct net_device *dev = skb->dev;
-
-#ifdef DEBUG_HEADER
-	DHDR(("myri_rebuild_header: pad[%02x,%02x] ", pad[0], pad[1]));
-	dump_ehdr(eth);
-#endif
-
-	/* Refill MyriNet padding identifiers, this is just being anal. */
-	pad[0] = MYRI_PAD_LEN;
-	pad[1] = 0xab;
-
-	switch (eth->h_proto)
-	{
-#ifdef CONFIG_INET
-	case cpu_to_be16(ETH_P_IP):
- 		return arp_find(eth->h_dest, skb);
-#endif
-
-	default:
-		printk(KERN_DEBUG
-		       "%s: unable to resolve type %X addresses.\n",
-		       dev->name, (int)eth->h_proto);
-
-		memcpy(eth->h_source, dev->dev_addr, dev->addr_len);
-		return 0;
-		break;
-	}
-
-	return 0;
-}
-
-static int myri_header_cache(const struct neighbour *neigh, struct hh_cache *hh)
-{
-	unsigned short type = hh->hh_type;
-	unsigned char *pad;
-	struct ethhdr *eth;
-	const struct net_device *dev = neigh->dev;
-
-	pad = ((unsigned char *) hh->hh_data) +
-		HH_DATA_OFF(sizeof(*eth) + MYRI_PAD_LEN);
-	eth = (struct ethhdr *) (pad + MYRI_PAD_LEN);
-
-	if (type == htons(ETH_P_802_3))
-		return -1;
-
-	/* Refill MyriNet padding identifiers, this is just being anal. */
-	pad[0] = MYRI_PAD_LEN;
-	pad[1] = 0xab;
-
-	eth->h_proto = type;
-	memcpy(eth->h_source, dev->dev_addr, dev->addr_len);
-	memcpy(eth->h_dest, neigh->ha, dev->addr_len);
-	hh->hh_len = 16;
-	return 0;
-}
-
-
-/* Called by Address Resolution module to notify changes in address. */
-void myri_header_cache_update(struct hh_cache *hh,
-			      const struct net_device *dev,
-			      const unsigned char * haddr)
-{
-	memcpy(((u8*)hh->hh_data) + HH_DATA_OFF(sizeof(struct ethhdr)),
-	       haddr, dev->addr_len);
-}
-
-static int myri_change_mtu(struct net_device *dev, int new_mtu)
-{
-	if ((new_mtu < (ETH_HLEN + MYRI_PAD_LEN)) || (new_mtu > MYRINET_MTU))
-		return -EINVAL;
-	dev->mtu = new_mtu;
-	return 0;
-}
-
-static void myri_set_multicast(struct net_device *dev)
-{
-	/* Do nothing, all MyriCOM nodes transmit multicast frames
-	 * as broadcast packets...
-	 */
-}
-
-static inline void set_boardid_from_idprom(struct myri_eth *mp, int num)
-{
-	mp->eeprom.id[0] = 0;
-	mp->eeprom.id[1] = idprom->id_machtype;
-	mp->eeprom.id[2] = (idprom->id_sernum >> 16) & 0xff;
-	mp->eeprom.id[3] = (idprom->id_sernum >> 8) & 0xff;
-	mp->eeprom.id[4] = (idprom->id_sernum >> 0) & 0xff;
-	mp->eeprom.id[5] = num;
-}
-
-static inline void determine_reg_space_size(struct myri_eth *mp)
-{
-	switch(mp->eeprom.cpuvers) {
-	case CPUVERS_2_3:
-	case CPUVERS_3_0:
-	case CPUVERS_3_1:
-	case CPUVERS_3_2:
-		mp->reg_size = (3 * 128 * 1024) + 4096;
-		break;
-
-	case CPUVERS_4_0:
-	case CPUVERS_4_1:
-		mp->reg_size = ((4096<<1) + mp->eeprom.ramsz);
-		break;
-
-	case CPUVERS_4_2:
-	case CPUVERS_5_0:
-	default:
-		printk("myricom: AIEEE weird cpu version %04x assuming pre4.0\n",
-		       mp->eeprom.cpuvers);
-		mp->reg_size = (3 * 128 * 1024) + 4096;
-	}
-}
-
-#ifdef DEBUG_DETECT
-static void dump_eeprom(struct myri_eth *mp)
-{
-	printk("EEPROM: clockval[%08x] cpuvers[%04x] "
-	       "id[%02x,%02x,%02x,%02x,%02x,%02x]\n",
-	       mp->eeprom.cval, mp->eeprom.cpuvers,
-	       mp->eeprom.id[0], mp->eeprom.id[1], mp->eeprom.id[2],
-	       mp->eeprom.id[3], mp->eeprom.id[4], mp->eeprom.id[5]);
-	printk("EEPROM: ramsz[%08x]\n", mp->eeprom.ramsz);
-	printk("EEPROM: fvers[%02x,%02x,%02x,%02x,%02x,%02x,%02x,%02x\n",
-	       mp->eeprom.fvers[0], mp->eeprom.fvers[1], mp->eeprom.fvers[2],
-	       mp->eeprom.fvers[3], mp->eeprom.fvers[4], mp->eeprom.fvers[5],
-	       mp->eeprom.fvers[6], mp->eeprom.fvers[7]);
-	printk("EEPROM:       %02x,%02x,%02x,%02x,%02x,%02x,%02x,%02x\n",
-	       mp->eeprom.fvers[8], mp->eeprom.fvers[9], mp->eeprom.fvers[10],
-	       mp->eeprom.fvers[11], mp->eeprom.fvers[12], mp->eeprom.fvers[13],
-	       mp->eeprom.fvers[14], mp->eeprom.fvers[15]);
-	printk("EEPROM:       %02x,%02x,%02x,%02x,%02x,%02x,%02x,%02x\n",
-	       mp->eeprom.fvers[16], mp->eeprom.fvers[17], mp->eeprom.fvers[18],
-	       mp->eeprom.fvers[19], mp->eeprom.fvers[20], mp->eeprom.fvers[21],
-	       mp->eeprom.fvers[22], mp->eeprom.fvers[23]);
-	printk("EEPROM:       %02x,%02x,%02x,%02x,%02x,%02x,%02x,%02x]\n",
-	       mp->eeprom.fvers[24], mp->eeprom.fvers[25], mp->eeprom.fvers[26],
-	       mp->eeprom.fvers[27], mp->eeprom.fvers[28], mp->eeprom.fvers[29],
-	       mp->eeprom.fvers[30], mp->eeprom.fvers[31]);
-	printk("EEPROM: mvers[%02x,%02x,%02x,%02x,%02x,%02x,%02x,%02x\n",
-	       mp->eeprom.mvers[0], mp->eeprom.mvers[1], mp->eeprom.mvers[2],
-	       mp->eeprom.mvers[3], mp->eeprom.mvers[4], mp->eeprom.mvers[5],
-	       mp->eeprom.mvers[6], mp->eeprom.mvers[7]);
-	printk("EEPROM:       %02x,%02x,%02x,%02x,%02x,%02x,%02x,%02x]\n",
-	       mp->eeprom.mvers[8], mp->eeprom.mvers[9], mp->eeprom.mvers[10],
-	       mp->eeprom.mvers[11], mp->eeprom.mvers[12], mp->eeprom.mvers[13],
-	       mp->eeprom.mvers[14], mp->eeprom.mvers[15]);
-	printk("EEPROM: dlval[%04x] brd_type[%04x] bus_type[%04x] prod_code[%04x]\n",
-	       mp->eeprom.dlval, mp->eeprom.brd_type, mp->eeprom.bus_type,
-	       mp->eeprom.prod_code);
-	printk("EEPROM: serial_num[%08x]\n", mp->eeprom.serial_num);
-}
-#endif
-
-static const struct header_ops myri_header_ops = {
-	.create		= myri_header,
-	.rebuild	= myri_rebuild_header,
-	.cache	 	= myri_header_cache,
-	.cache_update	= myri_header_cache_update,
-};
-
-static const struct net_device_ops myri_ops = {
-	.ndo_open		= myri_open,
-	.ndo_stop		= myri_close,
-	.ndo_start_xmit		= myri_start_xmit,
-	.ndo_set_multicast_list	= myri_set_multicast,
-	.ndo_tx_timeout		= myri_tx_timeout,
-	.ndo_change_mtu		= myri_change_mtu,
-	.ndo_set_mac_address	= eth_mac_addr,
-	.ndo_validate_addr	= eth_validate_addr,
-};
-
-static int __devinit myri_sbus_probe(struct platform_device *op)
-{
-	struct device_node *dp = op->dev.of_node;
-	static unsigned version_printed;
-	struct net_device *dev;
-	struct myri_eth *mp;
-	const void *prop;
-	static int num;
-	int i, len;
-
-	DET(("myri_ether_init(%p,%d):\n", op, num));
-	dev = alloc_etherdev(sizeof(struct myri_eth));
-	if (!dev)
-		return -ENOMEM;
-
-	if (version_printed++ == 0)
-		printk(version);
-
-	SET_NETDEV_DEV(dev, &op->dev);
-
-	mp = netdev_priv(dev);
-	spin_lock_init(&mp->irq_lock);
-	mp->myri_op = op;
-
-	/* Clean out skb arrays. */
-	for (i = 0; i < (RX_RING_SIZE + 1); i++)
-		mp->rx_skbs[i] = NULL;
-
-	for (i = 0; i < TX_RING_SIZE; i++)
-		mp->tx_skbs[i] = NULL;
-
-	/* First check for EEPROM information. */
-	prop = of_get_property(dp, "myrinet-eeprom-info", &len);
-
-	if (prop)
-		memcpy(&mp->eeprom, prop, sizeof(struct myri_eeprom));
-	if (!prop) {
-		/* No eeprom property, must cook up the values ourselves. */
-		DET(("No EEPROM: "));
-		mp->eeprom.bus_type = BUS_TYPE_SBUS;
-		mp->eeprom.cpuvers =
-			of_getintprop_default(dp, "cpu_version", 0);
-		mp->eeprom.cval =
-			of_getintprop_default(dp, "clock_value", 0);
-		mp->eeprom.ramsz = of_getintprop_default(dp, "sram_size", 0);
-		if (!mp->eeprom.cpuvers)
-			mp->eeprom.cpuvers = CPUVERS_2_3;
-		if (mp->eeprom.cpuvers < CPUVERS_3_0)
-			mp->eeprom.cval = 0;
-		if (!mp->eeprom.ramsz)
-			mp->eeprom.ramsz = (128 * 1024);
-
-		prop = of_get_property(dp, "myrinet-board-id", &len);
-		if (prop)
-			memcpy(&mp->eeprom.id[0], prop, 6);
-		else
-			set_boardid_from_idprom(mp, num);
-
-		prop = of_get_property(dp, "fpga_version", &len);
-		if (prop)
-			memcpy(&mp->eeprom.fvers[0], prop, 32);
-		else
-			memset(&mp->eeprom.fvers[0], 0, 32);
-
-		if (mp->eeprom.cpuvers == CPUVERS_4_1) {
-			if (mp->eeprom.ramsz == (128 * 1024))
-				mp->eeprom.ramsz = (256 * 1024);
-			if ((mp->eeprom.cval == 0x40414041) ||
-			    (mp->eeprom.cval == 0x90449044))
-				mp->eeprom.cval = 0x50e450e4;
-		}
-	}
-#ifdef DEBUG_DETECT
-	dump_eeprom(mp);
-#endif
-
-	for (i = 0; i < 6; i++)
-		dev->dev_addr[i] = mp->eeprom.id[i];
-
-	determine_reg_space_size(mp);
-
-	/* Map in the MyriCOM register/localram set. */
-	if (mp->eeprom.cpuvers < CPUVERS_4_0) {
-		/* XXX Makes no sense, if control reg is non-existent this
-		 * XXX driver cannot function at all... maybe pre-4.0 is
-		 * XXX only a valid version for PCI cards?  Ask feldy...
-		 */
-		DET(("Mapping regs for cpuvers < CPUVERS_4_0\n"));
-		mp->regs = of_ioremap(&op->resource[0], 0,
-				      mp->reg_size, "MyriCOM Regs");
-		if (!mp->regs) {
-			printk("MyriCOM: Cannot map MyriCOM registers.\n");
-			goto err;
-		}
-		mp->lanai = mp->regs + (256 * 1024);
-		mp->lregs = mp->lanai + (0x10000 * 2);
-	} else {
-		DET(("Mapping regs for cpuvers >= CPUVERS_4_0\n"));
-		mp->cregs = of_ioremap(&op->resource[0], 0,
-				       PAGE_SIZE, "MyriCOM Control Regs");
-		mp->lregs = of_ioremap(&op->resource[0], (256 * 1024),
-					 PAGE_SIZE, "MyriCOM LANAI Regs");
-		mp->lanai = of_ioremap(&op->resource[0], (512 * 1024),
-				       mp->eeprom.ramsz, "MyriCOM SRAM");
-	}
-	DET(("Registers mapped: cregs[%p] lregs[%p] lanai[%p]\n",
-	     mp->cregs, mp->lregs, mp->lanai));
-
-	if (mp->eeprom.cpuvers >= CPUVERS_4_0)
-		mp->shmem_base = 0xf000;
-	else
-		mp->shmem_base = 0x8000;
-
-	DET(("Shared memory base is %04x, ", mp->shmem_base));
-
-	mp->shmem = (struct myri_shmem __iomem *)
-		(mp->lanai + (mp->shmem_base * 2));
-	DET(("shmem mapped at %p\n", mp->shmem));
-
-	mp->rqack	= &mp->shmem->channel.recvqa;
-	mp->rq		= &mp->shmem->channel.recvq;
-	mp->sq		= &mp->shmem->channel.sendq;
-
-	/* Reset the board. */
-	DET(("Resetting LANAI\n"));
-	myri_reset_off(mp->lregs, mp->cregs);
-	myri_reset_on(mp->cregs);
-
-	/* Turn IRQ's off. */
-	myri_disable_irq(mp->lregs, mp->cregs);
-
-	/* Reset once more. */
-	myri_reset_on(mp->cregs);
-
-	/* Get the supported DVMA burst sizes from our SBUS. */
-	mp->myri_bursts = of_getintprop_default(dp->parent,
-						"burst-sizes", 0x00);
-	if (!sbus_can_burst64())
-		mp->myri_bursts &= ~(DMA_BURST64);
-
-	DET(("MYRI bursts %02x\n", mp->myri_bursts));
-
-	/* Encode SBUS interrupt level in second control register. */
-	i = of_getintprop_default(dp, "interrupts", 0);
-	if (i == 0)
-		i = 4;
-	DET(("prom_getint(interrupts)==%d, irqlvl set to %04x\n",
-	     i, (1 << i)));
-
-	sbus_writel((1 << i), mp->cregs + MYRICTRL_IRQLVL);
-
-	mp->dev = dev;
-	dev->watchdog_timeo = 5*HZ;
-	dev->irq = op->archdata.irqs[0];
-	dev->netdev_ops = &myri_ops;
-
-	/* Register interrupt handler now. */
-	DET(("Requesting MYRIcom IRQ line.\n"));
-	if (request_irq(dev->irq, myri_interrupt,
-			IRQF_SHARED, "MyriCOM Ethernet", (void *) dev)) {
-		printk("MyriCOM: Cannot register interrupt handler.\n");
-		goto err;
-	}
-
-	dev->mtu		= MYRINET_MTU;
-	dev->header_ops		= &myri_header_ops;
-
-	dev->hard_header_len	= (ETH_HLEN + MYRI_PAD_LEN);
-
-	/* Load code onto the LANai. */
-	DET(("Loading LANAI firmware\n"));
-	if (myri_load_lanai(mp)) {
-		printk(KERN_ERR "MyriCOM: Cannot Load LANAI firmware.\n");
-		goto err_free_irq;
-	}
-
-	if (register_netdev(dev)) {
-		printk("MyriCOM: Cannot register device.\n");
-		goto err_free_irq;
-	}
-
-	dev_set_drvdata(&op->dev, mp);
-
-	num++;
-
-	printk("%s: MyriCOM MyriNET Ethernet %pM\n",
-	       dev->name, dev->dev_addr);
-
-	return 0;
-
-err_free_irq:
-	free_irq(dev->irq, dev);
-err:
-	/* This will also free the co-allocated private data*/
-	free_netdev(dev);
-	return -ENODEV;
-}
-
-static int __devexit myri_sbus_remove(struct platform_device *op)
-{
-	struct myri_eth *mp = dev_get_drvdata(&op->dev);
-	struct net_device *net_dev = mp->dev;
-
-	unregister_netdev(net_dev);
-
-	free_irq(net_dev->irq, net_dev);
-
-	if (mp->eeprom.cpuvers < CPUVERS_4_0) {
-		of_iounmap(&op->resource[0], mp->regs, mp->reg_size);
-	} else {
-		of_iounmap(&op->resource[0], mp->cregs, PAGE_SIZE);
-		of_iounmap(&op->resource[0], mp->lregs, (256 * 1024));
-		of_iounmap(&op->resource[0], mp->lanai, (512 * 1024));
-	}
-
-	free_netdev(net_dev);
-
-	dev_set_drvdata(&op->dev, NULL);
-
-	return 0;
-}
-
-static const struct of_device_id myri_sbus_match[] = {
-	{
-		.name = "MYRICOM,mlanai",
-	},
-	{
-		.name = "myri",
-	},
-	{},
-};
-
-MODULE_DEVICE_TABLE(of, myri_sbus_match);
-
-static struct platform_driver myri_sbus_driver = {
-	.driver = {
-		.name = "myri",
-		.owner = THIS_MODULE,
-		.of_match_table = myri_sbus_match,
-	},
-	.probe		= myri_sbus_probe,
-	.remove		= __devexit_p(myri_sbus_remove),
-};
-
-static int __init myri_sbus_init(void)
-{
-	return platform_driver_register(&myri_sbus_driver);
-}
-
-static void __exit myri_sbus_exit(void)
-{
-	platform_driver_unregister(&myri_sbus_driver);
-}
-
-module_init(myri_sbus_init);
-module_exit(myri_sbus_exit);
-
-MODULE_LICENSE("GPL");
-MODULE_FIRMWARE(FWNAME);
diff --git a/drivers/net/myri_sbus.h b/drivers/net/myri_sbus.h
deleted file mode 100644
index 80a2fa5..0000000
--- a/drivers/net/myri_sbus.h
+++ /dev/null
@@ -1,311 +0,0 @@
-/* myri_sbus.h: Defines for MyriCOM MyriNET SBUS card driver.
- *
- * Copyright (C) 1996 David S. Miller (davem@caip.rutgers.edu)
- */
-
-#ifndef _MYRI_SBUS_H
-#define _MYRI_SBUS_H
-
-/* LANAI Registers */
-#define LANAI_IPF0	0x00UL		/* Context zero state registers.*/
-#define LANAI_CUR0	0x04UL
-#define LANAI_PREV0	0x08UL
-#define LANAI_DATA0	0x0cUL
-#define LANAI_DPF0	0x10UL
-#define LANAI_IPF1	0x14UL		/* Context one state registers.	*/
-#define LANAI_CUR1	0x18UL
-#define LANAI_PREV1	0x1cUL
-#define LANAI_DATA1	0x20UL
-#define LANAI_DPF1	0x24UL
-#define LANAI_ISTAT	0x28UL		/* Interrupt status.		*/
-#define LANAI_EIMASK	0x2cUL		/* External IRQ mask.		*/
-#define LANAI_ITIMER	0x30UL		/* IRQ timer.			*/
-#define LANAI_RTC	0x34UL		/* Real Time Clock		*/
-#define LANAI_CSUM	0x38UL		/* Checksum.			*/
-#define LANAI_DMAXADDR	0x3cUL		/* SBUS DMA external address.	*/
-#define LANAI_DMALADDR	0x40UL		/* SBUS DMA local address.	*/
-#define LANAI_DMACTR	0x44UL		/* SBUS DMA counter.		*/
-#define LANAI_RXDMAPTR	0x48UL		/* Receive DMA pointer.		*/
-#define LANAI_RXDMALIM	0x4cUL		/* Receive DMA limit.		*/
-#define LANAI_TXDMAPTR	0x50UL		/* Transmit DMA pointer.	*/
-#define LANAI_TXDMALIM	0x54UL		/* Transmit DMA limit.		*/
-#define LANAI_TXDMALIMT	0x58UL		/* Transmit DMA limit w/tail.	*/
-	/* 0x5cUL, reserved */
-#define LANAI_RBYTE	0x60UL		/* Receive byte.		*/
-	/* 0x64-->0x6c, reserved */
-#define LANAI_RHALF	0x70UL		/* Receive half-word.		*/
-	/* 0x72UL, reserved */
-#define LANAI_RWORD	0x74UL		/* Receive word.		*/
-#define LANAI_SALIGN	0x78UL		/* Send align.			*/
-#define LANAI_SBYTE	0x7cUL		/* SingleSend send-byte.	*/
-#define LANAI_SHALF	0x80UL		/* SingleSend send-halfword.	*/
-#define LANAI_SWORD	0x84UL		/* SingleSend send-word.	*/
-#define LANAI_SSENDT	0x88UL		/* SingleSend special.		*/
-#define LANAI_DMADIR	0x8cUL		/* DMA direction.		*/
-#define LANAI_DMASTAT	0x90UL		/* DMA status.			*/
-#define LANAI_TIMEO	0x94UL		/* Timeout register.		*/
-#define LANAI_MYRINET	0x98UL		/* XXX MAGIC myricom thing	*/
-#define LANAI_HWDEBUG	0x9cUL		/* Hardware debugging reg.	*/
-#define LANAI_LEDS	0xa0UL		/* LED control.			*/
-#define LANAI_VERS	0xa4UL		/* Version register.		*/
-#define LANAI_LINKON	0xa8UL		/* Link activation reg.		*/
-	/* 0xac-->0x104, reserved */
-#define LANAI_CVAL	0x108UL		/* Clock value register.	*/
-#define LANAI_REG_SIZE	0x10cUL
-
-/* Interrupt status bits. */
-#define ISTAT_DEBUG	0x80000000
-#define ISTAT_HOST	0x40000000
-#define ISTAT_LAN7	0x00800000
-#define ISTAT_LAN6	0x00400000
-#define ISTAT_LAN5	0x00200000
-#define ISTAT_LAN4	0x00100000
-#define ISTAT_LAN3	0x00080000
-#define ISTAT_LAN2	0x00040000
-#define ISTAT_LAN1	0x00020000
-#define ISTAT_LAN0	0x00010000
-#define ISTAT_WRDY	0x00008000
-#define ISTAT_HRDY	0x00004000
-#define ISTAT_SRDY	0x00002000
-#define ISTAT_LINK	0x00001000
-#define ISTAT_FRES	0x00000800
-#define ISTAT_NRES	0x00000800
-#define ISTAT_WAKE	0x00000400
-#define ISTAT_OB2	0x00000200
-#define ISTAT_OB1	0x00000100
-#define ISTAT_TAIL	0x00000080
-#define ISTAT_WDOG	0x00000040
-#define ISTAT_TIME	0x00000020
-#define ISTAT_DMA	0x00000010
-#define ISTAT_SEND	0x00000008
-#define ISTAT_BUF	0x00000004
-#define ISTAT_RECV	0x00000002
-#define ISTAT_BRDY	0x00000001
-
-/* MYRI Registers */
-#define MYRI_RESETOFF	0x00UL
-#define MYRI_RESETON	0x04UL
-#define MYRI_IRQOFF	0x08UL
-#define MYRI_IRQON	0x0cUL
-#define MYRI_WAKEUPOFF	0x10UL
-#define MYRI_WAKEUPON	0x14UL
-#define MYRI_IRQREAD	0x18UL
-	/* 0x1c-->0x3ffc, reserved */
-#define MYRI_LOCALMEM	0x4000UL
-#define MYRI_REG_SIZE	0x25000UL
-
-/* Shared memory interrupt mask. */
-#define SHMEM_IMASK_RX		0x00000002
-#define SHMEM_IMASK_TX		0x00000001
-
-/* Just to make things readable. */
-#define KERNEL_CHANNEL		0
-
-/* The size of this must be >= 129 bytes. */
-struct myri_eeprom {
-	unsigned int		cval;
-	unsigned short		cpuvers;
-	unsigned char		id[6];
-	unsigned int		ramsz;
-	unsigned char		fvers[32];
-	unsigned char		mvers[16];
-	unsigned short		dlval;
-	unsigned short		brd_type;
-	unsigned short		bus_type;
-	unsigned short		prod_code;
-	unsigned int		serial_num;
-	unsigned short		_reserved[24];
-	unsigned int		_unused[2];
-};
-
-/* EEPROM bus types, only SBUS is valid in this driver. */
-#define BUS_TYPE_SBUS		1
-
-/* EEPROM CPU revisions. */
-#define CPUVERS_2_3		0x0203
-#define CPUVERS_3_0		0x0300
-#define CPUVERS_3_1		0x0301
-#define CPUVERS_3_2		0x0302
-#define CPUVERS_4_0		0x0400
-#define CPUVERS_4_1		0x0401
-#define CPUVERS_4_2		0x0402
-#define CPUVERS_5_0		0x0500
-
-/* MYRI Control Registers */
-#define MYRICTRL_CTRL		0x00UL
-#define MYRICTRL_IRQLVL		0x02UL
-#define MYRICTRL_REG_SIZE	0x04UL
-
-/* Global control register defines. */
-#define CONTROL_ROFF		0x8000	/* Reset OFF.		*/
-#define CONTROL_RON		0x4000	/* Reset ON.		*/
-#define CONTROL_EIRQ		0x2000	/* Enable IRQ's.	*/
-#define CONTROL_DIRQ		0x1000	/* Disable IRQ's.	*/
-#define CONTROL_WON		0x0800	/* Wake-up ON.		*/
-
-#define MYRI_SCATTER_ENTRIES	8
-#define MYRI_GATHER_ENTRIES	16
-
-struct myri_sglist {
-	u32 addr;
-	u32 len;
-};
-
-struct myri_rxd {
-	struct myri_sglist myri_scatters[MYRI_SCATTER_ENTRIES];	/* DMA scatter list.*/
-	u32 csum;	/* HW computed checksum.    */
-	u32 ctx;
-	u32 num_sg;	/* Total scatter entries.   */
-};
-
-struct myri_txd {
-	struct myri_sglist myri_gathers[MYRI_GATHER_ENTRIES]; /* DMA scatter list.  */
-	u32 num_sg;	/* Total scatter entries.   */
-	u16 addr[4];	/* XXX address              */
-	u32 chan;
-	u32 len;	/* Total length of packet.  */
-	u32 csum_off;	/* Where data to csum is.   */
-	u32 csum_field;	/* Where csum goes in pkt.  */
-};
-
-#define MYRINET_MTU        8432
-#define RX_ALLOC_SIZE      8448
-#define MYRI_PAD_LEN       2
-#define RX_COPY_THRESHOLD  256
-
-/* These numbers are cast in stone, new firmware is needed if
- * you want to change them.
- */
-#define TX_RING_MAXSIZE    16
-#define RX_RING_MAXSIZE    16
-
-#define TX_RING_SIZE       16
-#define RX_RING_SIZE       16
-
-/* GRRR... */
-static __inline__ int NEXT_RX(int num)
-{
-	/* XXX >=??? */
-	if(++num > RX_RING_SIZE)
-		num = 0;
-	return num;
-}
-
-static __inline__ int PREV_RX(int num)
-{
-	if(--num < 0)
-		num = RX_RING_SIZE;
-	return num;
-}
-
-#define NEXT_TX(num)	(((num) + 1) & (TX_RING_SIZE - 1))
-#define PREV_TX(num)	(((num) - 1) & (TX_RING_SIZE - 1))
-
-#define TX_BUFFS_AVAIL(head, tail)		\
-	((head) <= (tail) ?			\
-	 (head) + (TX_RING_SIZE - 1) - (tail) :	\
-	 (head) - (tail) - 1)
-
-struct sendq {
-	u32	tail;
-	u32	head;
-	u32	hdebug;
-	u32	mdebug;
-	struct myri_txd	myri_txd[TX_RING_MAXSIZE];
-};
-
-struct recvq {
-	u32	head;
-	u32	tail;
-	u32	hdebug;
-	u32	mdebug;
-	struct myri_rxd	myri_rxd[RX_RING_MAXSIZE + 1];
-};
-
-#define MYRI_MLIST_SIZE 8
-
-struct mclist {
-	u32 maxlen;
-	u32 len;
-	u32 cache;
-	struct pair {
-		u8 addr[8];
-		u32 val;
-	} mc_pairs[MYRI_MLIST_SIZE];
-	u8 bcast_addr[8];
-};
-
-struct myri_channel {
-	u32		state;		/* State of the channel.	*/
-	u32		busy;		/* Channel is busy.		*/
-	struct sendq	sendq;		/* Device tx queue.		*/
-	struct recvq	recvq;		/* Device rx queue.		*/
-	struct recvq	recvqa;		/* Device rx queue acked.	*/
-	u32		rbytes;		/* Receive bytes.		*/
-	u32		sbytes;		/* Send bytes.			*/
-	u32		rmsgs;		/* Receive messages.		*/
-	u32		smsgs;		/* Send messages.		*/
-	struct mclist	mclist;		/* Device multicast list.	*/
-};
-
-/* Values for per-channel state. */
-#define STATE_WFH	0		/* Waiting for HOST.		*/
-#define STATE_WFN	1		/* Waiting for NET.		*/
-#define STATE_READY	2		/* Ready.			*/
-
-struct myri_shmem {
-	u8	addr[8];		/* Board's address.		*/
-	u32	nchan;			/* Number of channels.		*/
-	u32	burst;			/* SBUS dma burst enable.	*/
-	u32	shakedown;		/* DarkkkkStarrr Crashesss...	*/
-	u32	send;			/* Send wanted.			*/
-	u32	imask;			/* Interrupt enable mask.	*/
-	u32	mlevel;			/* Map level.			*/
-	u32	debug[4];		/* Misc. debug areas.		*/
-	struct myri_channel channel;	/* Only one channel on a host.	*/
-};
-
-struct myri_eth {
-	/* These are frequently accessed, keep together
-	 * to obtain good cache hit rates.
-	 */
-	spinlock_t			irq_lock;
-	struct myri_shmem __iomem	*shmem;		/* Shared data structures.    */
-	void __iomem			*cregs;		/* Control register space.    */
-	struct recvq __iomem		*rqack;		/* Where we ack rx's.         */
-	struct recvq __iomem		*rq;		/* Where we put buffers.      */
-	struct sendq __iomem		*sq;		/* Where we stuff tx's.       */
-	struct net_device		*dev;		/* Linux/NET dev struct.      */
-	int				tx_old;		/* To speed up tx cleaning.   */
-	void __iomem			*lregs;		/* Quick ptr to LANAI regs.   */
-	struct sk_buff	       *rx_skbs[RX_RING_SIZE+1];/* RX skb's                   */
-	struct sk_buff	       *tx_skbs[TX_RING_SIZE];  /* TX skb's                   */
-
-	/* These are less frequently accessed. */
-	void __iomem			*regs;          /* MyriCOM register space.    */
-	void __iomem			*lanai;		/* View 2 of register space.  */
-	unsigned int			myri_bursts;	/* SBUS bursts.               */
-	struct myri_eeprom		eeprom;		/* Local copy of EEPROM.      */
-	unsigned int			reg_size;	/* Size of register space.    */
-	unsigned int			shmem_base;	/* Offset to shared ram.      */
-	struct platform_device		*myri_op;	/* Our OF device struct.    */
-};
-
-/* We use this to acquire receive skb's that we can DMA directly into. */
-#define ALIGNED_RX_SKB_ADDR(addr) \
-        ((((unsigned long)(addr) + (64 - 1)) & ~(64 - 1)) - (unsigned long)(addr))
-static inline struct sk_buff *myri_alloc_skb(unsigned int length, gfp_t gfp_flags)
-{
-	struct sk_buff *skb;
-
-	skb = alloc_skb(length + 64, gfp_flags);
-	if(skb) {
-		int offset = ALIGNED_RX_SKB_ADDR(skb->data);
-
-		if(offset)
-			skb_reserve(skb, offset);
-	}
-	return skb;
-}
-
-#endif /* !(_MYRI_SBUS_H) */
-- 
1.7.5.4


^ permalink raw reply related

* Re: [RESENT PATCH] net: tuntap: Fix tun_net_fix_features()
From: Michał Mirosław @ 2011-06-20 19:44 UTC (permalink / raw)
  To: Ben Hutchings; +Cc: netdev, Herbert Xu, Michael S. Tsirkin, Shan Wei
In-Reply-To: <1308597906.2701.148.camel@bwh-desktop>

On Mon, Jun 20, 2011 at 08:25:06PM +0100, Ben Hutchings wrote:
> On Mon, 2011-06-20 at 21:14 +0200, Michał Mirosław wrote:
> > tun->set_features are meant to limit not force the features.
> >
> > Signed-off-by: Michał Mirosław <mirq-linux@rere.qmqm.pl>
> > Acked-by: Michael S. Tsirkin <mst@redhat.com>
> > 
> > ---
> >  drivers/net/tun.c |    2 +-
> >  1 files changed, 1 insertions(+), 1 deletions(-)
> > 
> > diff --git a/drivers/net/tun.c b/drivers/net/tun.c
> > index 4dab85e..56981c2 100644
> > --- a/drivers/net/tun.c
> > +++ b/drivers/net/tun.c
> > @@ -458,7 +458,7 @@ static u32 tun_net_fix_features(struct net_device *dev, u32 features)
> >  {
> >  	struct tun_struct *tun = netdev_priv(dev);
> >  
> > -	return (features & tun->set_features) | (features & ~TUN_USER_FEATURES);
> > +	return features & (tun->set_features | ~TUN_USER_FEATURES);
> 
> (A & B) | (A & C) <=> A & (B | C)
> 
> This is a cosmetic change, not a fix.  Maybe you think it is clearer but
> then you should say that in the commit message.

Hmm. Noise through my braincells, I suppose. Let's just drop this patch.

Best Regards,
Michał Mirosław

^ permalink raw reply

* Re: [RFT PATCH 0/9] Cleanup and extension of netdev features
From: Michał Mirosław @ 2011-06-20 19:47 UTC (permalink / raw)
  To: David Miller; +Cc: netdev, bhutchings
In-Reply-To: <20110620.123538.1237637857260925516.davem@davemloft.net>

On Mon, Jun 20, 2011 at 12:35:38PM -0700, David Miller wrote:
> Patch #1 was not sent out.

Yes, that's on purpose: it's outdated and is just for making intel
drivers compile. I'll append it so you have a clear view for the rest
of the series.

Best Regards,
Michał Mirosław

^ permalink raw reply

* Re: [PATCH 2/2] proc: Usable inode numbers for the namespace file descriptors.
From: Eric W. Biederman @ 2011-06-20 19:50 UTC (permalink / raw)
  To: Serge E. Hallyn
  Cc: Linux Containers, Alexey Dobriyan, netdev, David Lamparter,
	linux-kernel
In-Reply-To: <20110620160656.GB16444@mail.hallyn.com>

"Serge E. Hallyn" <serge@hallyn.com> writes:

> Quoting Eric W. Biederman (ebiederm@xmission.com):
>> 
>> Assign a unique proc inode to each namespace, yielding an
>> identifier that userspace can use for identifying a namespace.
>> 
>> This has been a long requested feature and only blocked because
>> a naive implementation would put the id in a global space and
>> would ultimately require having a namespace for the names of
>> namespaces, making migration and certain virtualization tricks
>> impossible.
>> 
>> We still don't have per superblock inode numbers for proc, which
>> appears necessary for application unaware checkpoint/restart and
>> migrations (if the application is using namespace filedescriptors)
>> but that is now allowd by the design if it becomes important.
>> 
>> I have preallocated the ipc and uts initial proc inode numbers so
>> their structures can be statically initialized.
>> 
>> Signed-off-by: Eric W. Biederman <ebiederm@xmission.com>
>
> I've not looked at the setns patches enough, but from what I can see
> here it looks good.
>
> Acked-by: Serge Hallyn <serge@hallyn.com>

Thanks.

There are bugs in my existing proc bits that I am working on fixing so
this second patch will have a small update, before it gets merged.

But posting the patches I was looking for a little review and I was
announcing I had solved the technical problem of how we talk about
namespaces, without needing to introduce another namespace for
namespaces.

Eric

^ permalink raw reply

* Re: [PATCH] myri_sbus: remove driver
From: David Miller @ 2011-06-20 19:51 UTC (permalink / raw)
  To: jon.mason; +Cc: netdev, jeffrey.t.kirsher, gallatin
In-Reply-To: <20110620193859.GA19114@myri.com>

From: Jon Mason <jon.mason@myri.com>
Date: Mon, 20 Jun 2011 14:39:00 -0500

> Remove the myri_sbus driver. Why?
> * There is no possibility of ethernet mode on this adapter, so it's
>   Myrinet only.
> * It won't inter-op with modern versions of Myrinet, and thus can only
>   work with legacy adapters.
> * There are no in-kernel Linux drivers for the PCI version of this
>   adapter, so it only can work on ~15 year old Sun hardware.
> 
> It's long in the tooth, let's take it to the knackers.
> 
> Signed-off-by: Jon Mason <mason@myri.com>

Sniff sniff... applied.

^ permalink raw reply

* [IGNORE PATCH 1/9] Intel net drivers: convert to ndo_fix_features
From: Michał Mirosław @ 2011-06-20 19:55 UTC (permalink / raw)
  To: netdev; +Cc: David S. Miller, Ben Hutchings
In-Reply-To: <20110620194756.GB3231@rere.qmqm.pl>

[This is an outdated patch just for making the rest of the series compile.]

Private rx_csum flags are now duplicate of netdev->features & NETIF_F_RXCSUM.
Removing this needs deeper surgery.

Since ixgbevf doesn't change hardware state on RX csum enable/disable
its reset is avoided.

Things noticed:
 - e1000, e1000e and ixgb have RX csum disabled by default
 - HW VLAN acceleration probably can be toggled, but it's left as is
 - the resets on RX csum offload change can probably be avoided
 - there is A LOT of copy-and-pasted code here

Signed-off-by: Michał Mirosław <mirq-linux@rere.qmqm.pl>
---
 drivers/net/e1000/e1000_ethtool.c  |   69 --------------
 drivers/net/e1000/e1000_main.c     |   30 +++++-
 drivers/net/e1000e/ethtool.c       |   88 -----------------
 drivers/net/e1000e/netdev.c        |   35 ++++++--
 drivers/net/igb/igb_ethtool.c      |   67 -------------
 drivers/net/igb/igb_main.c         |   33 +++++--
 drivers/net/igbvf/ethtool.c        |   57 -----------
 drivers/net/igbvf/netdev.c         |   25 ++++-
 drivers/net/ixgb/ixgb.h            |    2 +
 drivers/net/ixgb/ixgb_ethtool.c    |   98 +-------------------
 drivers/net/ixgb/ixgb_main.c       |   44 ++++++++-
 drivers/net/ixgbe/ixgbe_ethtool.c  |  182 +++++++++++-------------------------
 drivers/net/ixgbe/ixgbe_main.c     |   41 +++++---
 drivers/net/ixgbevf/ethtool.c      |   46 ---------
 drivers/net/ixgbevf/ixgbevf_main.c |   26 ++++-
 15 files changed, 244 insertions(+), 599 deletions(-)

diff --git a/drivers/net/e1000/e1000_ethtool.c b/drivers/net/e1000/e1000_ethtool.c
index ec0fa42..c5f0f04 100644
--- a/drivers/net/e1000/e1000_ethtool.c
+++ b/drivers/net/e1000/e1000_ethtool.c
@@ -290,69 +290,6 @@ static int e1000_set_pauseparam(struct net_device *netdev,
 	return retval;
 }
 
-static u32 e1000_get_rx_csum(struct net_device *netdev)
-{
-	struct e1000_adapter *adapter = netdev_priv(netdev);
-	return adapter->rx_csum;
-}
-
-static int e1000_set_rx_csum(struct net_device *netdev, u32 data)
-{
-	struct e1000_adapter *adapter = netdev_priv(netdev);
-	adapter->rx_csum = data;
-
-	if (netif_running(netdev))
-		e1000_reinit_locked(adapter);
-	else
-		e1000_reset(adapter);
-	return 0;
-}
-
-static u32 e1000_get_tx_csum(struct net_device *netdev)
-{
-	return (netdev->features & NETIF_F_HW_CSUM) != 0;
-}
-
-static int e1000_set_tx_csum(struct net_device *netdev, u32 data)
-{
-	struct e1000_adapter *adapter = netdev_priv(netdev);
-	struct e1000_hw *hw = &adapter->hw;
-
-	if (hw->mac_type < e1000_82543) {
-		if (!data)
-			return -EINVAL;
-		return 0;
-	}
-
-	if (data)
-		netdev->features |= NETIF_F_HW_CSUM;
-	else
-		netdev->features &= ~NETIF_F_HW_CSUM;
-
-	return 0;
-}
-
-static int e1000_set_tso(struct net_device *netdev, u32 data)
-{
-	struct e1000_adapter *adapter = netdev_priv(netdev);
-	struct e1000_hw *hw = &adapter->hw;
-
-	if ((hw->mac_type < e1000_82544) ||
-	    (hw->mac_type == e1000_82547))
-		return data ? -EINVAL : 0;
-
-	if (data)
-		netdev->features |= NETIF_F_TSO;
-	else
-		netdev->features &= ~NETIF_F_TSO;
-
-	netdev->features &= ~NETIF_F_TSO6;
-
-	e_info(probe, "TSO is %s\n", data ? "Enabled" : "Disabled");
-	adapter->tso_force = true;
-	return 0;
-}
-
 static u32 e1000_get_msglevel(struct net_device *netdev)
 {
 	struct e1000_adapter *adapter = netdev_priv(netdev);
@@ -1905,12 +1842,6 @@ static const struct ethtool_ops e1000_ethtool_ops = {
 	.set_ringparam          = e1000_set_ringparam,
 	.get_pauseparam         = e1000_get_pauseparam,
 	.set_pauseparam         = e1000_set_pauseparam,
-	.get_rx_csum            = e1000_get_rx_csum,
-	.set_rx_csum            = e1000_set_rx_csum,
-	.get_tx_csum            = e1000_get_tx_csum,
-	.set_tx_csum            = e1000_set_tx_csum,
-	.set_sg                 = ethtool_op_set_sg,
-	.set_tso                = e1000_set_tso,
 	.self_test              = e1000_diag_test,
 	.get_strings            = e1000_get_strings,
 	.set_phys_id            = e1000_set_phys_id,
diff --git a/drivers/net/e1000/e1000_main.c b/drivers/net/e1000/e1000_main.c
index 76e8af0..188d99a 100644
--- a/drivers/net/e1000/e1000_main.c
+++ b/drivers/net/e1000/e1000_main.c
@@ -797,6 +797,24 @@ static int e1000_is_need_ioport(struct pci_dev *pdev)
 	}
 }
 
+static int e1000_set_features(struct net_device *netdev, u32 features)
+{
+	struct e1000_adapter *adapter = netdev_priv(netdev);
+	u32 changed = features ^ netdev->features;
+
+	if (!(changed & NETIF_F_RXCSUM))
+		return 0;
+
+	adapter->rx_csum = !!(features & NETIF_F_RXCSUM);
+
+	if (netif_running(netdev))
+		e1000_reinit_locked(adapter);
+	else
+		e1000_reset(adapter);
+
+	return 0;
+}
+
 static const struct net_device_ops e1000_netdev_ops = {
 	.ndo_open		= e1000_open,
 	.ndo_stop		= e1000_close,
@@ -815,6 +833,7 @@ static const struct net_device_ops e1000_netdev_ops = {
 #ifdef CONFIG_NET_POLL_CONTROLLER
 	.ndo_poll_controller	= e1000_netpoll,
 #endif
+	.ndo_set_features       = e1000_set_features,
 };
 
 /**
@@ -1016,16 +1035,19 @@ static int __devinit e1000_probe(struct pci_dev *pdev,
 	}
 
 	if (hw->mac_type >= e1000_82543) {
-		netdev->features = NETIF_F_SG |
-				   NETIF_F_HW_CSUM |
-				   NETIF_F_HW_VLAN_TX |
+		netdev->hw_features = NETIF_F_SG |
+				   NETIF_F_HW_CSUM;
+		netdev->features = NETIF_F_HW_VLAN_TX |
 				   NETIF_F_HW_VLAN_RX |
 				   NETIF_F_HW_VLAN_FILTER;
 	}
 
 	if ((hw->mac_type >= e1000_82544) &&
 	   (hw->mac_type != e1000_82547))
-		netdev->features |= NETIF_F_TSO;
+		netdev->hw_features |= NETIF_F_TSO;
+
+	netdev->features |= netdev->hw_features;
+	netdev->hw_features |= NETIF_F_RXCSUM;
 
 	if (pci_using_dac) {
 		netdev->features |= NETIF_F_HIGHDMA;
diff --git a/drivers/net/e1000e/ethtool.c b/drivers/net/e1000e/ethtool.c
index cb1a362..25b5431 100644
--- a/drivers/net/e1000e/ethtool.c
+++ b/drivers/net/e1000e/ethtool.c
@@ -367,59 +367,6 @@ out:
 	return retval;
 }
 
-static u32 e1000_get_rx_csum(struct net_device *netdev)
-{
-	struct e1000_adapter *adapter = netdev_priv(netdev);
-	return adapter->flags & FLAG_RX_CSUM_ENABLED;
-}
-
-static int e1000_set_rx_csum(struct net_device *netdev, u32 data)
-{
-	struct e1000_adapter *adapter = netdev_priv(netdev);
-
-	if (data)
-		adapter->flags |= FLAG_RX_CSUM_ENABLED;
-	else
-		adapter->flags &= ~FLAG_RX_CSUM_ENABLED;
-
-	if (netif_running(netdev))
-		e1000e_reinit_locked(adapter);
-	else
-		e1000e_reset(adapter);
-	return 0;
-}
-
-static u32 e1000_get_tx_csum(struct net_device *netdev)
-{
-	return (netdev->features & NETIF_F_HW_CSUM) != 0;
-}
-
-static int e1000_set_tx_csum(struct net_device *netdev, u32 data)
-{
-	if (data)
-		netdev->features |= NETIF_F_HW_CSUM;
-	else
-		netdev->features &= ~NETIF_F_HW_CSUM;
-
-	return 0;
-}
-
-static int e1000_set_tso(struct net_device *netdev, u32 data)
-{
-	struct e1000_adapter *adapter = netdev_priv(netdev);
-
-	if (data) {
-		netdev->features |= NETIF_F_TSO;
-		netdev->features |= NETIF_F_TSO6;
-	} else {
-		netdev->features &= ~NETIF_F_TSO;
-		netdev->features &= ~NETIF_F_TSO6;
-	}
-
-	adapter->flags |= FLAG_TSO_FORCE;
-	return 0;
-}
-
 static u32 e1000_get_msglevel(struct net_device *netdev)
 {
 	struct e1000_adapter *adapter = netdev_priv(netdev);
@@ -2003,31 +1950,6 @@ static void e1000_get_strings(struct net_device *netdev, u32 stringset,
 	}
 }
 
-static int e1000e_set_flags(struct net_device *netdev, u32 data)
-{
-	struct e1000_adapter *adapter = netdev_priv(netdev);
-	bool need_reset = false;
-	int rc;
-
-	need_reset = (data & ETH_FLAG_RXVLAN) !=
-		     (netdev->features & NETIF_F_HW_VLAN_RX);
-
-	rc = ethtool_op_set_flags(netdev, data, ETH_FLAG_RXVLAN |
-				  ETH_FLAG_TXVLAN);
-
-	if (rc)
-		return rc;
-
-	if (need_reset) {
-		if (netif_running(netdev))
-			e1000e_reinit_locked(adapter);
-		else
-			e1000e_reset(adapter);
-	}
-
-	return 0;
-}
-
 static const struct ethtool_ops e1000_ethtool_ops = {
 	.get_settings		= e1000_get_settings,
 	.set_settings		= e1000_set_settings,
@@ -2047,14 +1969,6 @@ static const struct ethtool_ops e1000_ethtool_ops = {
 	.set_ringparam		= e1000_set_ringparam,
 	.get_pauseparam		= e1000_get_pauseparam,
 	.set_pauseparam		= e1000_set_pauseparam,
-	.get_rx_csum		= e1000_get_rx_csum,
-	.set_rx_csum		= e1000_set_rx_csum,
-	.get_tx_csum		= e1000_get_tx_csum,
-	.set_tx_csum		= e1000_set_tx_csum,
-	.get_sg			= ethtool_op_get_sg,
-	.set_sg			= ethtool_op_set_sg,
-	.get_tso		= ethtool_op_get_tso,
-	.set_tso		= e1000_set_tso,
 	.self_test		= e1000_diag_test,
 	.get_strings		= e1000_get_strings,
 	.set_phys_id		= e1000_set_phys_id,
@@ -2062,8 +1976,6 @@ static const struct ethtool_ops e1000_ethtool_ops = {
 	.get_sset_count		= e1000e_get_sset_count,
 	.get_coalesce		= e1000_get_coalesce,
 	.set_coalesce		= e1000_set_coalesce,
-	.get_flags		= ethtool_op_get_flags,
-	.set_flags		= e1000e_set_flags,
 };
 
 void e1000e_set_ethtool_ops(struct net_device *netdev)
diff --git a/drivers/net/e1000e/netdev.c b/drivers/net/e1000e/netdev.c
index 3bf5249..45c9d06 100644
--- a/drivers/net/e1000e/netdev.c
+++ b/drivers/net/e1000e/netdev.c
@@ -5751,6 +5751,28 @@ static void e1000_eeprom_checks(struct e1000_adapter *adapter)
 	}
 }
 
+static int e1000_set_features(struct net_device *netdev, u32 features)
+{
+	struct e1000_adapter *adapter = netdev_priv(netdev);
+	u32 changed = features ^ netdev->features;
+
+	if (features & NETIF_F_RXCSUM)
+		adapter->flags |= FLAG_RX_CSUM_ENABLED;
+	else
+		adapter->flags &= ~FLAG_RX_CSUM_ENABLED;
+
+	if (changed & NETIF_F_HW_VLAN_RX) {
+		netdev->features = features;
+		if (netif_running(netdev))
+			e1000e_reinit_locked(adapter);
+		else
+			e1000e_reset(adapter);
+		return 1;
+	}
+
+	return 0;
+}
+
 static const struct net_device_ops e1000e_netdev_ops = {
 	.ndo_open		= e1000_open,
 	.ndo_stop		= e1000_close,
@@ -5768,6 +5790,7 @@ static const struct net_device_ops e1000e_netdev_ops = {
 #ifdef CONFIG_NET_POLL_CONTROLLER
 	.ndo_poll_controller	= e1000_netpoll,
 #endif
+	.ndo_set_features	= e1000_set_features,
 };
 
 /**
@@ -5927,17 +5950,15 @@ static int __devinit e1000_probe(struct pci_dev *pdev,
 	if (e1000_check_reset_block(&adapter->hw))
 		e_info("PHY reset is blocked due to SOL/IDER session.\n");
 
-	netdev->features = NETIF_F_SG |
-			   NETIF_F_HW_CSUM |
-			   NETIF_F_HW_VLAN_TX |
-			   NETIF_F_HW_VLAN_RX;
+	netdev->hw_features = NETIF_F_SG | NETIF_F_HW_CSUM |
+			      NETIF_F_TSO | NETIF_F_TSO6 |
+			      NETIF_F_HW_VLAN_TX | NETIF_F_HW_VLAN_RX;
+	netdev->features = netdev->hw_features;
+	netdev->hw_features |= NETIF_F_RXCSUM;
 
 	if (adapter->flags & FLAG_HAS_HW_VLAN_FILTER)
 		netdev->features |= NETIF_F_HW_VLAN_FILTER;
 
-	netdev->features |= NETIF_F_TSO;
-	netdev->features |= NETIF_F_TSO6;
-
 	netdev->vlan_features |= NETIF_F_TSO;
 	netdev->vlan_features |= NETIF_F_TSO6;
 	netdev->vlan_features |= NETIF_F_HW_CSUM;
diff --git a/drivers/net/igb/igb_ethtool.c b/drivers/net/igb/igb_ethtool.c
index fdc895e..1862c97 100644
--- a/drivers/net/igb/igb_ethtool.c
+++ b/drivers/net/igb/igb_ethtool.c
@@ -318,65 +318,6 @@ static int igb_set_pauseparam(struct net_device *netdev,
 	return retval;
 }
 
-static u32 igb_get_rx_csum(struct net_device *netdev)
-{
-	struct igb_adapter *adapter = netdev_priv(netdev);
-	return !!(adapter->rx_ring[0]->flags & IGB_RING_FLAG_RX_CSUM);
-}
-
-static int igb_set_rx_csum(struct net_device *netdev, u32 data)
-{
-	struct igb_adapter *adapter = netdev_priv(netdev);
-	int i;
-
-	for (i = 0; i < adapter->num_rx_queues; i++) {
-		if (data)
-			adapter->rx_ring[i]->flags |= IGB_RING_FLAG_RX_CSUM;
-		else
-			adapter->rx_ring[i]->flags &= ~IGB_RING_FLAG_RX_CSUM;
-	}
-
-	return 0;
-}
-
-static u32 igb_get_tx_csum(struct net_device *netdev)
-{
-	return (netdev->features & NETIF_F_IP_CSUM) != 0;
-}
-
-static int igb_set_tx_csum(struct net_device *netdev, u32 data)
-{
-	struct igb_adapter *adapter = netdev_priv(netdev);
-
-	if (data) {
-		netdev->features |= (NETIF_F_IP_CSUM | NETIF_F_IPV6_CSUM);
-		if (adapter->hw.mac.type >= e1000_82576)
-			netdev->features |= NETIF_F_SCTP_CSUM;
-	} else {
-		netdev->features &= ~(NETIF_F_IP_CSUM | NETIF_F_IPV6_CSUM |
-		                      NETIF_F_SCTP_CSUM);
-	}
-
-	return 0;
-}
-
-static int igb_set_tso(struct net_device *netdev, u32 data)
-{
-	struct igb_adapter *adapter = netdev_priv(netdev);
-
-	if (data) {
-		netdev->features |= NETIF_F_TSO;
-		netdev->features |= NETIF_F_TSO6;
-	} else {
-		netdev->features &= ~NETIF_F_TSO;
-		netdev->features &= ~NETIF_F_TSO6;
-	}
-
-	dev_info(&adapter->pdev->dev, "TSO is %s\n",
-		 data ? "Enabled" : "Disabled");
-	return 0;
-}
-
 static u32 igb_get_msglevel(struct net_device *netdev)
 {
 	struct igb_adapter *adapter = netdev_priv(netdev);
@@ -2207,14 +2148,6 @@ static const struct ethtool_ops igb_ethtool_ops = {
 	.set_ringparam          = igb_set_ringparam,
 	.get_pauseparam         = igb_get_pauseparam,
 	.set_pauseparam         = igb_set_pauseparam,
-	.get_rx_csum            = igb_get_rx_csum,
-	.set_rx_csum            = igb_set_rx_csum,
-	.get_tx_csum            = igb_get_tx_csum,
-	.set_tx_csum            = igb_set_tx_csum,
-	.get_sg                 = ethtool_op_get_sg,
-	.set_sg                 = ethtool_op_set_sg,
-	.get_tso                = ethtool_op_get_tso,
-	.set_tso                = igb_set_tso,
 	.self_test              = igb_diag_test,
 	.get_strings            = igb_get_strings,
 	.set_phys_id            = igb_set_phys_id,
diff --git a/drivers/net/igb/igb_main.c b/drivers/net/igb/igb_main.c
index c2e9670..2841f14 100644
--- a/drivers/net/igb/igb_main.c
+++ b/drivers/net/igb/igb_main.c
@@ -1748,6 +1748,21 @@ void igb_reset(struct igb_adapter *adapter)
 	igb_get_phy_info(hw);
 }
 
+static int igb_set_features(struct net_device *netdev, u32 features)
+{
+	struct igb_adapter *adapter = netdev_priv(netdev);
+	int i;
+
+	for (i = 0; i < adapter->num_rx_queues; i++) {
+		if (features & NETIF_F_RXCSUM)
+			adapter->rx_ring[i]->flags |= IGB_RING_FLAG_RX_CSUM;
+		else
+			adapter->rx_ring[i]->flags &= ~IGB_RING_FLAG_RX_CSUM;
+	}
+
+	return 0;
+}
+
 static const struct net_device_ops igb_netdev_ops = {
 	.ndo_open		= igb_open,
 	.ndo_stop		= igb_close,
@@ -1770,6 +1785,7 @@ static const struct net_device_ops igb_netdev_ops = {
 #ifdef CONFIG_NET_POLL_CONTROLLER
 	.ndo_poll_controller	= igb_netpoll,
 #endif
+	.ndo_set_features       = igb_set_features,
 };
 
 /**
@@ -1909,17 +1925,18 @@ static int __devinit igb_probe(struct pci_dev *pdev,
 		dev_info(&pdev->dev,
 			"PHY reset is blocked due to SOL/IDER session.\n");
 
-	netdev->features = NETIF_F_SG |
+	netdev->hw_features = NETIF_F_SG |
 			   NETIF_F_IP_CSUM |
+			   NETIF_F_IPV6_CSUM |
+			   NETIF_F_TSO |
+			   NETIF_F_TSO6 |
+			   NETIF_F_RXCSUM;
+
+	netdev->features = netdev->hw_features |
 			   NETIF_F_HW_VLAN_TX |
 			   NETIF_F_HW_VLAN_RX |
 			   NETIF_F_HW_VLAN_FILTER;
 
-	netdev->features |= NETIF_F_IPV6_CSUM;
-	netdev->features |= NETIF_F_TSO;
-	netdev->features |= NETIF_F_TSO6;
-	netdev->features |= NETIF_F_GRO;
-
 	netdev->vlan_features |= NETIF_F_TSO;
 	netdev->vlan_features |= NETIF_F_TSO6;
 	netdev->vlan_features |= NETIF_F_IP_CSUM;
@@ -1931,8 +1948,10 @@ static int __devinit igb_probe(struct pci_dev *pdev,
 		netdev->vlan_features |= NETIF_F_HIGHDMA;
 	}
 
-	if (hw->mac.type >= e1000_82576)
+	if (hw->mac.type >= e1000_82576) {
+		netdev->hw_features |= NETIF_F_SCTP_CSUM;
 		netdev->features |= NETIF_F_SCTP_CSUM;
+	}
 
 	adapter->en_mng_pt = igb_enable_mng_pass_thru(hw);
 
diff --git a/drivers/net/igbvf/ethtool.c b/drivers/net/igbvf/ethtool.c
index b0b14d6..fd36366 100644
--- a/drivers/net/igbvf/ethtool.c
+++ b/drivers/net/igbvf/ethtool.c
@@ -128,55 +128,6 @@ static int igbvf_set_pauseparam(struct net_device *netdev,
 	return -EOPNOTSUPP;
 }
 
-static u32 igbvf_get_rx_csum(struct net_device *netdev)
-{
-	struct igbvf_adapter *adapter = netdev_priv(netdev);
-	return !(adapter->flags & IGBVF_FLAG_RX_CSUM_DISABLED);
-}
-
-static int igbvf_set_rx_csum(struct net_device *netdev, u32 data)
-{
-	struct igbvf_adapter *adapter = netdev_priv(netdev);
-
-	if (data)
-		adapter->flags &= ~IGBVF_FLAG_RX_CSUM_DISABLED;
-	else
-		adapter->flags |= IGBVF_FLAG_RX_CSUM_DISABLED;
-
-	return 0;
-}
-
-static u32 igbvf_get_tx_csum(struct net_device *netdev)
-{
-	return (netdev->features & NETIF_F_IP_CSUM) != 0;
-}
-
-static int igbvf_set_tx_csum(struct net_device *netdev, u32 data)
-{
-	if (data)
-		netdev->features |= (NETIF_F_IP_CSUM | NETIF_F_IPV6_CSUM);
-	else
-		netdev->features &= ~(NETIF_F_IP_CSUM | NETIF_F_IPV6_CSUM);
-	return 0;
-}
-
-static int igbvf_set_tso(struct net_device *netdev, u32 data)
-{
-	struct igbvf_adapter *adapter = netdev_priv(netdev);
-
-	if (data) {
-		netdev->features |= NETIF_F_TSO;
-		netdev->features |= NETIF_F_TSO6;
-	} else {
-		netdev->features &= ~NETIF_F_TSO;
-		netdev->features &= ~NETIF_F_TSO6;
-	}
-
-	dev_info(&adapter->pdev->dev, "TSO is %s\n",
-	         data ? "Enabled" : "Disabled");
-	return 0;
-}
-
 static u32 igbvf_get_msglevel(struct net_device *netdev)
 {
 	struct igbvf_adapter *adapter = netdev_priv(netdev);
@@ -511,14 +462,6 @@ static const struct ethtool_ops igbvf_ethtool_ops = {
 	.set_ringparam		= igbvf_set_ringparam,
 	.get_pauseparam		= igbvf_get_pauseparam,
 	.set_pauseparam		= igbvf_set_pauseparam,
-	.get_rx_csum            = igbvf_get_rx_csum,
-	.set_rx_csum            = igbvf_set_rx_csum,
-	.get_tx_csum		= igbvf_get_tx_csum,
-	.set_tx_csum		= igbvf_set_tx_csum,
-	.get_sg			= ethtool_op_get_sg,
-	.set_sg			= ethtool_op_set_sg,
-	.get_tso		= ethtool_op_get_tso,
-	.set_tso		= igbvf_set_tso,
 	.self_test		= igbvf_diag_test,
 	.get_sset_count		= igbvf_get_sset_count,
 	.get_strings		= igbvf_get_strings,
diff --git a/drivers/net/igbvf/netdev.c b/drivers/net/igbvf/netdev.c
index 64b47bf..bb2a596 100644
--- a/drivers/net/igbvf/netdev.c
+++ b/drivers/net/igbvf/netdev.c
@@ -2546,6 +2546,18 @@ static void igbvf_print_device_info(struct igbvf_adapter *adapter)
 	dev_info(&pdev->dev, "MAC: %d\n", hw->mac.type);
 }
 
+static int igbvf_set_features(struct net_device *netdev, u32 features)
+{
+	struct igbvf_adapter *adapter = netdev_priv(netdev);
+
+	if (features & NETIF_F_RXCSUM)
+		adapter->flags &= ~IGBVF_FLAG_RX_CSUM_DISABLED;
+	else
+		adapter->flags |= IGBVF_FLAG_RX_CSUM_DISABLED;
+
+	return 0;
+}
+
 static const struct net_device_ops igbvf_netdev_ops = {
 	.ndo_open                       = igbvf_open,
 	.ndo_stop                       = igbvf_close,
@@ -2562,6 +2574,7 @@ static const struct net_device_ops igbvf_netdev_ops = {
 #ifdef CONFIG_NET_POLL_CONTROLLER
 	.ndo_poll_controller            = igbvf_netpoll,
 #endif
+	.ndo_set_features               = igbvf_set_features,
 };
 
 /**
@@ -2669,16 +2682,18 @@ static int __devinit igbvf_probe(struct pci_dev *pdev,
 
 	adapter->bd_number = cards_found++;
 
-	netdev->features = NETIF_F_SG |
+	netdev->hw_features = NETIF_F_SG |
 	                   NETIF_F_IP_CSUM |
+	                   NETIF_F_IPV6_CSUM |
+			   NETIF_F_TSO |
+			   NETIF_F_TSO6 |
+			   NETIF_F_RXCSUM;
+
+	netdev->features = netdev->hw_features |
 	                   NETIF_F_HW_VLAN_TX |
 	                   NETIF_F_HW_VLAN_RX |
 	                   NETIF_F_HW_VLAN_FILTER;
 
-	netdev->features |= NETIF_F_IPV6_CSUM;
-	netdev->features |= NETIF_F_TSO;
-	netdev->features |= NETIF_F_TSO6;
-
 	if (pci_using_dac)
 		netdev->features |= NETIF_F_HIGHDMA;
 
diff --git a/drivers/net/ixgb/ixgb.h b/drivers/net/ixgb/ixgb.h
index 49e8408..cb23448 100644
--- a/drivers/net/ixgb/ixgb.h
+++ b/drivers/net/ixgb/ixgb.h
@@ -204,6 +204,8 @@ extern void ixgb_set_ethtool_ops(struct net_device *netdev);
 extern char ixgb_driver_name[];
 extern const char ixgb_driver_version[];
 
+extern void ixgb_set_speed_duplex(struct net_device *netdev);
+
 extern int ixgb_up(struct ixgb_adapter *adapter);
 extern void ixgb_down(struct ixgb_adapter *adapter, bool kill_watchdog);
 extern void ixgb_reset(struct ixgb_adapter *adapter);
diff --git a/drivers/net/ixgb/ixgb_ethtool.c b/drivers/net/ixgb/ixgb_ethtool.c
index 6da890b..ab404e7 100644
--- a/drivers/net/ixgb/ixgb_ethtool.c
+++ b/drivers/net/ixgb/ixgb_ethtool.c
@@ -115,7 +115,7 @@ ixgb_get_settings(struct net_device *netdev, struct ethtool_cmd *ecmd)
 	return 0;
 }
 
-static void ixgb_set_speed_duplex(struct net_device *netdev)
+void ixgb_set_speed_duplex(struct net_device *netdev)
 {
 	struct ixgb_adapter *adapter = netdev_priv(netdev);
 	/* be optimistic about our link, since we were up before */
@@ -195,57 +195,6 @@ ixgb_set_pauseparam(struct net_device *netdev,
 }
 
 static u32
-ixgb_get_rx_csum(struct net_device *netdev)
-{
-	struct ixgb_adapter *adapter = netdev_priv(netdev);
-
-	return adapter->rx_csum;
-}
-
-static int
-ixgb_set_rx_csum(struct net_device *netdev, u32 data)
-{
-	struct ixgb_adapter *adapter = netdev_priv(netdev);
-
-	adapter->rx_csum = data;
-
-	if (netif_running(netdev)) {
-		ixgb_down(adapter, true);
-		ixgb_up(adapter);
-		ixgb_set_speed_duplex(netdev);
-	} else
-		ixgb_reset(adapter);
-	return 0;
-}
-
-static u32
-ixgb_get_tx_csum(struct net_device *netdev)
-{
-	return (netdev->features & NETIF_F_HW_CSUM) != 0;
-}
-
-static int
-ixgb_set_tx_csum(struct net_device *netdev, u32 data)
-{
-	if (data)
-		netdev->features |= NETIF_F_HW_CSUM;
-	else
-		netdev->features &= ~NETIF_F_HW_CSUM;
-
-	return 0;
-}
-
-static int
-ixgb_set_tso(struct net_device *netdev, u32 data)
-{
-	if (data)
-		netdev->features |= NETIF_F_TSO;
-	else
-		netdev->features &= ~NETIF_F_TSO;
-	return 0;
-}
-
-static u32
 ixgb_get_msglevel(struct net_device *netdev)
 {
 	struct ixgb_adapter *adapter = netdev_priv(netdev);
@@ -685,43 +634,6 @@ ixgb_get_strings(struct net_device *netdev, u32 stringset, u8 *data)
 	}
 }
 
-static int ixgb_set_flags(struct net_device *netdev, u32 data)
-{
-	struct ixgb_adapter *adapter = netdev_priv(netdev);
-	bool need_reset;
-	int rc;
-
-	/*
-	 * Tx VLAN insertion does not work per HW design when Rx stripping is
-	 * disabled.  Disable txvlan when rxvlan is turned off, and enable
-	 * rxvlan when txvlan is turned on.
-	 */
-	if (!(data & ETH_FLAG_RXVLAN) &&
-	    (netdev->features & NETIF_F_HW_VLAN_TX))
-		data &= ~ETH_FLAG_TXVLAN;
-	else if (data & ETH_FLAG_TXVLAN)
-		data |= ETH_FLAG_RXVLAN;
-
-	need_reset = (data & ETH_FLAG_RXVLAN) !=
-		     (netdev->features & NETIF_F_HW_VLAN_RX);
-
-	rc = ethtool_op_set_flags(netdev, data, ETH_FLAG_RXVLAN |
-						ETH_FLAG_TXVLAN);
-	if (rc)
-		return rc;
-
-	if (need_reset) {
-		if (netif_running(netdev)) {
-			ixgb_down(adapter, true);
-			ixgb_up(adapter);
-			ixgb_set_speed_duplex(netdev);
-		} else
-			ixgb_reset(adapter);
-	}
-
-	return 0;
-}
-
 static const struct ethtool_ops ixgb_ethtool_ops = {
 	.get_settings = ixgb_get_settings,
 	.set_settings = ixgb_set_settings,
@@ -736,20 +648,12 @@ static const struct ethtool_ops ixgb_ethtool_ops = {
 	.set_ringparam = ixgb_set_ringparam,
 	.get_pauseparam	= ixgb_get_pauseparam,
 	.set_pauseparam	= ixgb_set_pauseparam,
-	.get_rx_csum = ixgb_get_rx_csum,
-	.set_rx_csum = ixgb_set_rx_csum,
-	.get_tx_csum = ixgb_get_tx_csum,
-	.set_tx_csum = ixgb_set_tx_csum,
-	.set_sg	= ethtool_op_set_sg,
 	.get_msglevel = ixgb_get_msglevel,
 	.set_msglevel = ixgb_set_msglevel,
-	.set_tso = ixgb_set_tso,
 	.get_strings = ixgb_get_strings,
 	.set_phys_id = ixgb_set_phys_id,
 	.get_sset_count = ixgb_get_sset_count,
 	.get_ethtool_stats = ixgb_get_ethtool_stats,
-	.get_flags = ethtool_op_get_flags,
-	.set_flags = ixgb_set_flags,
 };
 
 void ixgb_set_ethtool_ops(struct net_device *netdev)
diff --git a/drivers/net/ixgb/ixgb_main.c b/drivers/net/ixgb/ixgb_main.c
index 6a130eb..a2c47bf 100644
--- a/drivers/net/ixgb/ixgb_main.c
+++ b/drivers/net/ixgb/ixgb_main.c
@@ -325,6 +325,40 @@ ixgb_reset(struct ixgb_adapter *adapter)
 	}
 }
 
+static u32
+ixgb_fix_features(struct net_device *netdev, u32 features)
+{
+	/*
+	 * Tx VLAN insertion does not work per HW design when Rx stripping is
+	 * disabled.
+	 */
+	if (!(features & NETIF_F_HW_VLAN_RX))
+		features &= ~NETIF_F_HW_VLAN_TX;
+
+	return features;
+}
+
+static int
+ixgb_set_features(struct net_device *netdev, u32 features)
+{
+	struct ixgb_adapter *adapter = netdev_priv(netdev);
+	u32 changed = features ^ netdev->features;
+
+	if (!(changed & (NETIF_F_RXCSUM|NETIF_F_HW_VLAN_RX)))
+		return 0;
+
+	adapter->rx_csum = !!(features & NETIF_F_RXCSUM);
+
+	if (netif_running(netdev)) {
+		ixgb_down(adapter, true);
+		ixgb_up(adapter);
+		ixgb_set_speed_duplex(netdev);
+	} else
+		ixgb_reset(adapter);
+
+	return 0;
+}
+
 static const struct net_device_ops ixgb_netdev_ops = {
 	.ndo_open 		= ixgb_open,
 	.ndo_stop		= ixgb_close,
@@ -334,6 +368,8 @@ static const struct net_device_ops ixgb_netdev_ops = {
 	.ndo_validate_addr	= eth_validate_addr,
 	.ndo_set_mac_address	= ixgb_set_mac,
 	.ndo_change_mtu		= ixgb_change_mtu,
+	.ndo_fix_features       = ixgb_fix_features,
+	.ndo_set_features       = ixgb_set_features,
 	.ndo_tx_timeout		= ixgb_tx_timeout,
 	.ndo_vlan_rx_add_vid	= ixgb_vlan_rx_add_vid,
 	.ndo_vlan_rx_kill_vid	= ixgb_vlan_rx_kill_vid,
@@ -439,12 +475,14 @@ ixgb_probe(struct pci_dev *pdev, const struct pci_device_id *ent)
 	if (err)
 		goto err_sw_init;
 
-	netdev->features = NETIF_F_SG |
-			   NETIF_F_HW_CSUM |
+	netdev->hw_features = NETIF_F_SG |
+			   NETIF_F_TSO |
+			   NETIF_F_HW_CSUM;
+	netdev->features = netdev->hw_features |
 			   NETIF_F_HW_VLAN_TX |
 			   NETIF_F_HW_VLAN_RX |
 			   NETIF_F_HW_VLAN_FILTER;
-	netdev->features |= NETIF_F_TSO;
+	netdev->hw_features |= NETIF_F_RXCSUM;
 
 	if (pci_using_dac) {
 		netdev->features |= NETIF_F_HIGHDMA;
diff --git a/drivers/net/ixgbe/ixgbe_ethtool.c b/drivers/net/ixgbe/ixgbe_ethtool.c
index 4950d03..38ee164 100644
--- a/drivers/net/ixgbe/ixgbe_ethtool.c
+++ b/drivers/net/ixgbe/ixgbe_ethtool.c
@@ -442,62 +442,6 @@ static int ixgbe_set_pauseparam(struct net_device *netdev,
 	return 0;
 }
 
-static u32 ixgbe_get_rx_csum(struct net_device *netdev)
-{
-	struct ixgbe_adapter *adapter = netdev_priv(netdev);
-	return adapter->flags & IXGBE_FLAG_RX_CSUM_ENABLED;
-}
-
-static int ixgbe_set_rx_csum(struct net_device *netdev, u32 data)
-{
-	struct ixgbe_adapter *adapter = netdev_priv(netdev);
-	if (data)
-		adapter->flags |= IXGBE_FLAG_RX_CSUM_ENABLED;
-	else
-		adapter->flags &= ~IXGBE_FLAG_RX_CSUM_ENABLED;
-
-	return 0;
-}
-
-static u32 ixgbe_get_tx_csum(struct net_device *netdev)
-{
-	return (netdev->features & NETIF_F_IP_CSUM) != 0;
-}
-
-static int ixgbe_set_tx_csum(struct net_device *netdev, u32 data)
-{
-	struct ixgbe_adapter *adapter = netdev_priv(netdev);
-	u32 feature_list;
-
-	feature_list = (NETIF_F_IP_CSUM | NETIF_F_IPV6_CSUM);
-	switch (adapter->hw.mac.type) {
-	case ixgbe_mac_82599EB:
-	case ixgbe_mac_X540:
-		feature_list |= NETIF_F_SCTP_CSUM;
-		break;
-	default:
-		break;
-	}
-	if (data)
-		netdev->features |= feature_list;
-	else
-		netdev->features &= ~feature_list;
-
-	return 0;
-}
-
-static int ixgbe_set_tso(struct net_device *netdev, u32 data)
-{
-	if (data) {
-		netdev->features |= NETIF_F_TSO;
-		netdev->features |= NETIF_F_TSO6;
-	} else {
-		netdev->features &= ~NETIF_F_TSO;
-		netdev->features &= ~NETIF_F_TSO6;
-	}
-	return 0;
-}
-
 static u32 ixgbe_get_msglevel(struct net_device *netdev)
 {
 	struct ixgbe_adapter *adapter = netdev_priv(netdev);
@@ -2244,65 +2188,60 @@ static int ixgbe_set_coalesce(struct net_device *netdev,
 	return 0;
 }
 
-static int ixgbe_set_flags(struct net_device *netdev, u32 data)
+u32 ixgbe_fix_features(struct net_device *netdev, u32 features)
 {
 	struct ixgbe_adapter *adapter = netdev_priv(netdev);
-	bool need_reset = false;
-	int rc;
 
 #ifdef CONFIG_IXGBE_DCB
-	if ((adapter->flags & IXGBE_FLAG_DCB_ENABLED) &&
-	    !(data & ETH_FLAG_RXVLAN))
-		return -EINVAL;
+	if (adapter->flags & IXGBE_FLAG_DCB_ENABLED)
+		features |= NETIF_F_HW_VLAN_RX;
 #endif
 
-	need_reset = (data & ETH_FLAG_RXVLAN) !=
-		     (netdev->features & NETIF_F_HW_VLAN_RX);
-
-	if ((data & ETH_FLAG_RXHASH) &&
-	    !(adapter->flags & IXGBE_FLAG_RSS_ENABLED))
-		return -EOPNOTSUPP;
-
-	rc = ethtool_op_set_flags(netdev, data, ETH_FLAG_LRO | ETH_FLAG_NTUPLE |
-				  ETH_FLAG_RXVLAN | ETH_FLAG_TXVLAN |
-				  ETH_FLAG_RXHASH);
-	if (rc)
-		return rc;
-
-	/* if state changes we need to update adapter->flags and reset */
-	if ((adapter->flags2 & IXGBE_FLAG2_RSC_CAPABLE) &&
-	    (!!(data & ETH_FLAG_LRO) !=
-	     !!(adapter->flags2 & IXGBE_FLAG2_RSC_ENABLED))) {
-		if ((data & ETH_FLAG_LRO) &&
-		    (!adapter->rx_itr_setting ||
-		     (adapter->rx_itr_setting > IXGBE_MAX_RSC_INT_RATE))) {
+	if (!adapter->rx_itr_setting ||
+	    adapter->rx_itr_setting > IXGBE_MAX_RSC_INT_RATE) {
+		if (features & NETIF_F_LRO)
 			e_info(probe, "rx-usecs set too low, "
 				      "not enabling RSC.\n");
-		} else {
-			adapter->flags2 ^= IXGBE_FLAG2_RSC_ENABLED;
-			switch (adapter->hw.mac.type) {
-			case ixgbe_mac_82599EB:
-				need_reset = true;
-				break;
-			case ixgbe_mac_X540: {
-				int i;
-				for (i = 0; i < adapter->num_rx_queues; i++) {
-					struct ixgbe_ring *ring =
-					                  adapter->rx_ring[i];
-					if (adapter->flags2 &
-					    IXGBE_FLAG2_RSC_ENABLED) {
-						ixgbe_configure_rscctl(adapter,
-						                       ring);
-					} else {
-						ixgbe_clear_rscctl(adapter,
-						                   ring);
-					}
-				}
+		features &= ~NETIF_F_LRO;
+	}
+
+	if (!(adapter->flags & IXGBE_FLAG_RSS_ENABLED))
+		features &= ~NETIF_F_RXHASH;
+
+	return features;
+}
+
+int ixgbe_set_features(struct net_device *netdev, u32 features)
+{
+	struct ixgbe_adapter *adapter = netdev_priv(netdev);
+	u32 changed = netdev->features ^ features;
+	bool need_reset = !!(changed & NETIF_F_HW_VLAN_RX);
+
+	if (features & NETIF_F_RXCSUM)
+		adapter->flags |= IXGBE_FLAG_RX_CSUM_ENABLED;
+	else
+		adapter->flags &= ~IXGBE_FLAG_RX_CSUM_ENABLED;
+
+	/* if state changes we need to update adapter->flags and reset */
+	if (changed & NETIF_F_LRO) {
+		adapter->flags2 ^= IXGBE_FLAG2_RSC_ENABLED;
+		switch (adapter->hw.mac.type) {
+		case ixgbe_mac_82599EB:
+			need_reset = true;
+			break;
+		case ixgbe_mac_X540: {
+			int i;
+			for (i = 0; i < adapter->num_rx_queues; i++) {
+				struct ixgbe_ring *ring = adapter->rx_ring[i];
+				if (adapter->flags2 & IXGBE_FLAG2_RSC_ENABLED)
+					ixgbe_configure_rscctl(adapter, ring);
+				else
+					ixgbe_clear_rscctl(adapter, ring);
 			}
-				break;
-			default:
-				break;
+			break;
 			}
+		default:
+			break;
 		}
 	}
 
@@ -2310,20 +2249,17 @@ static int ixgbe_set_flags(struct net_device *netdev, u32 data)
 	 * Check if Flow Director n-tuple support was enabled or disabled.  If
 	 * the state changed, we need to reset.
 	 */
-	if ((adapter->flags & IXGBE_FLAG_FDIR_PERFECT_CAPABLE) &&
-	    (!(data & ETH_FLAG_NTUPLE))) {
-		/* turn off Flow Director perfect, set hash and reset */
-		adapter->flags &= ~IXGBE_FLAG_FDIR_PERFECT_CAPABLE;
-		adapter->flags |= IXGBE_FLAG_FDIR_HASH_CAPABLE;
+	if (changed & NETIF_F_NTUPLE) {
+		if (features & NETIF_F_NTUPLE) {
+			/* turn off Flow Director hash, enable perfect and reset */
+			adapter->flags &= ~IXGBE_FLAG_FDIR_HASH_CAPABLE;
+			adapter->flags |= IXGBE_FLAG_FDIR_PERFECT_CAPABLE;
+		} else {
+			/* turn off Flow Director perfect, set hash and reset */
+			adapter->flags &= ~IXGBE_FLAG_FDIR_PERFECT_CAPABLE;
+			adapter->flags |= IXGBE_FLAG_FDIR_HASH_CAPABLE;
+		}
 		need_reset = true;
-	} else if ((!(adapter->flags & IXGBE_FLAG_FDIR_PERFECT_CAPABLE)) &&
-	           (data & ETH_FLAG_NTUPLE)) {
-		/* turn off Flow Director hash, enable perfect and reset */
-		adapter->flags &= ~IXGBE_FLAG_FDIR_HASH_CAPABLE;
-		adapter->flags |= IXGBE_FLAG_FDIR_PERFECT_CAPABLE;
-		need_reset = true;
-	} else {
-		/* no state change */
 	}
 
 	if (need_reset) {
@@ -2487,16 +2423,8 @@ static const struct ethtool_ops ixgbe_ethtool_ops = {
 	.set_ringparam          = ixgbe_set_ringparam,
 	.get_pauseparam         = ixgbe_get_pauseparam,
 	.set_pauseparam         = ixgbe_set_pauseparam,
-	.get_rx_csum            = ixgbe_get_rx_csum,
-	.set_rx_csum            = ixgbe_set_rx_csum,
-	.get_tx_csum            = ixgbe_get_tx_csum,
-	.set_tx_csum            = ixgbe_set_tx_csum,
-	.get_sg                 = ethtool_op_get_sg,
-	.set_sg                 = ethtool_op_set_sg,
 	.get_msglevel           = ixgbe_get_msglevel,
 	.set_msglevel           = ixgbe_set_msglevel,
-	.get_tso                = ethtool_op_get_tso,
-	.set_tso                = ixgbe_set_tso,
 	.self_test              = ixgbe_diag_test,
 	.get_strings            = ixgbe_get_strings,
 	.set_phys_id            = ixgbe_set_phys_id,
@@ -2504,8 +2432,6 @@ static const struct ethtool_ops ixgbe_ethtool_ops = {
 	.get_ethtool_stats      = ixgbe_get_ethtool_stats,
 	.get_coalesce           = ixgbe_get_coalesce,
 	.set_coalesce           = ixgbe_set_coalesce,
-	.get_flags              = ethtool_op_get_flags,
-	.set_flags              = ixgbe_set_flags,
 	.set_rx_ntuple          = ixgbe_set_rx_ntuple,
 };
 
diff --git a/drivers/net/ixgbe/ixgbe_main.c b/drivers/net/ixgbe/ixgbe_main.c
index 06cfaf3..1a77310 100644
--- a/drivers/net/ixgbe/ixgbe_main.c
+++ b/drivers/net/ixgbe/ixgbe_main.c
@@ -7199,6 +7199,8 @@ static struct rtnl_link_stats64 *ixgbe_get_stats64(struct net_device *netdev,
 	return stats;
 }
 
+u32 ixgbe_fix_features(struct net_device *netdev, u32 features);
+int ixgbe_set_features(struct net_device *netdev, u32 features);
 
 static const struct net_device_ops ixgbe_netdev_ops = {
 	.ndo_open		= ixgbe_open,
@@ -7233,6 +7235,8 @@ static const struct net_device_ops ixgbe_netdev_ops = {
 	.ndo_fcoe_disable = ixgbe_fcoe_disable,
 	.ndo_fcoe_get_wwn = ixgbe_fcoe_get_wwn,
 #endif /* IXGBE_FCOE */
+	.ndo_fix_features = ixgbe_fix_features,
+	.ndo_set_features = ixgbe_set_features,
 };
 
 static void __devinit ixgbe_probe_vf(struct ixgbe_adapter *adapter,
@@ -7496,27 +7500,32 @@ static int __devinit ixgbe_probe(struct pci_dev *pdev,
 
 	ixgbe_probe_vf(adapter, ii);
 
-	netdev->features = NETIF_F_SG |
+	netdev->hw_features = NETIF_F_SG |
 			   NETIF_F_IP_CSUM |
+			   NETIF_F_IPV6_CSUM |
+			   NETIF_F_TSO |
+			   NETIF_F_TSO6 |
+			   NETIF_F_RXCSUM |
 			   NETIF_F_HW_VLAN_TX |
 			   NETIF_F_HW_VLAN_RX |
+			   NETIF_F_NTUPLE |
+			   NETIF_F_RXHASH;
+
+	if (adapter->flags2 & IXGBE_FLAG2_RSC_CAPABLE)
+		netdev->hw_features |= NETIF_F_LRO;
+
+	switch (adapter->hw.mac.type) {
+	case ixgbe_mac_82599EB:
+	case ixgbe_mac_X540:
+		netdev->hw_features |= NETIF_F_SCTP_CSUM;
+		break;
+	default:
+		break;
+	}
+
+	netdev->features = netdev->hw_features |
 			   NETIF_F_HW_VLAN_FILTER;
 
-	netdev->features |= NETIF_F_IPV6_CSUM;
-	netdev->features |= NETIF_F_TSO;
-	netdev->features |= NETIF_F_TSO6;
-	netdev->features |= NETIF_F_GRO;
-	netdev->features |= NETIF_F_RXHASH;
-
-	switch (adapter->hw.mac.type) {
-	case ixgbe_mac_82599EB:
-	case ixgbe_mac_X540:
-		netdev->features |= NETIF_F_SCTP_CSUM;
-		break;
-	default:
-		break;
-	}
-
 	netdev->vlan_features |= NETIF_F_TSO;
 	netdev->vlan_features |= NETIF_F_TSO6;
 	netdev->vlan_features |= NETIF_F_IP_CSUM;
diff --git a/drivers/net/ixgbevf/ethtool.c b/drivers/net/ixgbevf/ethtool.c
index deee375..e1d9e3b 100644
--- a/drivers/net/ixgbevf/ethtool.c
+++ b/drivers/net/ixgbevf/ethtool.c
@@ -117,44 +117,6 @@ static int ixgbevf_get_settings(struct net_device *netdev,
 	return 0;
 }
 
-static u32 ixgbevf_get_rx_csum(struct net_device *netdev)
-{
-	struct ixgbevf_adapter *adapter = netdev_priv(netdev);
-	return adapter->flags & IXGBE_FLAG_RX_CSUM_ENABLED;
-}
-
-static int ixgbevf_set_rx_csum(struct net_device *netdev, u32 data)
-{
-	struct ixgbevf_adapter *adapter = netdev_priv(netdev);
-	if (data)
-		adapter->flags |= IXGBE_FLAG_RX_CSUM_ENABLED;
-	else
-		adapter->flags &= ~IXGBE_FLAG_RX_CSUM_ENABLED;
-
-	if (netif_running(netdev)) {
-		if (!adapter->dev_closed)
-			ixgbevf_reinit_locked(adapter);
-	} else {
-		ixgbevf_reset(adapter);
-	}
-
-	return 0;
-}
-
-static int ixgbevf_set_tso(struct net_device *netdev, u32 data)
-{
-	if (data) {
-		netdev->features |= NETIF_F_TSO;
-		netdev->features |= NETIF_F_TSO6;
-	} else {
-		netif_tx_stop_all_queues(netdev);
-		netdev->features &= ~NETIF_F_TSO;
-		netdev->features &= ~NETIF_F_TSO6;
-		netif_tx_start_all_queues(netdev);
-	}
-	return 0;
-}
-
 static u32 ixgbevf_get_msglevel(struct net_device *netdev)
 {
 	struct ixgbevf_adapter *adapter = netdev_priv(netdev);
@@ -720,16 +682,8 @@ static struct ethtool_ops ixgbevf_ethtool_ops = {
 	.get_link               = ethtool_op_get_link,
 	.get_ringparam          = ixgbevf_get_ringparam,
 	.set_ringparam          = ixgbevf_set_ringparam,
-	.get_rx_csum            = ixgbevf_get_rx_csum,
-	.set_rx_csum            = ixgbevf_set_rx_csum,
-	.get_tx_csum            = ethtool_op_get_tx_csum,
-	.set_tx_csum            = ethtool_op_set_tx_ipv6_csum,
-	.get_sg                 = ethtool_op_get_sg,
-	.set_sg                 = ethtool_op_set_sg,
 	.get_msglevel           = ixgbevf_get_msglevel,
 	.set_msglevel           = ixgbevf_set_msglevel,
-	.get_tso                = ethtool_op_get_tso,
-	.set_tso                = ixgbevf_set_tso,
 	.self_test              = ixgbevf_diag_test,
 	.get_sset_count         = ixgbevf_get_sset_count,
 	.get_strings            = ixgbevf_get_strings,
diff --git a/drivers/net/ixgbevf/ixgbevf_main.c b/drivers/net/ixgbevf/ixgbevf_main.c
index b2c5ecd..8c2be31 100644
--- a/drivers/net/ixgbevf/ixgbevf_main.c
+++ b/drivers/net/ixgbevf/ixgbevf_main.c
@@ -3248,6 +3248,19 @@ static void ixgbevf_shutdown(struct pci_dev *pdev)
 	pci_disable_device(pdev);
 }
 
+static int ixgbevf_set_features(struct net_device *netdev, u32 features)
+{
+	struct ixgbevf_adapter *adapter = netdev_priv(netdev);
+
+	if (features & NETIF_F_RXCSUM)
+		adapter->flags |= IXGBE_FLAG_RX_CSUM_ENABLED;
+	else
+		adapter->flags &= ~IXGBE_FLAG_RX_CSUM_ENABLED;
+
+	return 0;
+}
+
+
 static const struct net_device_ops ixgbe_netdev_ops = {
 	.ndo_open		= &ixgbevf_open,
 	.ndo_stop		= &ixgbevf_close,
@@ -3261,6 +3274,7 @@ static const struct net_device_ops ixgbe_netdev_ops = {
 	.ndo_vlan_rx_register	= &ixgbevf_vlan_rx_register,
 	.ndo_vlan_rx_add_vid	= &ixgbevf_vlan_rx_add_vid,
 	.ndo_vlan_rx_kill_vid	= &ixgbevf_vlan_rx_kill_vid,
+	.ndo_set_features       = ixgbevf_set_features,
 };
 
 static void ixgbevf_assign_netdev_ops(struct net_device *dev)
@@ -3373,16 +3387,18 @@ static int __devinit ixgbevf_probe(struct pci_dev *pdev,
 	/* setup the private structure */
 	err = ixgbevf_sw_init(adapter);
 
-	netdev->features = NETIF_F_SG |
+	netdev->hw_features = NETIF_F_SG |
 			   NETIF_F_IP_CSUM |
+			   NETIF_F_IPV6_CSUM |
+			   NETIF_F_TSO |
+			   NETIF_F_TSO6 |
+			   NETIF_F_RXCSUM;
+
+	netdev->features = netdev->hw_features |
 			   NETIF_F_HW_VLAN_TX |
 			   NETIF_F_HW_VLAN_RX |
 			   NETIF_F_HW_VLAN_FILTER;
 
-	netdev->features |= NETIF_F_IPV6_CSUM;
-	netdev->features |= NETIF_F_TSO;
-	netdev->features |= NETIF_F_TSO6;
-	netdev->features |= NETIF_F_GRO;
 	netdev->vlan_features |= NETIF_F_TSO;
 	netdev->vlan_features |= NETIF_F_TSO6;
 	netdev->vlan_features |= NETIF_F_IP_CSUM;
-- 
1.7.2.5


^ permalink raw reply related

* iscsi related softlockup (3.0 rc3)
From: Dave Jones @ 2011-06-20 20:00 UTC (permalink / raw)
  To: netdev

I made some changes to my syscall fuzzer as it hasn't been turning up anything
interesting since the last lot of problems got fixed.  I seem to have found
a way to get iscsi really confused, to the point that the soft-lockup detector
kicks in, and then the rcu stall detector.

http://davej.fedorapeople.org/iscsi-lockup.txt is the dmesg from the box.
sysrq was working, but I couldn't ssh into the box, or even log in on the console.
I had ssh sessions already logged into the box which were completely wedged.

I don't have any iscsi setup configured on this machine, the fuzzer just hit upon
that protocol randomly.  If it wasn't for the fact that the machine wedged I wouldn't
be overly concerned, but it seems that something got into a state that just consumed
all cpu time.

	Dave


^ permalink raw reply

* Re: pull request: batman-adv 2011-06-20
From: David Miller @ 2011-06-20 20:01 UTC (permalink / raw)
  To: sven-KaDOiPu9UxWEi8DpZVb4nw
  Cc: netdev-u79uwXL29TY76Z2rM5mHXA,
	b.a.t.m.a.n-ZwoEplunGu2X36UT3dwllkB+6BGkLq7r
In-Reply-To: <1308565025-21293-1-git-send-email-sven-KaDOiPu9UxWEi8DpZVb4nw@public.gmane.org>

From: Sven Eckelmann <sven-KaDOiPu9UxWEi8DpZVb4nw@public.gmane.org>
Date: Mon, 20 Jun 2011 12:16:53 +0200

> I would like to propose following changes for net-next-2.6/3.1. The
> first part (1-4) are only only small cleanup patches. The last 8 patches
> are related to Antonio Quartulli's research "Client announcement and
> Fast roaming in a Layer-2 mesh network". The technical report isn't
> published yet, but will hopefully follow soon. He tried to document all
> important parts in some (unofficial) documents [1,2,3].

Pulled, but you should seriously consider locking down the on-the-wire
protocol at some point and only make backward compatible changes to it
from that point forward.

^ permalink raw reply

* Re: [PATCH net-next-2.6] myricom: remove stats_lock
From: David Miller @ 2011-06-20 20:02 UTC (permalink / raw)
  To: eric.dumazet; +Cc: netdev, gallatin, brice, shemminger
In-Reply-To: <1308550066.3539.129.camel@edumazet-laptop>

From: Eric Dumazet <eric.dumazet@gmail.com>
Date: Mon, 20 Jun 2011 08:07:46 +0200

> stats_lock is non useless, lets remove it.
> 
> Also, ndo_get_stats64() doesnt have to clear the stats, caller takes
> care of this.
> 
> Note: folding 32bit fields in 64bit one is problematic when one of 32bit
> values wraps : SNMP reader will see a ~2^32 back change in a 64bit
> value. A future patch should fix this.
> 
> Signed-off-by: Eric Dumazet <eric.dumazet@gmail.com>

Applied.

^ permalink raw reply

* Re: [PATCH][Trivial]: ipv4, ping: Remove duplicate icmp.h include
From: David Miller @ 2011-06-20 20:05 UTC (permalink / raw)
  To: jj; +Cc: netdev, segoon, linux-kernel, trivial
In-Reply-To: <alpine.LNX.2.00.1106201028340.18991@swampdragon.chaosbits.net>

From: Jesper Juhl <jj@chaosbits.net>
Date: Mon, 20 Jun 2011 10:31:20 +0200 (CEST)

> Remove the duplicate inclusion of net/icmp.h from net/ipv4/ping.c
> 
> Signed-off-by: Jesper Juhl <jj@chaosbits.net>

Applied.

^ permalink raw reply

* Re: [PATCH] netxen: fix race in skb->len access
From: David Miller @ 2011-06-20 20:05 UTC (permalink / raw)
  To: eric.dumazet; +Cc: netdev, amit.salecha
In-Reply-To: <1308551175.3539.133.camel@edumazet-laptop>

From: Eric Dumazet <eric.dumazet@gmail.com>
Date: Mon, 20 Jun 2011 08:26:15 +0200

> As soon as skb is given to hardware, TX completion can free skb under
> us.
> Therefore, we should update dev stats before kicking the device.
> 
> Signed-off-by: Eric Dumazet <eric.dumazet@gmail.com>

Applied.

^ permalink raw reply


This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox