Netdev List
 help / color / mirror / Atom feed
* [PATCH 3/3] net: tipc: fix information leak to userland
From: Vasiliy Kulikov @ 2010-10-31 17:10 UTC (permalink / raw)
  To: kernel-janitors
  Cc: Jon Maloy, Allan Stephens, David S. Miller, tipc-discussion,
	netdev, linux-kernel

Structure sockaddr_tipc is copied to userland with padding bytes after
"id" field in union field "name" unitialized.  It leads to leaking of
contents of kernel stack memory.  We have to initialize them to zero.

Signed-off-by: Vasiliy Kulikov <segooon@gmail.com>
---
 net/tipc/socket.c |    1 +
 1 files changed, 1 insertions(+), 0 deletions(-)

diff --git a/net/tipc/socket.c b/net/tipc/socket.c
index 33217fc..e9f0d50 100644
--- a/net/tipc/socket.c
+++ b/net/tipc/socket.c
@@ -396,6 +396,7 @@ static int get_name(struct socket *sock, struct sockaddr *uaddr,
 	struct sockaddr_tipc *addr = (struct sockaddr_tipc *)uaddr;
 	struct tipc_sock *tsock = tipc_sk(sock->sk);
 
+	memset(addr, 0, sizeof(*addr));
 	if (peer) {
 		if ((sock->state != SS_CONNECTED) &&
 			((peer != 2) || (sock->state != SS_DISCONNECTING)))
-- 
1.7.0.4


^ permalink raw reply related

* [PATCH 2/3] net: packet: fix information leak to userland
From: Vasiliy Kulikov @ 2010-10-31 17:10 UTC (permalink / raw)
  To: kernel-janitors
  Cc: David S. Miller, Jiri Pirko, Eric Dumazet, netdev, linux-kernel

packet_getname_spkt() doesn't initialize all members of sa_data field of
sockaddr struct if strlen(dev->name) < 13.  This structure is then copied
to userland.  It leads to leaking of contents of kernel stack memory.
We have to fully fill sa_data with strncpy() instead of strlcpy().

The same with packet_getname(): it doesn't initialize sll_pkttype field of
sockaddr_ll.  Set it to zero.

Signed-off-by: Vasiliy Kulikov <segooon@gmail.com>
---
 net/packet/af_packet.c |    3 ++-
 1 files changed, 2 insertions(+), 1 deletions(-)

diff --git a/net/packet/af_packet.c b/net/packet/af_packet.c
index 3616f27..0856a13 100644
--- a/net/packet/af_packet.c
+++ b/net/packet/af_packet.c
@@ -1719,7 +1719,7 @@ static int packet_getname_spkt(struct socket *sock, struct sockaddr *uaddr,
 	rcu_read_lock();
 	dev = dev_get_by_index_rcu(sock_net(sk), pkt_sk(sk)->ifindex);
 	if (dev)
-		strlcpy(uaddr->sa_data, dev->name, 15);
+		strncpy(uaddr->sa_data, dev->name, 14);
 	else
 		memset(uaddr->sa_data, 0, 14);
 	rcu_read_unlock();
@@ -1742,6 +1742,7 @@ static int packet_getname(struct socket *sock, struct sockaddr *uaddr,
 	sll->sll_family = AF_PACKET;
 	sll->sll_ifindex = po->ifindex;
 	sll->sll_protocol = po->num;
+	sll->sll_pkttype = 0;
 	rcu_read_lock();
 	dev = dev_get_by_index_rcu(sock_net(sk), po->ifindex);
 	if (dev) {
-- 
1.7.0.4


^ permalink raw reply related

* [PATCH 1/3] net: ax25: fix information leak to userland
From: Vasiliy Kulikov @ 2010-10-31 17:10 UTC (permalink / raw)
  To: kernel-janitors
  Cc: Joerg Reuter, Ralf Baechle, David S. Miller, linux-hams, netdev,
	linux-kernel

Sometimes ax25_getname() doesn't initialize all members of fsa_digipeater
field of fsa struct.  This structure is then copied to userland.  It leads to
leaking of contents of kernel stack memory.  We have to initialize them to zero.

Signed-off-by: Vasiliy Kulikov <segooon@gmail.com>
---
 net/ax25/af_ax25.c |    1 +
 1 files changed, 1 insertions(+), 0 deletions(-)

diff --git a/net/ax25/af_ax25.c b/net/ax25/af_ax25.c
index 26eaebf..a324d83 100644
--- a/net/ax25/af_ax25.c
+++ b/net/ax25/af_ax25.c
@@ -1392,6 +1392,7 @@ static int ax25_getname(struct socket *sock, struct sockaddr *uaddr,
 	ax25_cb *ax25;
 	int err = 0;
 
+	memset(&fsa->fsa_digipeater, 0, sizeof(fsa->fsa_digipeater));
 	lock_sock(sk);
 	ax25 = ax25_sk(sk);
 
-- 
1.7.0.4


^ permalink raw reply related

* AFFORDABLE LOAN OFFER!!!
From: ASIAWORLD LOAN COMPANY @ 2010-10-31 16:05 UTC (permalink / raw)




  We offer Loan to serious individuals or Organization with low  
interest rate of
  3%. Contact us via e-mail: asiaworldloan@yahoo.com.hk or Tel: +233543956345


^ permalink raw reply

* Re: [PATCH] text ematch: check for NULL pointer before destroying textsearch config
From: David Miller @ 2010-10-31 16:38 UTC (permalink / raw)
  To: tgraf; +Cc: netdev
In-Reply-To: <20101031080635.GA22639@canuck.infradead.org>

From: Thomas Graf <tgraf@infradead.org>
Date: Sun, 31 Oct 2010 04:06:35 -0400

> While validating the configuration em_ops is already set, thus the
> individual destroy functions are called, but the ematch data has
> not been allocated and associated with the ematch yet.
> 
> Signed-off-by: Thomas Graf <tgraf@infradead.org>

Applied, thanks Thomas.

^ permalink raw reply

* Re: [PATCH] qlcnic: fix panic on load
From: David Miller @ 2010-10-31 16:34 UTC (permalink / raw)
  To: eric.dumazet; +Cc: netdev, amit.salecha
In-Reply-To: <1288540238.2660.50.camel@edumazet-laptop>

From: Eric Dumazet <eric.dumazet@gmail.com>
Date: Sun, 31 Oct 2010 16:50:38 +0100

> Its now illegal to call netif_stop_queue() before register_netdev()
> 
> Signed-off-by: Eric Dumazet <eric.dumazet@gmail.com>

Applied.

^ permalink raw reply

* Re: [PATCH] jme: fix panic on load
From: David Miller @ 2010-10-31 16:34 UTC (permalink / raw)
  To: eric.dumazet; +Cc: netdev, cooldavid
In-Reply-To: <1288539978.2660.47.camel@edumazet-laptop>

From: Eric Dumazet <eric.dumazet@gmail.com>
Date: Sun, 31 Oct 2010 16:46:18 +0100

> Its now illegal to call netif_stop_queue() before register_netdev()
> 
> Signed-off-by: Eric Dumazet <eric.dumazet@gmail.com>

Applied.

^ permalink raw reply

* Re: [PATCH] jme: fix panic on load
From: Eric Dumazet @ 2010-10-31 16:32 UTC (permalink / raw)
  To: Guo-Fu Tseng; +Cc: David Miller, netdev
In-Reply-To: <20101031163428.M61655@cooldavid.org>

Le lundi 01 novembre 2010 à 00:39 +0800, Guo-Fu Tseng a écrit :
> Can this patch be modified to move the netif_stop_queue()
> after register_netdev() ?
> It seems the __QUEUE_STATE_XOFF is not set after the register_netdev.
> The tx_queue was kcalloc() ed without touching state flags.
> 

Real question is : why this netif_stop_queue() was needed at the first
place ?

We believe (David and others), that using before ndo_open() is useless
or a sign of design error.

http://www.spinics.net/lists/netdev/msg145481.html


Refs: commit c117e4a2bb4911

If your driver doesnt work after my change, then another patch is
needed, but not using netif_stop_queue() right after register_netdev()




^ permalink raw reply

* Re: [PATCH] jme: fix panic on load
From: David Miller @ 2010-10-31 16:26 UTC (permalink / raw)
  To: cooldavid; +Cc: eric.dumazet, netdev
In-Reply-To: <20101031163428.M61655@cooldavid.org>

From: "Guo-Fu Tseng" <cooldavid@cooldavid.org>
Date: Mon, 1 Nov 2010 00:39:14 +0800

> On Sun, 31 Oct 2010 16:46:18 +0100, Eric Dumazet wrote
> Can this patch be modified to move the netif_stop_queue()
> after register_netdev() ?
> It seems the __QUEUE_STATE_XOFF is not set after the register_netdev.
> The tx_queue was kcalloc() ed without touching state flags.

At the veyr moment that register_netdev() is called, the
->open() method of your driver can be invoked and the
queue state changed.

So no, you can't put it after the register call.

There is zero reason to touch the queue state in your
probe routine, the state of the queue before ->open()
is "don't care".

Eric's patch is going to be applied, it is correct.

^ permalink raw reply

* Re: [PATCH] jme: fix panic on load
From: Guo-Fu Tseng @ 2010-10-31 16:39 UTC (permalink / raw)
  To: Eric Dumazet, David Miller; +Cc: netdev
In-Reply-To: <1288539978.2660.47.camel@edumazet-laptop>

On Sun, 31 Oct 2010 16:46:18 +0100, Eric Dumazet wrote
> Its now illegal to call netif_stop_queue() before register_netdev()
> 
> Signed-off-by: Eric Dumazet <eric.dumazet@gmail.com>
> Cc: Guo-Fu Tseng <cooldavid@cooldavid.org>
> ---
>  drivers/net/jme.c |    4 ----
>  1 file changed, 4 deletions(-)
> 
> diff --git a/drivers/net/jme.c b/drivers/net/jme.c
> index d85edf3..c57d9a4 100644
> --- a/drivers/net/jme.c
> +++ b/drivers/net/jme.c
> @@ -2955,11 +2955,7 @@ jme_init_one(struct pci_dev *pdev,
>  	 * Tell stack that we are not ready to work until open()
>  	 */
>  	netif_carrier_off(netdev);
> -	netif_stop_queue(netdev);
> 
> -	/*
> -	 * Register netdev
> -	 */
>  	rc = register_netdev(netdev);
>  	if (rc) {
>  		pr_err("Cannot register net device\n");
> 
> --
> To unsubscribe from this list: send the line "unsubscribe netdev" in
> the body of a message to majordomo@vger.kernel.org
> More majordomo info at  http://vger.kernel.org/majordomo-info.html
Can this patch be modified to move the netif_stop_queue()
after register_netdev() ?
It seems the __QUEUE_STATE_XOFF is not set after the register_netdev.
The tx_queue was kcalloc() ed without touching state flags.

Guo-Fu Tseng


^ permalink raw reply

* [PATCH] qlcnic: fix panic on load
From: Eric Dumazet @ 2010-10-31 15:50 UTC (permalink / raw)
  To: David Miller; +Cc: netdev, Amit Kumar Salecha

Its now illegal to call netif_stop_queue() before register_netdev()

Signed-off-by: Eric Dumazet <eric.dumazet@gmail.com>
Cc: Amit Kumar Salecha <amit.salecha@qlogic.com>
---
 drivers/net/qlcnic/qlcnic_main.c |    1 -
 1 file changed, 1 deletion(-)

diff --git a/drivers/net/qlcnic/qlcnic_main.c b/drivers/net/qlcnic/qlcnic_main.c
index 7a298cd..a3dcd04 100644
--- a/drivers/net/qlcnic/qlcnic_main.c
+++ b/drivers/net/qlcnic/qlcnic_main.c
@@ -1450,7 +1450,6 @@ qlcnic_setup_netdev(struct qlcnic_adapter *adapter,
 	netdev->irq = adapter->msix_entries[0].vector;
 
 	netif_carrier_off(netdev);
-	netif_stop_queue(netdev);
 
 	err = register_netdev(netdev);
 	if (err) {



^ permalink raw reply related

* [PATCH] jme: fix panic on load
From: Eric Dumazet @ 2010-10-31 15:46 UTC (permalink / raw)
  To: David Miller; +Cc: netdev, Guo-Fu Tseng

Its now illegal to call netif_stop_queue() before register_netdev()

Signed-off-by: Eric Dumazet <eric.dumazet@gmail.com>
Cc: Guo-Fu Tseng <cooldavid@cooldavid.org>
---
 drivers/net/jme.c |    4 ----
 1 file changed, 4 deletions(-)

diff --git a/drivers/net/jme.c b/drivers/net/jme.c
index d85edf3..c57d9a4 100644
--- a/drivers/net/jme.c
+++ b/drivers/net/jme.c
@@ -2955,11 +2955,7 @@ jme_init_one(struct pci_dev *pdev,
 	 * Tell stack that we are not ready to work until open()
 	 */
 	netif_carrier_off(netdev);
-	netif_stop_queue(netdev);
 
-	/*
-	 * Register netdev
-	 */
 	rc = register_netdev(netdev);
 	if (rc) {
 		pr_err("Cannot register net device\n");



^ permalink raw reply related

* [PATCH 2/2] af_unix: optimize unix_dgram_poll()
From: Eric Dumazet @ 2010-10-31 15:38 UTC (permalink / raw)
  To: David Miller; +Cc: netdev, Davide Libenzi, Alban Crequy

unix_dgram_poll() is pretty expensive to check POLLOUT status, because
it has to lock the socket to get its peer, take a reference on the peer
to check its receive queue status, and queue another poll_wait on
peer_wait. This all can be avoided if the process calling
unix_dgram_poll() is not interested in POLLOUT status. It makes
unix_dgram_recvmsg() faster by not queueing irrelevant pollers in
peer_wait.

On a test program provided by Alan Crequy :

Before:

real    0m0.211s
user    0m0.000s
sys     0m0.208s

After:

real    0m0.044s
user    0m0.000s
sys     0m0.040s

Suggested-by: Davide Libenzi <davidel@xmailserver.org>
Reported-by: Alban Crequy <alban.crequy@collabora.co.uk>
Acked-by: Davide Libenzi <davidel@xmailserver.org>
Signed-off-by: Eric Dumazet <eric.dumazet@gmail.com>
---
 net/unix/af_unix.c |    4 ++++
 1 file changed, 4 insertions(+)

diff --git a/net/unix/af_unix.c b/net/unix/af_unix.c
index 7375131..7067c5d 100644
--- a/net/unix/af_unix.c
+++ b/net/unix/af_unix.c
@@ -2089,6 +2089,10 @@ static unsigned int unix_dgram_poll(struct file *file, struct socket *sock,
 			return mask;
 	}
 
+	/* No write status requested, avoid expensive OUT tests. */
+	if (wait && !(wait->key & (POLLWRBAND | POLLWRNORM | POLLOUT)))
+		return mask;
+
 	writable = unix_writable(sk);
 	other = unix_peer_get(sk);
 	if (other) {



^ permalink raw reply related

* [PATCH 1/2] af_unix: fix unix_dgram_poll() behavior for EPOLLOUT event
From: Eric Dumazet @ 2010-10-31 15:36 UTC (permalink / raw)
  To: Alban Crequy, David Miller; +Cc: netdev, Davide Libenzi
In-Reply-To: <20101030224703.065e70f6@chocolatine.cbg.collabora.co.uk>

Le samedi 30 octobre 2010 à 22:47 +0100, Alban Crequy a écrit :
> Le Sat, 30 Oct 2010 15:17:58 +0200,
> Eric Dumazet <eric.dumazet@gmail.com> a écrit :
> 
> > > Problem is the peer_wait, that epoll doesnt seem to be plugged into.
> > > 
> > > Bug is in unix_dgram_poll()
> > > 
> > > It calls sock_poll_wait( ... &unix_sk(other)->peer_wait,) only if
> > > socket is 'writable'. Its a clear bug
> 
> Yes, it looks weird...
> 
> > > Try this patch please ?
> 
> I will be away from computer and I will continue to work on this from
> the 20th of November.

OK, no problem. I tried it and it solves the problem. Here is an
official patch submission.

David, for your convenience, I cooked a patch serie for the 2 patches
against af_unix unix_dgram_poll().

The third patch (af_unix: unix_write_space() use keyed wakeups)) can be
applied as is.

Thanks !

[PATCH 1/2] af_unix: fix unix_dgram_poll() behavior for EPOLLOUT event

Alban Crequy reported a problem with connected dgram af_unix sockets and
provided a test program. epoll() would miss to send an EPOLLOUT event
when a thread unqueues a packet from the other peer, making its receive
queue not full.

This is because unix_dgram_poll() fails to call sock_poll_wait(file,
&unix_sk(other)->peer_wait, wait);
if the socket is not writeable at the time epoll_ctl(ADD) is called. 

We must call sock_poll_wait(), regardless of 'writable' status, so that
epoll can be notified later of states changes.

Misc: avoids testing twice (sk->sk_shutdown & RCV_SHUTDOWN)

Reported-by: Alban Crequy <alban.crequy@collabora.co.uk>
Cc: Davide Libenzi <davidel@xmailserver.org>
Signed-off-by: Eric Dumazet <eric.dumazet@gmail.com>
---
 net/unix/af_unix.c |   24 +++++++++---------------
 1 file changed, 9 insertions(+), 15 deletions(-)

diff --git a/net/unix/af_unix.c b/net/unix/af_unix.c
index 0ebc777..7375131 100644
--- a/net/unix/af_unix.c
+++ b/net/unix/af_unix.c
@@ -2072,13 +2072,12 @@ static unsigned int unix_dgram_poll(struct file *file, struct socket *sock,
 	if (sk->sk_err || !skb_queue_empty(&sk->sk_error_queue))
 		mask |= POLLERR;
 	if (sk->sk_shutdown & RCV_SHUTDOWN)
-		mask |= POLLRDHUP;
+		mask |= POLLRDHUP | POLLIN | POLLRDNORM;
 	if (sk->sk_shutdown == SHUTDOWN_MASK)
 		mask |= POLLHUP;
 
 	/* readable? */
-	if (!skb_queue_empty(&sk->sk_receive_queue) ||
-	    (sk->sk_shutdown & RCV_SHUTDOWN))
+	if (!skb_queue_empty(&sk->sk_receive_queue))
 		mask |= POLLIN | POLLRDNORM;
 
 	/* Connection-based need to check for termination and startup */
@@ -2090,20 +2089,15 @@ static unsigned int unix_dgram_poll(struct file *file, struct socket *sock,
 			return mask;
 	}
 
-	/* writable? */
 	writable = unix_writable(sk);
-	if (writable) {
-		other = unix_peer_get(sk);
-		if (other) {
-			if (unix_peer(other) != sk) {
-				sock_poll_wait(file, &unix_sk(other)->peer_wait,
-					  wait);
-				if (unix_recvq_full(other))
-					writable = 0;
-			}
-
-			sock_put(other);
+	other = unix_peer_get(sk);
+	if (other) {
+		if (unix_peer(other) != sk) {
+			sock_poll_wait(file, &unix_sk(other)->peer_wait, wait);
+			if (unix_recvq_full(other))
+				writable = 0;
 		}
+		sock_put(other);
 	}
 
 	if (writable)



^ permalink raw reply related

* Re: [PATCH v2 02/22] bitops: rename generic little-endian bitops functions
From: Hans-Christian Egtvedt @ 2010-10-31 14:02 UTC (permalink / raw)
  To: Akinobu Mita
  Cc: linux-kernel, linux-arch, Arnd Bergmann, Christoph Hellwig,
	Andrew Morton, Hans-Christian Egtvedt, Geert Uytterhoeven,
	Roman Zippel, Andreas Schwab, linux-m68k, Greg Ungerer,
	Benjamin Herrenschmidt, Paul Mackerras, linuxppc-dev, Andy Grover,
	rds-devel, David S. Miller, netdev, Avi Kivity, Marcelo Tosatti,
	kvm
In-Reply-To: <1287672077-5797-3-git-send-email-akinobu.mita@gmail.com>

Around Thu 21 Oct 2010 23:40:57 +0900 or thereabout, Akinobu Mita wrote:
> As a preparation for providing little-endian bitops for all architectures,
> This removes generic_ prefix from little-endian bitops function names
> in asm-generic/bitops/le.h.
> 
> s/generic_find_next_le_bit/find_next_le_bit/
> s/generic_find_next_zero_le_bit/find_next_zero_le_bit/
> s/generic_find_first_zero_le_bit/find_first_zero_le_bit/
> s/generic___test_and_set_le_bit/__test_and_set_le_bit/
> s/generic___test_and_clear_le_bit/__test_and_clear_le_bit/
> s/generic_test_le_bit/test_le_bit/
> s/generic___set_le_bit/__set_le_bit/
> s/generic___clear_le_bit/__clear_le_bit/
> s/generic_test_and_set_le_bit/test_and_set_le_bit/
> s/generic_test_and_clear_le_bit/test_and_clear_le_bit/
> 
> Signed-off-by: Akinobu Mita <akinobu.mita@gmail.com>
> Cc: Hans-Christian Egtvedt <hans-christian.egtvedt@atmel.com>
> Cc: Geert Uytterhoeven <geert@linux-m68k.org>
> Cc: Roman Zippel <zippel@linux-m68k.org>
> Cc: Andreas Schwab <schwab@linux-m68k.org>
> Cc: linux-m68k@lists.linux-m68k.org
> Cc: Greg Ungerer <gerg@uclinux.org>
> Cc: Benjamin Herrenschmidt <benh@kernel.crashing.org>
> Cc: Paul Mackerras <paulus@samba.org>
> Cc: linuxppc-dev@lists.ozlabs.org
> Cc: Andy Grover <andy.grover@oracle.com>
> Cc: rds-devel@oss.oracle.com
> Cc: "David S. Miller" <davem@davemloft.net>
> Cc: netdev@vger.kernel.org
> Cc: Avi Kivity <avi@redhat.com>
> Cc: Marcelo Tosatti <mtosatti@redhat.com>
> Cc: kvm@vger.kernel.org
> ---
> No change from previous submission
> 
>  arch/avr32/kernel/avr32_ksyms.c              |    4 ++--
>  arch/avr32/lib/findbit.S                     |    4 ++--

For the AVR32 changes.

Acked-by: Hans-Christian Egtvedt <hans-christian.egtvedt@atmel.com>

<snipp patch>

-- 
Best regards, Hans-Christian Egtvedt

^ permalink raw reply

* Re: [GIT] Networking
From: David Miller @ 2010-10-31 13:42 UTC (permalink / raw)
  To: ben; +Cc: torvalds, akpm, netdev, linux-kernel
In-Reply-To: <1288516747.4050.10.camel@localhost>

From: Ben Hutchings <ben@decadent.org.uk>
Date: Sun, 31 Oct 2010 10:19:07 +0100

> On Sat, 2010-10-30 at 18:32 -0700, David Miller wrote:
>> Last pull request before 2.6.37-rc1, I really wanted to get your
>> sendto/recvfrom patch in here as well as the RDS fixes.
>> 
>> I did a bunch of tests with the various I/O calls using different
>> lengths, like 10, (2^31 - 1), 2^31, 2^32, and larger on 64-bit and it
>> all seems to be doing the right thing at least with TCP and UDP.
> [...]
>> 7) RDS fixes from you and Andy Grover.
> [...]
> 
> Aren't the generic length limiting changes (8acfe46 and 253eacc) also
> supposed to cover the overflow issues with TIPC?  Or are those still
> unfixed?

Yes, the TIPC issues should be cured by those generic networking changes.

^ permalink raw reply

* tc action mirred packet lost
From: Nieścierowicz Adam @ 2010-10-31 12:44 UTC (permalink / raw)
  To: netdev

 Hello,
 recently there was a need to create 3-4 copies of the data sent to the 
 router, I decided to use the tc action mirred.


 Ingress traficn on eth1 copies to eth1 eth2, eth3, eth4, eth5 using:
 ---
 tc qdisc add dev eth1 ingress

 tc filter add dev eth1 parent ffff: protocol ip prio 10 u32 match ip 
 src
 0/0 flowid 1:1 action mirred egress mirror dev eth2 pipe action mirred
 egress mirror dev eth3 pipe action mirred egress mirror dev eth4 pipe
 action mirred egress mirror dev eth5
 --


 Unfortunately the number of packets seen on eth1 qdisc is different 
 than the eth [2-5]
 ---
 12:02:57 CET
 qdisc pfifo_fast 0: dev eth0 root refcnt 2 bands 3 priomap  1 2 2 2 1 2 
 0 0 1 1 1 1 1 1 1 1
  Sent 668167 bytes 6001 pkt (dropped 0, overlimits 0 requeues 0)
  backlog 0b 0p requeues 0
 qdisc pfifo_fast 0: dev eth1 root refcnt 2 bands 3 priomap  1 2 2 2 1 2 
 0 0 1 1 1 1 1 1 1 1
  Sent 36336 bytes 860 pkt (dropped 0, overlimits 0 requeues 0)
  backlog 0b 0p requeues 0
 qdisc ingress ffff: dev eth1 parent ffff:fff1 ----------------
  Sent 7221533005980 bytes 199468106 pkt (dropped 0, overlimits 0 
 requeues 0)
  backlog 0b 0p requeues 0
 qdisc htb 1: dev eth2 root refcnt 2 r2q 10 default 0 
 direct_packets_stat 197808186 ver 3.17
  Sent 7404614590804 bytes 197808186 pkt (dropped 0, overlimits 0 
 requeues 1976)
  backlog 0b 0p requeues 1976
 qdisc pfifo_fast 0: dev eth3 root refcnt 2 bands 3 priomap  1 2 2 2 1 2 
 0 0 1 1 1 1 1 1 1 1
  Sent 7404614590804 bytes 197808186 pkt (dropped 0, overlimits 0 
 requeues 2779)
  backlog 0b 0p requeues 2779
 qdisc pfifo_fast 0: dev eth4 root refcnt 2 bands 3 priomap  1 2 2 2 1 2 
 0 0 1 1 1 1 1 1 1 1
  Sent 7404614590804 bytes 197808186 pkt (dropped 0, overlimits 0 
 requeues 1958)
  backlog 0b 0p requeues 1958
 qdisc pfifo_fast 0: dev eth5 root refcnt 2 bands 3 priomap  1 2 2 2 1 2 
 0 0 1 1 1 1 1 1 1 1
  Sent 7404614590804 bytes 197808186 pkt (dropped 0, overlimits 0 
 requeues 3231)
  backlog 0b 0p requeues 3231

 12:03:07 CET
 qdisc pfifo_fast 0: dev eth0 root refcnt 2 bands 3 priomap  1 2 2 2 1 2 
 0 0 1 1 1 1 1 1 1 1
  Sent 669819 bytes 6003 pkt (dropped 0, overlimits 0 requeues 0)
  backlog 0b 0p requeues 0
 qdisc pfifo_fast 0: dev eth1 root refcnt 2 bands 3 priomap  1 2 2 2 1 2 
 0 0 1 1 1 1 1 1 1 1
  Sent 36336 bytes 860 pkt (dropped 0, overlimits 0 requeues 0)
  backlog 0b 0p requeues 0
 qdisc ingress ffff: dev eth1 parent ffff:fff1 ----------------
  Sent 7221762321336 bytes 199909173 pkt (dropped 0, overlimits 0 
 requeues 0)
  backlog 0b 0p requeues 0
 qdisc htb 1: dev eth2 root refcnt 2 r2q 10 default 0 
 direct_packets_stat 198249138 ver 3.17
  Sent 7404850074198 bytes 198249138 pkt (dropped 0, overlimits 0 
 requeues 1976)
  backlog 0b 0p requeues 1976
 qdisc pfifo_fast 0: dev eth3 root refcnt 2 bands 3 priomap  1 2 2 2 1 2 
 0 0 1 1 1 1 1 1 1 1
  Sent 7404850074198 bytes 198249138 pkt (dropped 0, overlimits 0 
 requeues 2779)
  backlog 0b 0p requeues 2779
 qdisc pfifo_fast 0: dev eth4 root refcnt 2 bands 3 priomap  1 2 2 2 1 2 
 0 0 1 1 1 1 1 1 1 1
  Sent 7404850074198 bytes 198249138 pkt (dropped 0, overlimits 0 
 requeues 1958)
  backlog 0b 0p requeues 1958
 qdisc pfifo_fast 0: dev eth5 root refcnt 2 bands 3 priomap  1 2 2 2 1 2 
 0 0 1 1 1 1 1 1 1 1
  Sent 7404850074198 bytes 198249138 pkt (dropped 0, overlimits 0 
 requeues 3232)
  backlog 0b 0p requeues 3232

 12:03:17 CET
 qdisc pfifo_fast 0: dev eth0 root refcnt 2 bands 3 priomap  1 2 2 2 1 2 
 0 0 1 1 1 1 1 1 1 1
  Sent 671439 bytes 6005 pkt (dropped 0, overlimits 0 requeues 0)
  backlog 0b 0p requeues 0
 qdisc pfifo_fast 0: dev eth1 root refcnt 2 bands 3 priomap  1 2 2 2 1 2 
 0 0 1 1 1 1 1 1 1 1
  Sent 36336 bytes 860 pkt (dropped 0, overlimits 0 requeues 0)
  backlog 0b 0p requeues 0
 qdisc ingress ffff: dev eth1 parent ffff:fff1 ----------------
  Sent 7221978715996 bytes 200334775 pkt (dropped 0, overlimits 0 
 requeues 0)
  backlog 0b 0p requeues 0
 qdisc htb 1: dev eth2 root refcnt 2 r2q 10 default 0 
 direct_packets_stat 198674650 ver 3.17
  Sent 7405072421886 bytes 198674650 pkt (dropped 0, overlimits 0 
 requeues 1976)
  backlog 0b 0p requeues 1976
 qdisc pfifo_fast 0: dev eth3 root refcnt 2 bands 3 priomap  1 2 2 2 1 2 
 0 0 1 1 1 1 1 1 1 1
  Sent 7405072421886 bytes 198674650 pkt (dropped 0, overlimits 0 
 requeues 2779)
  backlog 0b 0p requeues 2779
 qdisc pfifo_fast 0: dev eth4 root refcnt 2 bands 3 priomap  1 2 2 2 1 2 
 0 0 1 1 1 1 1 1 1 1
  Sent 7405072421886 bytes 198674650 pkt (dropped 0, overlimits 0 
 requeues 1958)
  backlog 0b 0p requeues 1958
 qdisc pfifo_fast 0: dev eth5 root refcnt 2 bands 3 priomap  1 2 2 2 1 2 
 0 0 1 1 1 1 1 1 1 1
  Sent 7405072421886 bytes 198674650 pkt (dropped 0, overlimits 0 
 requeues 3232)
  backlog 0b 0p requeues 3232
 ---


 also, each packet arriving at the filter is mirred
 ---
 filter protocol ip pref 10 u32
 filter protocol ip pref 10 u32 fh 800: ht divisor 1
 filter protocol ip pref 10 u32 fh 800::800 order 2048 key ht 800 bkt 0 
 flowid 1:1  (rule hit 422685 success 422685)
   match 00000000/00000000 at 12 (success 422685 )
         action order 1: mirred (Egress Mirror to device eth2) pipe
         index 9 ref 1 bind 1 installed 9 sec
         Action statistics:
         Sent 212219392 bytes 422685 pkt (dropped 0, overlimits 0 
 requeues 0)
         backlog 0b 0p requeues 0

         action order 2: mirred (Egress Mirror to device eth3) pipe
         index 10 ref 1 bind 1 installed 9 sec
         Action statistics:
         Sent 212219392 bytes 422685 pkt (dropped 0, overlimits 0 
 requeues 0)
         backlog 0b 0p requeues 0

         action order 3: mirred (Egress Mirror to device eth4) pipe
         index 11 ref 1 bind 1 installed 9 sec
         Action statistics:
         Sent 212219392 bytes 422685 pkt (dropped 0, overlimits 0 
 requeues 0)
         backlog 0b 0p requeues 0

         action order 4: mirred (Egress Mirror to device eth5) pipe
         index 12 ref 1 bind 1 installed 9 sec
         Action statistics:
         Sent 212219392 bytes 422685 pkt (dropped 0, overlimits 0 
 requeues 0)
         backlog 0b 0p requeues 0
 ---


 traffic on the interface is between 150-200Mbps
 ---
 ifstat -tb -i eth1,eth2,eth3,eth4,eth5
   Time           eth1                eth2                eth3           
  eth4                eth5
 HH:MM:SS   Kbps in  Kbps out   Kbps in  Kbps out   Kbps in  Kbps out   
 Kbps in  Kbps out   Kbps in  Kbps out
 12:32:13  188022.1      0.00      0.47  188016.0      0.00  188039.9    
 0.00  188016.0      0.00  188039.9
 12:32:14  188743.2      0.00      0.00  188736.6      0.00  188736.6    
 0.00  188736.6      0.00  188736.6
 12:32:15  195705.1      0.00      0.47  195700.9      0.00  195682.9    
 0.00  195682.9      0.00  195700.9
 12:32:16  183506.6      0.00      0.00  183516.1      0.00  183522.2    
 0.00  183522.2      0.00  183504.3
 ---

 Am I doing something wrong, or what is a purpose of packet loss.
 My plan is to mirror 800-900Mbps to 4-8 network devices.

 Thanks


^ permalink raw reply

* Re: [GIT] Networking
From: Ben Hutchings @ 2010-10-31  9:19 UTC (permalink / raw)
  To: David Miller; +Cc: torvalds, akpm, netdev, linux-kernel
In-Reply-To: <20101030.183257.70183832.davem@davemloft.net>

[-- Attachment #1: Type: text/plain, Size: 706 bytes --]

On Sat, 2010-10-30 at 18:32 -0700, David Miller wrote:
> Last pull request before 2.6.37-rc1, I really wanted to get your
> sendto/recvfrom patch in here as well as the RDS fixes.
> 
> I did a bunch of tests with the various I/O calls using different
> lengths, like 10, (2^31 - 1), 2^31, 2^32, and larger on 64-bit and it
> all seems to be doing the right thing at least with TCP and UDP.
[...]
> 7) RDS fixes from you and Andy Grover.
[...]

Aren't the generic length limiting changes (8acfe46 and 253eacc) also
supposed to cover the overflow issues with TIPC?  Or are those still
unfixed?

Ben.

-- 
Ben Hutchings
Once a job is fouled up, anything done to improve it makes it worse.

[-- Attachment #2: This is a digitally signed message part --]
[-- Type: application/pgp-signature, Size: 828 bytes --]

^ permalink raw reply

* [PATCH] text ematch: check for NULL pointer before destroying textsearch config
From: Thomas Graf @ 2010-10-31  8:06 UTC (permalink / raw)
  To: davem; +Cc: netdev

While validating the configuration em_ops is already set, thus the
individual destroy functions are called, but the ematch data has
not been allocated and associated with the ematch yet.

Signed-off-by: Thomas Graf <tgraf@infradead.org>

Index: net-2.6/net/sched/em_text.c
===================================================================
--- net-2.6.orig/net/sched/em_text.c
+++ net-2.6/net/sched/em_text.c
@@ -103,7 +103,8 @@ retry:
 
 static void em_text_destroy(struct tcf_proto *tp, struct tcf_ematch *m)
 {
-	textsearch_destroy(EM_TEXT_PRIV(m)->config);
+	if (EM_TEXT_PRIV(m) && EM_TEXT_PRIV(m)->config)
+		textsearch_destroy(EM_TEXT_PRIV(m)->config);
 }
 
 static int em_text_dump(struct sk_buff *skb, struct tcf_ematch *m)

^ permalink raw reply

* Re: [PATCH 37/39] net/mac80211: Update WARN uses
From: Johannes Berg @ 2010-10-31  7:33 UTC (permalink / raw)
  To: Joe Perches
  Cc: Jiri Kosina, John W. Linville, David S. Miller, linux-wireless,
	netdev, linux-kernel
In-Reply-To: <de75963e04701e309b86dfee54c36e11873048c2.1288471898.git.joe@perches.com>

On Sat, 2010-10-30 at 14:08 -0700, Joe Perches wrote:
> Coalesce long formats.
> Add missing newlines.

> -			WARN(1, "frame for unexpected interface type");
> +			WARN(1, "frame for unexpected interface type\n");

But I thought WARN() added a newline...

johannes


^ permalink raw reply

* Re: [PATCH 0/4] Ethtool: cleanup strategy
From: Michał Mirosław @ 2010-10-31  4:30 UTC (permalink / raw)
  To: David Miller; +Cc: netdev
In-Reply-To: <20101030.211820.229761955.davem@davemloft.net>

On Sat, Oct 30, 2010 at 09:18:20PM -0700, David Miller wrote:
> Can you do me a huge favor?
> 
> In the future make the dates more sensible in your patch postings.
> 
> With how you did this, your patches are scattered all over the place
> in patchwork because it orders things by date, have a look:
> 
> http://patchwork.ozlabs.org/project/netdev/list/

Thanks for the hint.  I used git format-patch and it creates Date
headers based on git commit time.  I'll probably just filter them
or git rebase before sending patches from now on.

Best Regards,
Michał Mirosław

^ permalink raw reply

* Re: [PATCH 0/4] Ethtool: cleanup strategy
From: David Miller @ 2010-10-31  4:18 UTC (permalink / raw)
  To: mirq-linux
  Cc: linux-net-drivers, ddutt, e1000-devel, netdev, gregkh, rmody,
	linux-driver, steve.glendinning, kristoffer
In-Reply-To: <cover.1288496404.git.mirq-linux@rere.qmqm.pl>


Can you do me a huge favor?

In the future make the dates more sensible in your patch postings.

With how you did this, your patches are scattered all over the place
in patchwork because it orders things by date, have a look:

http://patchwork.ozlabs.org/project/netdev/list/

Thanks.

------------------------------------------------------------------------------
Nokia and AT&T present the 2010 Calling All Innovators-North America contest
Create new apps & games for the Nokia N8 for consumers in  U.S. and Canada
$10 million total in prizes - $4M cash, 500 devices, nearly $6M in marketing
Develop with Nokia Qt SDK, Web Runtime, or Java and Publish to Ovi Store 
http://p.sf.net/sfu/nokia-dev2dev
_______________________________________________
E1000-devel mailing list
E1000-devel@lists.sourceforge.net
https://lists.sourceforge.net/lists/listinfo/e1000-devel
To learn more about Intel&#174; Ethernet, visit http://communities.intel.com/community/wired

^ permalink raw reply

* Re: [ANNOUNCE] Host Fabric Interface (HFI) device driver available on sourceforge
From: David Miller @ 2010-10-31  4:08 UTC (permalink / raw)
  To: dykmanj; +Cc: netdev
In-Reply-To: <4CCCDE23.1090202@linux.vnet.ibm.com>

From: Jim Dykman <dykmanj@linux.vnet.ibm.com>
Date: Sat, 30 Oct 2010 23:10:27 -0400

> The HFI network interface is the internal cluster fabric of IBM's
> PERCS supercomputer. The device driver patch for 2.6.36, hfi-utils,
> and an introduction to the hardware are available on the sourceforge
> page (http://sourceforge.net/projects/hfidevicedriver). The hardware
> design is under US export control, so we cannot release hardware
> specs.

Nobody is going to look at your code, let alone help review it
for inclusion, if you just say "go look at this stuff on this
sourceforge web site."

You have to post the kernel patches here, one by one.

^ permalink raw reply

* [PATCH 3/4] Ethtool: convert get_tso/set_tso calls to hw_features flags
From: Michał Mirosław @ 2010-10-30  8:44 UTC (permalink / raw)
  To: netdev
  Cc: e1000-devel, Steve Glendinning, Greg Kroah-Hartman, Rasesh Mody,
	Debashis Dutt, Kristoffer Glembo, linux-driver, linux-net-drivers
In-Reply-To: <cover.1288496404.git.mirq-linux@rere.qmqm.pl>


Signed-off-by: Michał Mirosław <mirq-linux@rere.qmqm.pl>
---
 drivers/infiniband/hw/nes/nes_nic.c          |    4 +-
 drivers/infiniband/ulp/ipoib/ipoib_ethtool.c |   10 ++--
 drivers/net/8139cp.c                         |    3 +-
 drivers/net/atl1e/atl1e_ethtool.c            |    3 +-
 drivers/net/atlx/atl1.c                      |    2 +-
 drivers/net/atlx/atl2.c                      |    3 -
 drivers/net/benet/be_ethtool.c               |    2 -
 drivers/net/benet/be_main.c                  |    2 +-
 drivers/net/bna/bnad_ethtool.c               |   20 +---------
 drivers/net/bnx2.c                           |   18 +--------
 drivers/net/bnx2x/bnx2x_ethtool.c            |   16 +-------
 drivers/net/bonding/bond_main.c              |    1 -
 drivers/net/chelsio/cxgb2.c                  |   12 +-----
 drivers/net/cxgb3/cxgb3_main.c               |    3 +-
 drivers/net/cxgb4/cxgb4_main.c               |   12 +-----
 drivers/net/cxgb4vf/cxgb4vf_main.c           |   14 +------
 drivers/net/e1000/e1000.h                    |    1 -
 drivers/net/e1000/e1000_ethtool.c            |   28 +++-----------
 drivers/net/e1000e/ethtool.c                 |   12 +-----
 drivers/net/ehea/ehea_ethtool.c              |    2 +-
 drivers/net/enic/enic_main.c                 |   11 +----
 drivers/net/forcedeth.c                      |   13 +------
 drivers/net/igb/igb_ethtool.c                |   20 +---------
 drivers/net/igbvf/ethtool.c                  |   20 +---------
 drivers/net/ixgb/ixgb_ethtool.c              |   13 +------
 drivers/net/ixgbe/ixgbe_ethtool.c            |   15 +-------
 drivers/net/ixgbevf/ethtool.c                |   17 +--------
 drivers/net/jme.c                            |    9 ++--
 drivers/net/loopback.c                       |    2 +-
 drivers/net/mlx4/en_ethtool.c                |   19 ++-------
 drivers/net/mlx4/en_netdev.c                 |    1 +
 drivers/net/myri10ge/myri10ge.c              |   14 +------
 drivers/net/netxen/netxen_nic_ethtool.c      |   26 -------------
 drivers/net/netxen/netxen_nic_main.c         |    4 +-
 drivers/net/qlcnic/qlcnic_ethtool.c          |   20 ----------
 drivers/net/qlcnic/qlcnic_main.c             |    1 +
 drivers/net/qlge/qlge_ethtool.c              |   15 -------
 drivers/net/qlge/qlge_main.c                 |    1 +
 drivers/net/r8169.c                          |    3 +-
 drivers/net/s2io.c                           |   18 +--------
 drivers/net/sfc/efx.c                        |    4 +-
 drivers/net/sfc/ethtool.c                    |   20 ----------
 drivers/net/sky2.c                           |    6 +-
 drivers/net/stmmac/stmmac_ethtool.c          |    4 +-
 drivers/net/tehuti.c                         |    1 -
 drivers/net/tg3.c                            |   38 ++++++++++---------
 drivers/net/typhoon.c                        |    3 +-
 drivers/net/usb/smsc75xx.c                   |   17 +-------
 drivers/net/virtio_net.c                     |    3 +-
 drivers/net/vmxnet3/vmxnet3_ethtool.c        |    4 +-
 drivers/net/vxge/vxge-ethtool.c              |   13 +------
 drivers/net/xen-netfront.c                   |    9 ++--
 drivers/s390/net/qeth_l3_main.c              |    7 +--
 include/linux/ethtool.h                      |    8 +---
 include/linux/netdevice.h                    |    2 +
 net/8021q/vlan_dev.c                         |    5 +-
 net/bridge/br_device.c                       |    7 +--
 net/core/ethtool.c                           |   52 +++++++++++++-------------
 58 files changed, 132 insertions(+), 481 deletions(-)

diff --git a/drivers/infiniband/hw/nes/nes_nic.c b/drivers/infiniband/hw/nes/nes_nic.c
index 6056913..04af96a 100644
--- a/drivers/infiniband/hw/nes/nes_nic.c
+++ b/drivers/infiniband/hw/nes/nes_nic.c
@@ -1595,8 +1595,6 @@ static const struct ethtool_ops nes_ethtool_ops = {
 	.set_pauseparam = nes_netdev_set_pauseparam,
 	.set_tx_csum = ethtool_op_set_tx_csum,
 	.set_rx_csum = nes_netdev_set_rx_csum,
-	.get_tso = ethtool_op_get_tso,
-	.set_tso = ethtool_op_set_tso,
 	.get_flags = ethtool_op_get_flags,
 	.set_flags = nes_netdev_set_flags,
 };
@@ -1670,7 +1668,7 @@ struct net_device *nes_netdev_init(struct nes_device *nesdev,
 	netdev->type = ARPHRD_ETHER;
 	netdev->features = NETIF_F_HIGHDMA;
 	netdev->netdev_ops = &nes_netdev_ops;
-	netdev->hw_features |= NETIF_F_SG;
+	netdev->hw_features |= NETIF_F_SG|NETIF_F_TSO;
 	netdev->ethtool_ops = &nes_ethtool_ops;
 	netif_napi_add(netdev, &nesvnic->napi, nes_netdev_poll, 128);
 	nes_debug(NES_DBG_INIT, "Enabling VLAN Insert/Delete.\n");
diff --git a/drivers/infiniband/ulp/ipoib/ipoib_ethtool.c b/drivers/infiniband/ulp/ipoib/ipoib_ethtool.c
index 1a1657c..6fb3cf4 100644
--- a/drivers/infiniband/ulp/ipoib/ipoib_ethtool.c
+++ b/drivers/infiniband/ulp/ipoib/ipoib_ethtool.c
@@ -58,13 +58,12 @@ static int ipoib_set_tso(struct net_device *dev, u32 data)
 		    (dev->features & NETIF_F_SG) &&
 		    (priv->hca_caps & IB_DEVICE_UD_TSO)) {
 			dev->features |= NETIF_F_TSO;
+			return 1;
 		} else {
 			ipoib_warn(priv, "can't set TSO on\n");
-			return -EOPNOTSUPP;
+			return -EINVAL;
 		}
-	} else
-		dev->features &= ~NETIF_F_TSO;
-
+	}
 	return 0;
 }
 
@@ -155,7 +154,7 @@ static int ipoib_set_flags(struct net_device *dev, u32 flags)
 static const struct ethtool_ops ipoib_ethtool_ops = {
 	.get_drvinfo		= ipoib_get_drvinfo,
 	.get_rx_csum		= ipoib_get_rx_csum,
-	.set_tso		= ipoib_set_tso,
+	.hw_set_tso		= ipoib_set_tso,
 	.get_coalesce		= ipoib_get_coalesce,
 	.set_coalesce		= ipoib_set_coalesce,
 	.get_flags		= ethtool_op_get_flags,
@@ -167,5 +166,6 @@ static const struct ethtool_ops ipoib_ethtool_ops = {
 
 void ipoib_set_ethtool_ops(struct net_device *dev)
 {
+	dev->hw_features |= NETIF_F_TSO;
 	SET_ETHTOOL_OPS(dev, &ipoib_ethtool_ops);
 }
diff --git a/drivers/net/8139cp.c b/drivers/net/8139cp.c
index e8cc0be..0fd2867 100644
--- a/drivers/net/8139cp.c
+++ b/drivers/net/8139cp.c
@@ -1559,7 +1559,6 @@ static const struct ethtool_ops cp_ethtool_ops = {
 	.get_rx_csum		= cp_get_rx_csum,
 	.set_rx_csum		= cp_set_rx_csum,
 	.set_tx_csum		= ethtool_op_set_tx_csum, /* local! */
-	.set_tso		= ethtool_op_set_tso,
 	.get_regs		= cp_get_regs,
 	.get_wol		= cp_get_wol,
 	.set_wol		= cp_set_wol,
@@ -1957,7 +1956,7 @@ static int cp_init_one (struct pci_dev *pdev, const struct pci_device_id *ent)
 
 	dev->netdev_ops = &cp_netdev_ops;
 	netif_napi_add(dev, &cp->napi, cp_rx_poll, 16);
-	dev->hw_features |= NETIF_F_SG;
+	dev->hw_features |= NETIF_F_SG|NETIF_F_TSO;
 	dev->ethtool_ops = &cp_ethtool_ops;
 	dev->watchdog_timeo = TX_TIMEOUT;
 
diff --git a/drivers/net/atl1e/atl1e_ethtool.c b/drivers/net/atl1e/atl1e_ethtool.c
index 5beebd5..1485797 100644
--- a/drivers/net/atl1e/atl1e_ethtool.c
+++ b/drivers/net/atl1e/atl1e_ethtool.c
@@ -383,11 +383,10 @@ static const struct ethtool_ops atl1e_ethtool_ops = {
 	.get_eeprom             = atl1e_get_eeprom,
 	.set_eeprom             = atl1e_set_eeprom,
 	.set_tx_csum            = ethtool_op_set_tx_hw_csum,
-	.set_tso                = ethtool_op_set_tso,
 };
 
 void atl1e_set_ethtool_ops(struct net_device *netdev)
 {
-	netdev->hw_features |= NETIF_F_SG;
+	netdev->hw_features |= NETIF_F_SG|NETIF_F_TSO;
 	SET_ETHTOOL_OPS(netdev, &atl1e_ethtool_ops);
 }
diff --git a/drivers/net/atlx/atl1.c b/drivers/net/atlx/atl1.c
index 9e27bd6..814a06c 100644
--- a/drivers/net/atlx/atl1.c
+++ b/drivers/net/atlx/atl1.c
@@ -2992,6 +2992,7 @@ static int __devinit atl1_probe(struct pci_dev *pdev,
 	netdev->watchdog_timeo = 5 * HZ;
 
 	netdev->hw_features |= NETIF_F_SG;
+	netdev->hw_features |= NETIF_F_TSO;
 	netdev->ethtool_ops = &atl1_ethtool_ops;
 	adapter->bd_number = cards_found;
 
@@ -3682,5 +3683,4 @@ static const struct ethtool_ops atl1_ethtool_ops = {
 	.nway_reset		= atl1_nway_reset,
 	.get_ethtool_stats	= atl1_get_ethtool_stats,
 	.get_sset_count		= atl1_get_sset_count,
-	.set_tso		= ethtool_op_set_tso,
 };
diff --git a/drivers/net/atlx/atl2.c b/drivers/net/atlx/atl2.c
index 1850a00..0d9b688 100644
--- a/drivers/net/atlx/atl2.c
+++ b/drivers/net/atlx/atl2.c
@@ -2107,9 +2107,6 @@ static const struct ethtool_ops atl2_ethtool_ops = {
 	.get_eeprom		= atl2_get_eeprom,
 	.set_eeprom		= atl2_set_eeprom,
 	.get_tx_csum		= atl2_get_tx_csum,
-#ifdef NETIF_F_TSO
-	.get_tso		= ethtool_op_get_tso,
-#endif
 };
 
 static void atl2_set_ethtool_ops(struct net_device *netdev)
diff --git a/drivers/net/benet/be_ethtool.c b/drivers/net/benet/be_ethtool.c
index 169429c..8c1eaee 100644
--- a/drivers/net/benet/be_ethtool.c
+++ b/drivers/net/benet/be_ethtool.c
@@ -698,8 +698,6 @@ const struct ethtool_ops be_ethtool_ops = {
 	.set_rx_csum = be_set_rx_csum,
 	.get_tx_csum = ethtool_op_get_tx_csum,
 	.set_tx_csum = ethtool_op_set_tx_hw_csum,
-	.get_tso = ethtool_op_get_tso,
-	.set_tso = ethtool_op_set_tso,
 	.get_strings = be_get_stat_strings,
 	.phys_id = be_phys_id,
 	.get_sset_count = be_get_sset_count,
diff --git a/drivers/net/benet/be_main.c b/drivers/net/benet/be_main.c
index dfa231d..b8a164f 100644
--- a/drivers/net/benet/be_main.c
+++ b/drivers/net/benet/be_main.c
@@ -2554,7 +2554,7 @@ static void be_netdev_init(struct net_device *netdev)
 
 	BE_SET_NETDEV_OPS(netdev, &be_netdev_ops);
 
-	netdev->hw_features |= NETIF_F_SG;
+	netdev->hw_features |= NETIF_F_SG|NETIF_F_TSO;
 	SET_ETHTOOL_OPS(netdev, &be_ethtool_ops);
 
 	for_all_rx_queues(adapter, rxo, i)
diff --git a/drivers/net/bna/bnad_ethtool.c b/drivers/net/bna/bnad_ethtool.c
index 207f57b..f8bdebf 100644
--- a/drivers/net/bna/bnad_ethtool.c
+++ b/drivers/net/bna/bnad_ethtool.c
@@ -848,23 +848,6 @@ bnad_set_tx_csum(struct net_device *netdev, u32 tx_csum)
 	return 0;
 }
 
-static int
-bnad_set_tso(struct net_device *netdev, u32 tso)
-{
-	struct bnad *bnad = netdev_priv(netdev);
-
-	mutex_lock(&bnad->conf_mutex);
-	if (tso) {
-		netdev->features |= NETIF_F_TSO;
-		netdev->features |= NETIF_F_TSO6;
-	} else {
-		netdev->features &= ~NETIF_F_TSO;
-		netdev->features &= ~NETIF_F_TSO6;
-	}
-	mutex_unlock(&bnad->conf_mutex);
-	return 0;
-}
-
 static void
 bnad_get_strings(struct net_device *netdev, u32 stringset, u8 * string)
 {
@@ -1261,8 +1244,6 @@ static struct ethtool_ops bnad_ethtool_ops = {
 	.set_rx_csum = bnad_set_rx_csum,
 	.get_tx_csum = ethtool_op_get_tx_csum,
 	.set_tx_csum = bnad_set_tx_csum,
-	.get_tso = ethtool_op_get_tso,
-	.set_tso = bnad_set_tso,
 	.get_strings = bnad_get_strings,
 	.get_ethtool_stats = bnad_get_ethtool_stats,
 	.get_sset_count = bnad_get_sset_count
@@ -1272,5 +1253,6 @@ void
 bnad_set_ethtool_ops(struct net_device *netdev)
 {
 	netdev->hw_features |= NETIF_F_SG;
+	netdev->hw_features |= NETIF_F_TSO|NETIF_F_TSO6;
 	SET_ETHTOOL_OPS(netdev, &bnad_ethtool_ops);
 }
diff --git a/drivers/net/bnx2.c b/drivers/net/bnx2.c
index 50bdafb..8a63a8b 100644
--- a/drivers/net/bnx2.c
+++ b/drivers/net/bnx2.c
@@ -7181,21 +7181,6 @@ bnx2_set_rx_csum(struct net_device *dev, u32 data)
 	return 0;
 }
 
-static int
-bnx2_set_tso(struct net_device *dev, u32 data)
-{
-	struct bnx2 *bp = netdev_priv(dev);
-
-	if (data) {
-		dev->features |= NETIF_F_TSO | NETIF_F_TSO_ECN;
-		if (CHIP_NUM(bp) == CHIP_NUM_5709)
-			dev->features |= NETIF_F_TSO6;
-	} else
-		dev->features &= ~(NETIF_F_TSO | NETIF_F_TSO6 |
-				   NETIF_F_TSO_ECN);
-	return 0;
-}
-
 static struct {
 	char string[ETH_GSTRING_LEN];
 } bnx2_stats_str_arr[] = {
@@ -7569,7 +7554,6 @@ static const struct ethtool_ops bnx2_ethtool_ops = {
 	.get_rx_csum		= bnx2_get_rx_csum,
 	.set_rx_csum		= bnx2_set_rx_csum,
 	.set_tx_csum		= bnx2_set_tx_csum,
-	.set_tso		= bnx2_set_tso,
 	.self_test		= bnx2_self_test,
 	.get_strings		= bnx2_get_strings,
 	.phys_id		= bnx2_phys_id,
@@ -8320,6 +8304,7 @@ bnx2_init_one(struct pci_dev *pdev, const struct pci_device_id *ent)
 	dev->netdev_ops = &bnx2_netdev_ops;
 	dev->watchdog_timeo = TX_TIMEOUT;
 	dev->hw_features |= NETIF_F_SG;
+	dev->hw_features |= NETIF_F_TSO|NETIF_F_TSO_ECN;
 	dev->ethtool_ops = &bnx2_ethtool_ops;
 
 	bp = netdev_priv(dev);
@@ -8344,6 +8329,7 @@ bnx2_init_one(struct pci_dev *pdev, const struct pci_device_id *ent)
 	dev->features |= NETIF_F_TSO | NETIF_F_TSO_ECN;
 	vlan_features_add(dev, NETIF_F_TSO | NETIF_F_TSO_ECN);
 	if (CHIP_NUM(bp) == CHIP_NUM_5709) {
+		dev->hw_features |= NETIF_F_TSO6;
 		dev->features |= NETIF_F_TSO6;
 		vlan_features_add(dev, NETIF_F_TSO6);
 	}
diff --git a/drivers/net/bnx2x/bnx2x_ethtool.c b/drivers/net/bnx2x/bnx2x_ethtool.c
index 54955fb..3d08714 100644
--- a/drivers/net/bnx2x/bnx2x_ethtool.c
+++ b/drivers/net/bnx2x/bnx2x_ethtool.c
@@ -1183,19 +1183,6 @@ static int bnx2x_set_rx_csum(struct net_device *dev, u32 data)
 	return rc;
 }
 
-static int bnx2x_set_tso(struct net_device *dev, u32 data)
-{
-	if (data) {
-		dev->features |= (NETIF_F_TSO | NETIF_F_TSO_ECN);
-		dev->features |= NETIF_F_TSO6;
-	} else {
-		dev->features &= ~(NETIF_F_TSO | NETIF_F_TSO_ECN);
-		dev->features &= ~NETIF_F_TSO6;
-	}
-
-	return 0;
-}
-
 static const struct {
 	char string[ETH_GSTRING_LEN];
 } bnx2x_tests_str_arr[BNX2X_NUM_TESTS] = {
@@ -2082,8 +2069,6 @@ static const struct ethtool_ops bnx2x_ethtool_ops = {
 	.set_tx_csum		= ethtool_op_set_tx_hw_csum,
 	.set_flags		= bnx2x_set_flags,
 	.get_flags		= ethtool_op_get_flags,
-	.get_tso		= ethtool_op_get_tso,
-	.set_tso		= bnx2x_set_tso,
 	.self_test		= bnx2x_self_test,
 	.get_sset_count		= bnx2x_get_sset_count,
 	.get_strings		= bnx2x_get_strings,
@@ -2094,5 +2079,6 @@ static const struct ethtool_ops bnx2x_ethtool_ops = {
 void bnx2x_set_ethtool_ops(struct net_device *netdev)
 {
 	netdev->hw_features |= NETIF_F_SG;
+	netdev->hw_features |= NETIF_F_TSO|NETIF_F_TSO_ECN|NETIF_F_TSO6;
 	SET_ETHTOOL_OPS(netdev, &bnx2x_ethtool_ops);
 }
diff --git a/drivers/net/bonding/bond_main.c b/drivers/net/bonding/bond_main.c
index 577b462..4e030c5 100644
--- a/drivers/net/bonding/bond_main.c
+++ b/drivers/net/bonding/bond_main.c
@@ -4651,7 +4651,6 @@ static const struct ethtool_ops bond_ethtool_ops = {
 	.get_drvinfo		= bond_ethtool_get_drvinfo,
 	.get_link		= ethtool_op_get_link,
 	.get_tx_csum		= ethtool_op_get_tx_csum,
-	.get_tso		= ethtool_op_get_tso,
 	.get_ufo		= ethtool_op_get_ufo,
 	.get_flags		= ethtool_op_get_flags,
 };
diff --git a/drivers/net/chelsio/cxgb2.c b/drivers/net/chelsio/cxgb2.c
index 7f63ede..712c413 100644
--- a/drivers/net/chelsio/cxgb2.c
+++ b/drivers/net/chelsio/cxgb2.c
@@ -723,15 +723,6 @@ static int set_rx_csum(struct net_device *dev, u32 data)
 	return 0;
 }
 
-static int set_tso(struct net_device *dev, u32 value)
-{
-	struct adapter *adapter = dev->ml_priv;
-
-	if (!(adapter->flags & TSO_CAPABLE))
-		return value ? -EOPNOTSUPP : 0;
-	return ethtool_op_set_tso(dev, value);
-}
-
 static void get_sge_param(struct net_device *dev, struct ethtool_ringparam *e)
 {
 	struct adapter *adapter = dev->ml_priv;
@@ -840,7 +831,6 @@ static const struct ethtool_ops t1_ethtool_ops = {
 	.get_ethtool_stats = get_stats,
 	.get_regs_len      = get_regs_len,
 	.get_regs          = get_regs,
-	.set_tso           = set_tso,
 };
 
 static int t1_ioctl(struct net_device *dev, struct ifreq *req, int cmd)
@@ -1131,6 +1121,8 @@ static int __devinit init_one(struct pci_dev *pdev,
 		netif_napi_add(netdev, &adapter->napi, t1_poll, 64);
 
 		netdev->hw_features |= NETIF_F_SG;
+		if (adapter->flags & TSO_CAPABLE)
+			netdev->hw_features |= NETIF_F_TSO;
 		SET_ETHTOOL_OPS(netdev, &t1_ethtool_ops);
 	}
 
diff --git a/drivers/net/cxgb3/cxgb3_main.c b/drivers/net/cxgb3/cxgb3_main.c
index 2bc7529..1d45f7d 100644
--- a/drivers/net/cxgb3/cxgb3_main.c
+++ b/drivers/net/cxgb3/cxgb3_main.c
@@ -2106,7 +2106,6 @@ static const struct ethtool_ops cxgb_ethtool_ops = {
 	.get_regs_len = get_regs_len,
 	.get_regs = get_regs,
 	.get_wol = get_wol,
-	.set_tso = ethtool_op_set_tso,
 };
 
 static int in_range(int val, int lo, int hi)
@@ -3310,7 +3309,7 @@ static int __devinit init_one(struct pci_dev *pdev,
 
 		netdev->features |= NETIF_F_HW_VLAN_TX | NETIF_F_HW_VLAN_RX;
 		netdev->netdev_ops = &cxgb_netdev_ops;
-		netdev->hw_features |= NETIF_F_SG;
+		netdev->hw_features |= NETIF_F_SG|NETIF_F_TSO;
 		SET_ETHTOOL_OPS(netdev, &cxgb_ethtool_ops);
 	}
 
diff --git a/drivers/net/cxgb4/cxgb4_main.c b/drivers/net/cxgb4/cxgb4_main.c
index ac843a3..700bb37 100644
--- a/drivers/net/cxgb4/cxgb4_main.c
+++ b/drivers/net/cxgb4/cxgb4_main.c
@@ -1870,15 +1870,6 @@ static int set_wol(struct net_device *dev, struct ethtool_wolinfo *wol)
 
 #define TSO_FLAGS (NETIF_F_TSO | NETIF_F_TSO6 | NETIF_F_TSO_ECN)
 
-static int set_tso(struct net_device *dev, u32 value)
-{
-	if (value)
-		dev->features |= TSO_FLAGS;
-	else
-		dev->features &= ~TSO_FLAGS;
-	return 0;
-}
-
 static int set_flags(struct net_device *dev, u32 flags)
 {
 	int err;
@@ -2021,7 +2012,6 @@ static struct ethtool_ops cxgb_ethtool_ops = {
 	.get_regs          = get_regs,
 	.get_wol           = get_wol,
 	.set_wol           = set_wol,
-	.set_tso           = set_tso,
 	.set_flags         = set_flags,
 	.get_rxnfc         = get_rxnfc,
 	.get_rxfh_indir    = get_rss_table,
@@ -3673,7 +3663,7 @@ static int __devinit init_one(struct pci_dev *pdev,
 		netdev->vlan_features = netdev->features & VLAN_FEAT;
 
 		netdev->netdev_ops = &cxgb4_netdev_ops;
-		netdev->hw_features |= NETIF_F_SG;
+		netdev->hw_features |= NETIF_F_SG | TSO_FLAGS;
 		SET_ETHTOOL_OPS(netdev, &cxgb_ethtool_ops);
 	}
 
diff --git a/drivers/net/cxgb4vf/cxgb4vf_main.c b/drivers/net/cxgb4vf/cxgb4vf_main.c
index ddaba63..61cc28c 100644
--- a/drivers/net/cxgb4vf/cxgb4vf_main.c
+++ b/drivers/net/cxgb4vf/cxgb4vf_main.c
@@ -1539,18 +1539,6 @@ static void cxgb4vf_get_wol(struct net_device *dev,
 	memset(&wol->sopass, 0, sizeof(wol->sopass));
 }
 
-/*
- * Set TCP Segmentation Offloading feature capabilities.
- */
-static int cxgb4vf_set_tso(struct net_device *dev, u32 tso)
-{
-	if (tso)
-		dev->features |= NETIF_F_TSO | NETIF_F_TSO6;
-	else
-		dev->features &= ~(NETIF_F_TSO | NETIF_F_TSO6);
-	return 0;
-}
-
 static struct ethtool_ops cxgb4vf_ethtool_ops = {
 	.get_settings		= cxgb4vf_get_settings,
 	.get_drvinfo		= cxgb4vf_get_drvinfo,
@@ -1572,7 +1560,6 @@ static struct ethtool_ops cxgb4vf_ethtool_ops = {
 	.get_regs_len		= cxgb4vf_get_regs_len,
 	.get_regs		= cxgb4vf_get_regs,
 	.get_wol		= cxgb4vf_get_wol,
-	.set_tso		= cxgb4vf_set_tso,
 };
 
 /*
@@ -2630,6 +2617,7 @@ static int __devinit cxgb4vf_pci_probe(struct pci_dev *pdev,
 #endif
 #endif
 		netdev->hw_features |= NETIF_F_SG;
+		netdev->hw_features |= NETIF_F_TSO|NETIF_F_TSO6;
 		SET_ETHTOOL_OPS(netdev, &cxgb4vf_ethtool_ops);
 
 		/*
diff --git a/drivers/net/e1000/e1000.h b/drivers/net/e1000/e1000.h
index a881dd0..8f14520 100644
--- a/drivers/net/e1000/e1000.h
+++ b/drivers/net/e1000/e1000.h
@@ -299,7 +299,6 @@ struct e1000_adapter {
 	int msg_enable;
 
 	/* to not mess up cache alignment, always add to the bottom */
-	bool tso_force;
 	bool smart_power_down;	/* phy smart power down */
 	bool quad_port_a;
 	unsigned long flags;
diff --git a/drivers/net/e1000/e1000_ethtool.c b/drivers/net/e1000/e1000_ethtool.c
index 008632c..fcde1b2 100644
--- a/drivers/net/e1000/e1000_ethtool.c
+++ b/drivers/net/e1000/e1000_ethtool.c
@@ -330,27 +330,6 @@ static int e1000_set_tx_csum(struct net_device *netdev, u32 data)
 	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);
@@ -1925,7 +1904,6 @@ static const struct ethtool_ops e1000_ethtool_ops = {
 	.set_rx_csum            = e1000_set_rx_csum,
 	.get_tx_csum            = e1000_get_tx_csum,
 	.set_tx_csum            = e1000_set_tx_csum,
-	.set_tso                = e1000_set_tso,
 	.self_test              = e1000_diag_test,
 	.get_strings            = e1000_get_strings,
 	.phys_id                = e1000_phys_id,
@@ -1937,6 +1915,12 @@ static const struct ethtool_ops e1000_ethtool_ops = {
 
 void e1000_set_ethtool_ops(struct net_device *netdev)
 {
+	struct e1000_adapter *adapter = netdev_priv(netdev);
+
 	netdev->hw_features |= NETIF_F_SG;
+	if (!(adapter->hw.mac_type < e1000_82544) &&
+	    !(adapter->hw.mac_type == e1000_82547))
+		netdev->hw_features |= NETIF_F_TSO;
+
 	SET_ETHTOOL_OPS(netdev, &e1000_ethtool_ops);
 }
diff --git a/drivers/net/e1000e/ethtool.c b/drivers/net/e1000e/ethtool.c
index bb0bcfa..579ed4b 100644
--- a/drivers/net/e1000e/ethtool.c
+++ b/drivers/net/e1000e/ethtool.c
@@ -406,14 +406,6 @@ 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;
 }
@@ -2036,8 +2028,7 @@ static const struct ethtool_ops e1000_ethtool_ops = {
 	.set_rx_csum		= e1000_set_rx_csum,
 	.get_tx_csum		= e1000_get_tx_csum,
 	.set_tx_csum		= e1000_set_tx_csum,
-	.get_tso		= ethtool_op_get_tso,
-	.set_tso		= e1000_set_tso,
+	.hw_set_tso		= e1000_set_tso,
 	.self_test		= e1000_diag_test,
 	.get_strings		= e1000_get_strings,
 	.phys_id		= e1000_phys_id,
@@ -2051,5 +2042,6 @@ static const struct ethtool_ops e1000_ethtool_ops = {
 void e1000e_set_ethtool_ops(struct net_device *netdev)
 {
 	netdev->hw_features |= NETIF_F_SG;
+	netdev->hw_features |= NETIF_F_TSO|NETIF_F_TSO6;
 	SET_ETHTOOL_OPS(netdev, &e1000_ethtool_ops);
 }
diff --git a/drivers/net/ehea/ehea_ethtool.c b/drivers/net/ehea/ehea_ethtool.c
index 75b099c..fb5b9ba 100644
--- a/drivers/net/ehea/ehea_ethtool.c
+++ b/drivers/net/ehea/ehea_ethtool.c
@@ -267,7 +267,6 @@ const struct ethtool_ops ehea_ethtool_ops = {
 	.get_msglevel = ehea_get_msglevel,
 	.set_msglevel = ehea_set_msglevel,
 	.get_link = ethtool_op_get_link,
-	.set_tso = ethtool_op_set_tso,
 	.get_strings = ehea_get_strings,
 	.get_sset_count = ehea_get_sset_count,
 	.get_ethtool_stats = ehea_get_ethtool_stats,
@@ -278,5 +277,6 @@ const struct ethtool_ops ehea_ethtool_ops = {
 
 void ehea_set_ethtool_ops(struct net_device *netdev)
 {
+	netdev->hw_features |= NETIF_F_TSO;
 	SET_ETHTOOL_OPS(netdev, &ehea_ethtool_ops);
 }
diff --git a/drivers/net/enic/enic_main.c b/drivers/net/enic/enic_main.c
index b744fca..88e4a99 100644
--- a/drivers/net/enic/enic_main.c
+++ b/drivers/net/enic/enic_main.c
@@ -312,13 +312,6 @@ static int enic_set_tso(struct net_device *netdev, u32 data)
 	if (data && !ENIC_SETTING(enic, TSO))
 		return -EINVAL;
 
-	if (data)
-		netdev->features |=
-			NETIF_F_TSO | NETIF_F_TSO6 | NETIF_F_TSO_ECN;
-	else
-		netdev->features &=
-			~(NETIF_F_TSO | NETIF_F_TSO6 | NETIF_F_TSO_ECN);
-
 	return 0;
 }
 
@@ -413,8 +406,7 @@ static const struct ethtool_ops enic_ethtool_ops = {
 	.set_rx_csum = enic_set_rx_csum,
 	.get_tx_csum = ethtool_op_get_tx_csum,
 	.set_tx_csum = enic_set_tx_csum,
-	.get_tso = ethtool_op_get_tso,
-	.set_tso = enic_set_tso,
+	.hw_set_tso = enic_set_tso,
 	.get_coalesce = enic_get_coalesce,
 	.set_coalesce = enic_set_coalesce,
 	.get_flags = ethtool_op_get_flags,
@@ -2637,6 +2629,7 @@ static int __devinit enic_probe(struct pci_dev *pdev,
 
 	netdev->watchdog_timeo = 2 * HZ;
 	netdev->hw_features |= NETIF_F_SG;
+	netdev->hw_features |= NETIF_F_TSO|NETIF_F_TSO6|NETIF_F_TSO_ECN;
 	netdev->ethtool_ops = &enic_ethtool_ops;
 
 	netdev->features |= NETIF_F_HW_VLAN_TX | NETIF_F_HW_VLAN_RX;
diff --git a/drivers/net/forcedeth.c b/drivers/net/forcedeth.c
index fb8c7c9..8aabb6a 100644
--- a/drivers/net/forcedeth.c
+++ b/drivers/net/forcedeth.c
@@ -4396,16 +4396,6 @@ static int nv_nway_reset(struct net_device *dev)
 	return ret;
 }
 
-static int nv_set_tso(struct net_device *dev, u32 value)
-{
-	struct fe_priv *np = netdev_priv(dev);
-
-	if ((np->driver_data & DEV_HAS_CHECKSUM))
-		return ethtool_op_set_tso(dev, value);
-	else
-		return -EOPNOTSUPP;
-}
-
 static void nv_get_ringparam(struct net_device *dev, struct ethtool_ringparam* ring)
 {
 	struct fe_priv *np = netdev_priv(dev);
@@ -5029,7 +5019,6 @@ static const struct ethtool_ops ops = {
 	.get_regs_len = nv_get_regs_len,
 	.get_regs = nv_get_regs,
 	.nway_reset = nv_nway_reset,
-	.set_tso = nv_set_tso,
 	.get_ringparam = nv_get_ringparam,
 	.set_ringparam = nv_set_ringparam,
 	.get_pauseparam = nv_get_pauseparam,
@@ -5565,7 +5554,7 @@ static int __devinit nv_probe(struct pci_dev *pci_dev, const struct pci_device_i
 
 	netif_napi_add(dev, &np->napi, nv_napi_poll, RX_WORK_PER_LOOP);
 	if (np->driver_data & DEV_HAS_CHECKSUM)
-		dev->hw_features |= NETIF_F_SG;
+		dev->hw_features |= NETIF_F_SG|NETIF_F_TSO;
 	SET_ETHTOOL_OPS(dev, &ops);
 	dev->watchdog_timeo = NV_WATCHDOG_TIMEO;
 
diff --git a/drivers/net/igb/igb_ethtool.c b/drivers/net/igb/igb_ethtool.c
index 2909af5..de257e4 100644
--- a/drivers/net/igb/igb_ethtool.c
+++ b/drivers/net/igb/igb_ethtool.c
@@ -355,23 +355,6 @@ static int igb_set_tx_csum(struct net_device *netdev, u32 data)
 	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);
@@ -2193,8 +2176,6 @@ static const struct ethtool_ops igb_ethtool_ops = {
 	.set_rx_csum            = igb_set_rx_csum,
 	.get_tx_csum            = igb_get_tx_csum,
 	.set_tx_csum            = igb_set_tx_csum,
-	.get_tso                = ethtool_op_get_tso,
-	.set_tso                = igb_set_tso,
 	.self_test              = igb_diag_test,
 	.get_strings            = igb_get_strings,
 	.phys_id                = igb_phys_id,
@@ -2207,5 +2188,6 @@ static const struct ethtool_ops igb_ethtool_ops = {
 void igb_set_ethtool_ops(struct net_device *netdev)
 {
 	netdev->hw_features |= NETIF_F_SG;
+	netdev->hw_features |= NETIF_F_TSO|NETIF_F_TSO6;
 	SET_ETHTOOL_OPS(netdev, &igb_ethtool_ops);
 }
diff --git a/drivers/net/igbvf/ethtool.c b/drivers/net/igbvf/ethtool.c
index 9bf5ea0..56f77b6 100644
--- a/drivers/net/igbvf/ethtool.c
+++ b/drivers/net/igbvf/ethtool.c
@@ -165,23 +165,6 @@ static int igbvf_set_tx_csum(struct net_device *netdev, u32 data)
 	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);
@@ -527,8 +510,6 @@ static const struct ethtool_ops igbvf_ethtool_ops = {
 	.set_rx_csum            = igbvf_set_rx_csum,
 	.get_tx_csum		= igbvf_get_tx_csum,
 	.set_tx_csum		= igbvf_set_tx_csum,
-	.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,
@@ -541,6 +522,7 @@ static const struct ethtool_ops igbvf_ethtool_ops = {
 void igbvf_set_ethtool_ops(struct net_device *netdev)
 {
 	netdev->hw_features |= NETIF_F_SG;
+	netdev->hw_features |= NETIF_F_TSO|NETIF_F_TSO6;
 	/* have to "undeclare" const on this struct to remove warnings */
 	SET_ETHTOOL_OPS(netdev, (struct ethtool_ops *)&igbvf_ethtool_ops);
 }
diff --git a/drivers/net/ixgb/ixgb_ethtool.c b/drivers/net/ixgb/ixgb_ethtool.c
index 9623e87..b8b38ef 100644
--- a/drivers/net/ixgb/ixgb_ethtool.c
+++ b/drivers/net/ixgb/ixgb_ethtool.c
@@ -234,16 +234,6 @@ ixgb_set_tx_csum(struct net_device *netdev, u32 data)
 	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)
 {
@@ -726,7 +716,6 @@ static const struct ethtool_ops ixgb_ethtool_ops = {
 	.set_tx_csum = ixgb_set_tx_csum,
 	.get_msglevel = ixgb_get_msglevel,
 	.set_msglevel = ixgb_set_msglevel,
-	.set_tso = ixgb_set_tso,
 	.get_strings = ixgb_get_strings,
 	.phys_id = ixgb_phys_id,
 	.get_sset_count = ixgb_get_sset_count,
@@ -735,6 +724,6 @@ static const struct ethtool_ops ixgb_ethtool_ops = {
 
 void ixgb_set_ethtool_ops(struct net_device *netdev)
 {
-	netdev->hw_features |= NETIF_F_SG;
+	netdev->hw_features |= NETIF_F_SG|NETIF_F_TSO;
 	SET_ETHTOOL_OPS(netdev, &ixgb_ethtool_ops);
 }
diff --git a/drivers/net/ixgbe/ixgbe_ethtool.c b/drivers/net/ixgbe/ixgbe_ethtool.c
index 5f1e17c..561a74d 100644
--- a/drivers/net/ixgbe/ixgbe_ethtool.c
+++ b/drivers/net/ixgbe/ixgbe_ethtool.c
@@ -442,18 +442,6 @@ static int ixgbe_set_tx_csum(struct net_device *netdev, u32 data)
 	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);
@@ -2289,8 +2277,6 @@ static const struct ethtool_ops ixgbe_ethtool_ops = {
 	.set_tx_csum            = ixgbe_set_tx_csum,
 	.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,
 	.phys_id                = ixgbe_phys_id,
@@ -2306,5 +2292,6 @@ static const struct ethtool_ops ixgbe_ethtool_ops = {
 void ixgbe_set_ethtool_ops(struct net_device *netdev)
 {
 	netdev->hw_features |= NETIF_F_SG;
+	netdev->hw_features |= NETIF_F_TSO|NETIF_F_TSO6;
 	SET_ETHTOOL_OPS(netdev, &ixgbe_ethtool_ops);
 }
diff --git a/drivers/net/ixgbevf/ethtool.c b/drivers/net/ixgbevf/ethtool.c
index 624375a..58ae092 100644
--- a/drivers/net/ixgbevf/ethtool.c
+++ b/drivers/net/ixgbevf/ethtool.c
@@ -139,20 +139,6 @@ static int ixgbevf_set_rx_csum(struct net_device *netdev, u32 data)
 	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,8 +706,6 @@ static struct ethtool_ops ixgbevf_ethtool_ops = {
 	.set_tx_csum            = ethtool_op_set_tx_ipv6_csum,
 	.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,
@@ -731,5 +715,6 @@ static struct ethtool_ops ixgbevf_ethtool_ops = {
 void ixgbevf_set_ethtool_ops(struct net_device *netdev)
 {
 	netdev->hw_features |= NETIF_F_SG;
+	netdev->hw_features |= NETIF_F_TSO|NETIF_F_TSO6;
 	SET_ETHTOOL_OPS(netdev, &ixgbevf_ethtool_ops);
 }
diff --git a/drivers/net/jme.c b/drivers/net/jme.c
index 1f7a0a7..f837c3f 100644
--- a/drivers/net/jme.c
+++ b/drivers/net/jme.c
@@ -2530,11 +2530,10 @@ jme_set_tso(struct net_device *netdev, u32 on)
 
 	if (on) {
 		set_bit(JME_FLAG_TSO, &jme->flags);
-		if (netdev->mtu <= 1900)
-			netdev->features |= NETIF_F_TSO | NETIF_F_TSO6;
+		if (netdev->mtu > 1900)
+			return 1;
 	} else {
 		clear_bit(JME_FLAG_TSO, &jme->flags);
-		netdev->features &= ~(NETIF_F_TSO | NETIF_F_TSO6);
 	}
 
 	return 0;
@@ -2684,7 +2683,7 @@ static const struct ethtool_ops jme_ethtool_ops = {
 	.get_rx_csum		= jme_get_rx_csum,
 	.set_rx_csum		= jme_set_rx_csum,
 	.set_tx_csum		= jme_set_tx_csum,
-	.set_tso		= jme_set_tso,
+	.hw_set_tso		= jme_set_tso,
 	.nway_reset             = jme_nway_reset,
 	.get_eeprom_len		= jme_get_eeprom_len,
 	.get_eeprom		= jme_get_eeprom,
@@ -2794,7 +2793,7 @@ jme_init_one(struct pci_dev *pdev,
 		goto err_out_release_regions;
 	}
 	netdev->netdev_ops = &jme_netdev_ops;
-	netdev->hw_features |= NETIF_F_SG;
+	netdev->hw_features |= NETIF_F_SG | NETIF_F_TSO | NETIF_F_TSO6;
 	netdev->ethtool_ops		= &jme_ethtool_ops;
 	netdev->watchdog_timeo		= TX_TIMEOUT;
 	netdev->features		=	NETIF_F_HW_CSUM |
diff --git a/drivers/net/loopback.c b/drivers/net/loopback.c
index 208e9f4..76e900c 100644
--- a/drivers/net/loopback.c
+++ b/drivers/net/loopback.c
@@ -129,7 +129,6 @@ static u32 always_on(struct net_device *dev)
 
 static const struct ethtool_ops loopback_ethtool_ops = {
 	.get_link		= always_on,
-	.set_tso		= ethtool_op_set_tso,
 	.get_tx_csum		= always_on,
 	.get_rx_csum		= always_on,
 };
@@ -174,6 +173,7 @@ static void loopback_setup(struct net_device *dev)
 		| NETIF_F_HIGHDMA
 		| NETIF_F_LLTX
 		| NETIF_F_NETNS_LOCAL;
+	dev->hw_features |= NETIF_F_TSO;
 	dev->ethtool_ops	= &loopback_ethtool_ops;
 	dev->header_ops		= &eth_header_ops;
 	dev->netdev_ops		= &loopback_ops;
diff --git a/drivers/net/mlx4/en_ethtool.c b/drivers/net/mlx4/en_ethtool.c
index 1b355b7..a963bcd 100644
--- a/drivers/net/mlx4/en_ethtool.c
+++ b/drivers/net/mlx4/en_ethtool.c
@@ -57,21 +57,13 @@ mlx4_en_get_drvinfo(struct net_device *dev, struct ethtool_drvinfo *drvinfo)
 	drvinfo->eedump_len = 0;
 }
 
-static u32 mlx4_en_get_tso(struct net_device *dev)
-{
-	return (dev->features & NETIF_F_TSO) != 0;
-}
-
 static int mlx4_en_set_tso(struct net_device *dev, u32 data)
 {
 	struct mlx4_en_priv *priv = netdev_priv(dev);
 
-	if (data) {
-		if (!priv->mdev->LSO_support)
-			return -EPERM;
-		dev->features |= (NETIF_F_TSO | NETIF_F_TSO6);
-	} else
-		dev->features &= ~(NETIF_F_TSO | NETIF_F_TSO6);
+	if (data && !priv->mdev->LSO_support)
+		return -EINVAL;
+
 	return 0;
 }
 
@@ -426,10 +418,7 @@ const struct ethtool_ops mlx4_en_ethtool_ops = {
 	.get_drvinfo = mlx4_en_get_drvinfo,
 	.get_settings = mlx4_en_get_settings,
 	.set_settings = mlx4_en_set_settings,
-#ifdef NETIF_F_TSO
-	.get_tso = mlx4_en_get_tso,
-	.set_tso = mlx4_en_set_tso,
-#endif
+	.hw_set_tso = mlx4_en_set_tso,
 	.get_link = ethtool_op_get_link,
 	.get_rx_csum = mlx4_en_get_rx_csum,
 	.set_rx_csum = mlx4_en_set_rx_csum,
diff --git a/drivers/net/mlx4/en_netdev.c b/drivers/net/mlx4/en_netdev.c
index f496dbc..b867b34 100644
--- a/drivers/net/mlx4/en_netdev.c
+++ b/drivers/net/mlx4/en_netdev.c
@@ -1039,6 +1039,7 @@ int mlx4_en_init_netdev(struct mlx4_en_dev *mdev, int port,
 	netif_set_real_num_rx_queues(dev, priv->rx_ring_num);
 
 	dev->hw_features |= NETIF_F_SG;
+	dev->hw_features |= NETIF_F_TSO|NETIF_F_TSO6;
 	SET_ETHTOOL_OPS(dev, &mlx4_en_ethtool_ops);
 
 	/* Set defualt MAC */
diff --git a/drivers/net/myri10ge/myri10ge.c b/drivers/net/myri10ge/myri10ge.c
index 3696bba..4f8b838 100644
--- a/drivers/net/myri10ge/myri10ge.c
+++ b/drivers/net/myri10ge/myri10ge.c
@@ -1773,18 +1773,6 @@ static int myri10ge_set_rx_csum(struct net_device *netdev, u32 csum_enabled)
 	return err;
 }
 
-static int myri10ge_set_tso(struct net_device *netdev, u32 tso_enabled)
-{
-	struct myri10ge_priv *mgp = netdev_priv(netdev);
-	unsigned long flags = mgp->features & (NETIF_F_TSO6 | NETIF_F_TSO);
-
-	if (tso_enabled)
-		netdev->features |= flags;
-	else
-		netdev->features &= ~flags;
-	return 0;
-}
-
 static const char myri10ge_gstrings_main_stats[][ETH_GSTRING_LEN] = {
 	"rx_packets", "tx_packets", "rx_bytes", "tx_bytes", "rx_errors",
 	"tx_errors", "rx_dropped", "tx_dropped", "multicast", "collisions",
@@ -1951,7 +1939,6 @@ static const struct ethtool_ops myri10ge_ethtool_ops = {
 	.get_rx_csum = myri10ge_get_rx_csum,
 	.set_rx_csum = myri10ge_set_rx_csum,
 	.set_tx_csum = ethtool_op_set_tx_hw_csum,
-	.set_tso = myri10ge_set_tso,
 	.get_link = ethtool_op_get_link,
 	.get_strings = myri10ge_get_strings,
 	.get_sset_count = myri10ge_get_sset_count,
@@ -3998,6 +3985,7 @@ static int myri10ge_probe(struct pci_dev *pdev, const struct pci_device_id *ent)
 
 	spin_lock_init(&mgp->stats_lock);
 	netdev->hw_features |= NETIF_F_SG;
+	netdev->hw_features |= NETIF_F_TSO|NETIF_F_TSO6;
 	SET_ETHTOOL_OPS(netdev, &myri10ge_ethtool_ops);
 	INIT_WORK(&mgp->watchdog_work, myri10ge_watchdog);
 	status = register_netdev(netdev);
diff --git a/drivers/net/netxen/netxen_nic_ethtool.c b/drivers/net/netxen/netxen_nic_ethtool.c
index f22f0a7..9244bb1 100644
--- a/drivers/net/netxen/netxen_nic_ethtool.c
+++ b/drivers/net/netxen/netxen_nic_ethtool.c
@@ -724,30 +724,6 @@ static int netxen_nic_set_rx_csum(struct net_device *dev, u32 data)
 	return 0;
 }
 
-static u32 netxen_nic_get_tso(struct net_device *dev)
-{
-	struct netxen_adapter *adapter = netdev_priv(dev);
-
-	if (NX_IS_REVISION_P3(adapter->ahw.revision_id))
-		return (dev->features & (NETIF_F_TSO | NETIF_F_TSO6)) != 0;
-
-	return (dev->features & NETIF_F_TSO) != 0;
-}
-
-static int netxen_nic_set_tso(struct net_device *dev, u32 data)
-{
-	if (data) {
-		struct netxen_adapter *adapter = netdev_priv(dev);
-
-		dev->features |= NETIF_F_TSO;
-		if (NX_IS_REVISION_P3(adapter->ahw.revision_id))
-			dev->features |= NETIF_F_TSO6;
-	} else
-		dev->features &= ~(NETIF_F_TSO | NETIF_F_TSO6);
-
-	return 0;
-}
-
 static void
 netxen_nic_get_wol(struct net_device *dev, struct ethtool_wolinfo *wol)
 {
@@ -926,8 +902,6 @@ const struct ethtool_ops netxen_nic_ethtool_ops = {
 	.set_pauseparam = netxen_nic_set_pauseparam,
 	.get_tx_csum = netxen_nic_get_tx_csum,
 	.set_tx_csum = ethtool_op_set_tx_csum,
-	.get_tso = netxen_nic_get_tso,
-	.set_tso = netxen_nic_set_tso,
 	.get_wol = netxen_nic_get_wol,
 	.set_wol = netxen_nic_set_wol,
 	.self_test = netxen_nic_diag_test,
diff --git a/drivers/net/netxen/netxen_nic_main.c b/drivers/net/netxen/netxen_nic_main.c
index 4b2874c..573e51f 100644
--- a/drivers/net/netxen/netxen_nic_main.c
+++ b/drivers/net/netxen/netxen_nic_main.c
@@ -1210,7 +1210,9 @@ netxen_setup_netdev(struct netxen_adapter *adapter,
 
 	netxen_nic_change_mtu(netdev, netdev->mtu);
 
-	netdev->hw_features |= NETIF_F_SG;
+	netdev->hw_features |= NETIF_F_SG|NETIF_F_TSO;
+	if (NX_IS_REVISION_P3(adapter->ahw.revision_id))
+		netdev->hw_features |= NETIF_F_TSO6;
 	SET_ETHTOOL_OPS(netdev, &netxen_nic_ethtool_ops);
 
 	netdev->features |= (NETIF_F_SG | NETIF_F_IP_CSUM | NETIF_F_TSO);
diff --git a/drivers/net/qlcnic/qlcnic_ethtool.c b/drivers/net/qlcnic/qlcnic_ethtool.c
index ceba22d..abf89ba 100644
--- a/drivers/net/qlcnic/qlcnic_ethtool.c
+++ b/drivers/net/qlcnic/qlcnic_ethtool.c
@@ -931,24 +931,6 @@ static int qlcnic_set_rx_csum(struct net_device *dev, u32 data)
 	return 0;
 }
 
-static u32 qlcnic_get_tso(struct net_device *dev)
-{
-	return (dev->features & (NETIF_F_TSO | NETIF_F_TSO6)) != 0;
-}
-
-static int qlcnic_set_tso(struct net_device *dev, u32 data)
-{
-	struct qlcnic_adapter *adapter = netdev_priv(dev);
-	if (!(adapter->capabilities & QLCNIC_FW_CAPABILITY_TSO))
-		return -EOPNOTSUPP;
-	if (data)
-		dev->features |= (NETIF_F_TSO | NETIF_F_TSO6);
-	else
-		dev->features &= ~(NETIF_F_TSO | NETIF_F_TSO6);
-
-	return 0;
-}
-
 static int qlcnic_blink_led(struct net_device *dev, u32 val)
 {
 	struct qlcnic_adapter *adapter = netdev_priv(dev);
@@ -1166,8 +1148,6 @@ const struct ethtool_ops qlcnic_ethtool_ops = {
 	.set_pauseparam = qlcnic_set_pauseparam,
 	.get_tx_csum = qlcnic_get_tx_csum,
 	.set_tx_csum = qlcnic_set_tx_csum,
-	.get_tso = qlcnic_get_tso,
-	.set_tso = qlcnic_set_tso,
 	.get_wol = qlcnic_get_wol,
 	.set_wol = qlcnic_set_wol,
 	.self_test = qlcnic_diag_test,
diff --git a/drivers/net/qlcnic/qlcnic_main.c b/drivers/net/qlcnic/qlcnic_main.c
index 30ed19a..53e07ed 100644
--- a/drivers/net/qlcnic/qlcnic_main.c
+++ b/drivers/net/qlcnic/qlcnic_main.c
@@ -1434,6 +1434,7 @@ qlcnic_setup_netdev(struct qlcnic_adapter *adapter,
 		NETIF_F_IPV6_CSUM);
 
 	if (adapter->capabilities & QLCNIC_FW_CAPABILITY_TSO) {
+		netdev->hw_features |= (NETIF_F_TSO | NETIF_F_TSO6);
 		netdev->features |= (NETIF_F_TSO | NETIF_F_TSO6);
 		netdev->vlan_features |= (NETIF_F_TSO | NETIF_F_TSO6);
 	}
diff --git a/drivers/net/qlge/qlge_ethtool.c b/drivers/net/qlge/qlge_ethtool.c
index d8b2d3f..9b7bddf 100644
--- a/drivers/net/qlge/qlge_ethtool.c
+++ b/drivers/net/qlge/qlge_ethtool.c
@@ -655,19 +655,6 @@ static int ql_set_rx_csum(struct net_device *netdev, uint32_t data)
 	return 0;
 }
 
-static int ql_set_tso(struct net_device *ndev, uint32_t data)
-{
-
-	if (data) {
-		ndev->features |= NETIF_F_TSO;
-		ndev->features |= NETIF_F_TSO6;
-	} else {
-		ndev->features &= ~NETIF_F_TSO;
-		ndev->features &= ~NETIF_F_TSO6;
-	}
-	return 0;
-}
-
 static u32 ql_get_msglevel(struct net_device *ndev)
 {
 	struct ql_adapter *qdev = netdev_priv(ndev);
@@ -698,8 +685,6 @@ const struct ethtool_ops qlge_ethtool_ops = {
 	.set_rx_csum = ql_set_rx_csum,
 	.get_tx_csum = ethtool_op_get_tx_csum,
 	.set_tx_csum = ethtool_op_set_tx_csum,
-	.get_tso = ethtool_op_get_tso,
-	.set_tso = ql_set_tso,
 	.get_coalesce = ql_get_coalesce,
 	.set_coalesce = ql_set_coalesce,
 	.get_sset_count = ql_get_sset_count,
diff --git a/drivers/net/qlge/qlge_main.c b/drivers/net/qlge/qlge_main.c
index 75b708c..fb36da6 100644
--- a/drivers/net/qlge/qlge_main.c
+++ b/drivers/net/qlge/qlge_main.c
@@ -4714,6 +4714,7 @@ static int __devinit qlge_probe(struct pci_dev *pdev,
 
 	ndev->netdev_ops = &qlge_netdev_ops;
 	ndev->hw_features |= NETIF_F_SG;
+	ndev->hw_features |= NETIF_F_TSO|NETIF_F_TSO6;
 	SET_ETHTOOL_OPS(ndev, &qlge_ethtool_ops);
 	ndev->watchdog_timeo = 10 * HZ;
 
diff --git a/drivers/net/r8169.c b/drivers/net/r8169.c
index 746e296..999a713 100644
--- a/drivers/net/r8169.c
+++ b/drivers/net/r8169.c
@@ -1277,7 +1277,6 @@ static const struct ethtool_ops rtl8169_ethtool_ops = {
 	.get_rx_csum		= rtl8169_get_rx_csum,
 	.set_rx_csum		= rtl8169_set_rx_csum,
 	.set_tx_csum		= ethtool_op_set_tx_csum,
-	.set_tso		= ethtool_op_set_tso,
 	.get_regs		= rtl8169_get_regs,
 	.get_wol		= rtl8169_get_wol,
 	.set_wol		= rtl8169_set_wol,
@@ -3172,7 +3171,7 @@ rtl8169_init_one(struct pci_dev *pdev, const struct pci_device_id *ent)
 		dev->dev_addr[i] = RTL_R8(MAC0 + i);
 	memcpy(dev->perm_addr, dev->dev_addr, dev->addr_len);
 
-	dev->hw_features |= NETIF_F_SG;
+	dev->hw_features |= NETIF_F_SG|NETIF_F_TSO;
 	SET_ETHTOOL_OPS(dev, &rtl8169_ethtool_ops);
 	dev->watchdog_timeo = RTL8169_TX_TIMEOUT;
 	dev->irq = pdev->irq;
diff --git a/drivers/net/s2io.c b/drivers/net/s2io.c
index e447a4d..ef63529 100644
--- a/drivers/net/s2io.c
+++ b/drivers/net/s2io.c
@@ -6704,21 +6704,6 @@ static int s2io_ethtool_op_set_tx_csum(struct net_device *dev, u32 data)
 	return 0;
 }
 
-static u32 s2io_ethtool_op_get_tso(struct net_device *dev)
-{
-	return (dev->features & NETIF_F_TSO) != 0;
-}
-
-static int s2io_ethtool_op_set_tso(struct net_device *dev, u32 data)
-{
-	if (data)
-		dev->features |= (NETIF_F_TSO | NETIF_F_TSO6);
-	else
-		dev->features &= ~(NETIF_F_TSO | NETIF_F_TSO6);
-
-	return 0;
-}
-
 static int s2io_ethtool_set_flags(struct net_device *dev, u32 data)
 {
 	struct s2io_nic *sp = netdev_priv(dev);
@@ -6769,8 +6754,6 @@ static const struct ethtool_ops netdev_ethtool_ops = {
 	.set_tx_csum = s2io_ethtool_op_set_tx_csum,
 	.set_flags = s2io_ethtool_set_flags,
 	.get_flags = ethtool_op_get_flags,
-	.get_tso = s2io_ethtool_op_get_tso,
-	.set_tso = s2io_ethtool_op_set_tso,
 	.set_ufo = ethtool_op_set_ufo,
 	.self_test = s2io_ethtool_test,
 	.get_strings = s2io_ethtool_get_strings,
@@ -8034,6 +8017,7 @@ s2io_init_nic(struct pci_dev *pdev, const struct pci_device_id *pre)
 	/*  Driver entry points */
 	dev->netdev_ops = &s2io_netdev_ops;
 	dev->hw_features |= NETIF_F_SG;
+	dev->hw_features |= NETIF_F_TSO|NETIF_F_TSO6;
 	SET_ETHTOOL_OPS(dev, &netdev_ethtool_ops);
 	dev->features |= NETIF_F_HW_VLAN_TX | NETIF_F_HW_VLAN_RX;
 	dev->features |= NETIF_F_LRO;
diff --git a/drivers/net/sfc/efx.c b/drivers/net/sfc/efx.c
index b6b0f5d..26bb98b 100644
--- a/drivers/net/sfc/efx.c
+++ b/drivers/net/sfc/efx.c
@@ -1882,7 +1882,9 @@ static int efx_register_netdev(struct efx_nic *efx)
 	net_dev->watchdog_timeo = 5 * HZ;
 	net_dev->irq = efx->pci_dev->irq;
 	net_dev->netdev_ops = &efx_netdev_ops;
-	net_dev->hw_features |= NETIF_F_SG;
+	net_dev->hw_features |= NETIF_F_SG|NETIF_F_TSO;
+	if (efx->type->offload_features & NETIF_F_V6_CSUM)
+		net_dev->hw_features |= NETIF_F_TSO6;
 	SET_ETHTOOL_OPS(net_dev, &efx_ethtool_ops);
 
 	/* Clear MAC statistics */
diff --git a/drivers/net/sfc/ethtool.c b/drivers/net/sfc/ethtool.c
index c994666..dd2b271 100644
--- a/drivers/net/sfc/ethtool.c
+++ b/drivers/net/sfc/ethtool.c
@@ -500,23 +500,6 @@ static void efx_ethtool_get_stats(struct net_device *net_dev,
 	}
 }
 
-static int efx_ethtool_set_tso(struct net_device *net_dev, u32 enable)
-{
-	struct efx_nic *efx __attribute__ ((unused)) = netdev_priv(net_dev);
-	unsigned long features;
-
-	features = NETIF_F_TSO;
-	if (efx->type->offload_features & NETIF_F_V6_CSUM)
-		features |= NETIF_F_TSO6;
-
-	if (enable)
-		net_dev->features |= features;
-	else
-		net_dev->features &= ~features;
-
-	return 0;
-}
-
 static int efx_ethtool_set_tx_csum(struct net_device *net_dev, u32 enable)
 {
 	struct efx_nic *efx = netdev_priv(net_dev);
@@ -1130,9 +1113,6 @@ const struct ethtool_ops efx_ethtool_ops = {
 	.get_tx_csum		= ethtool_op_get_tx_csum,
 	/* Need to enable/disable IPv6 too */
 	.set_tx_csum		= efx_ethtool_set_tx_csum,
-	.get_tso		= ethtool_op_get_tso,
-	/* Need to enable/disable TSO-IPv6 too */
-	.set_tso		= efx_ethtool_set_tso,
 	.get_flags		= ethtool_op_get_flags,
 	.set_flags		= efx_ethtool_set_flags,
 	.get_sset_count		= efx_ethtool_get_sset_count,
diff --git a/drivers/net/sky2.c b/drivers/net/sky2.c
index a06bb6e..98534ef 100644
--- a/drivers/net/sky2.c
+++ b/drivers/net/sky2.c
@@ -4080,7 +4080,7 @@ static int sky2_set_tso(struct net_device *dev, u32 data)
 	if (data && no_tx_offload(dev))
 		return -EINVAL;
 
-	return ethtool_op_set_tso(dev, data);
+	return 0;
 }
 
 static int sky2_get_eeprom_len(struct net_device *dev)
@@ -4217,7 +4217,7 @@ static const struct ethtool_ops sky2_ethtool_ops = {
 	.get_eeprom	= sky2_get_eeprom,
 	.set_eeprom	= sky2_set_eeprom,
 	.set_tx_csum	= sky2_set_tx_csum,
-	.set_tso	= sky2_set_tso,
+	.hw_set_tso	= sky2_set_tso,
 	.get_rx_csum	= sky2_get_rx_csum,
 	.set_rx_csum	= sky2_set_rx_csum,
 	.get_strings	= sky2_get_strings,
@@ -4549,7 +4549,7 @@ static __devinit struct net_device *sky2_init_netdev(struct sky2_hw *hw,
 
 	SET_NETDEV_DEV(dev, &hw->pdev->dev);
 	dev->irq = hw->pdev->irq;
-	dev->hw_features |= NETIF_F_SG;
+	dev->hw_features |= NETIF_F_SG|NETIF_F_TSO;
 	SET_ETHTOOL_OPS(dev, &sky2_ethtool_ops);
 	dev->watchdog_timeo = TX_WATCHDOG;
 	dev->netdev_ops = &sky2_netdev_ops[port];
diff --git a/drivers/net/stmmac/stmmac_ethtool.c b/drivers/net/stmmac/stmmac_ethtool.c
index 4461a9e..0674ebb 100644
--- a/drivers/net/stmmac/stmmac_ethtool.c
+++ b/drivers/net/stmmac/stmmac_ethtool.c
@@ -378,12 +378,10 @@ static struct ethtool_ops stmmac_ethtool_ops = {
 	.get_wol = stmmac_get_wol,
 	.set_wol = stmmac_set_wol,
 	.get_sset_count	= stmmac_get_sset_count,
-	.get_tso = ethtool_op_get_tso,
-	.set_tso = ethtool_op_set_tso,
 };
 
 void stmmac_set_ethtool_ops(struct net_device *netdev)
 {
-	netdev->hw_features |= NETIF_F_SG;
+	netdev->hw_features |= NETIF_F_SG|NETIF_F_TSO;
 	SET_ETHTOOL_OPS(netdev, &stmmac_ethtool_ops);
 }
diff --git a/drivers/net/tehuti.c b/drivers/net/tehuti.c
index ed6dc44..42913bf 100644
--- a/drivers/net/tehuti.c
+++ b/drivers/net/tehuti.c
@@ -2426,7 +2426,6 @@ static void bdx_set_ethtool_ops(struct net_device *netdev)
 		.set_ringparam = bdx_set_ringparam,
 		.get_rx_csum = bdx_get_rx_csum,
 		.get_tx_csum = bdx_get_tx_csum,
-		.get_tso = ethtool_op_get_tso,
 		.get_strings = bdx_get_strings,
 		.get_sset_count = bdx_get_sset_count,
 		.get_ethtool_stats = bdx_get_ethtool_stats,
diff --git a/drivers/net/tg3.c b/drivers/net/tg3.c
index b07e2d1..c08172d 100644
--- a/drivers/net/tg3.c
+++ b/drivers/net/tg3.c
@@ -6142,7 +6142,7 @@ static inline void tg3_set_mtu(struct net_device *dev, struct tg3 *tp,
 	if (new_mtu > ETH_DATA_LEN) {
 		if (tp->tg3_flags2 & TG3_FLG2_5780_CLASS) {
 			tp->tg3_flags2 &= ~TG3_FLG2_TSO_CAPABLE;
-			ethtool_op_set_tso(dev, 0);
+			dev->features &= ~NETIF_F_ALL_TSO;
 		} else {
 			tp->tg3_flags |= TG3_FLAG_JUMBO_RING_ENABLE;
 		}
@@ -9977,27 +9977,28 @@ static int tg3_set_tso(struct net_device *dev, u32 value)
 {
 	struct tg3 *tp = netdev_priv(dev);
 
-	if (!(tp->tg3_flags2 & TG3_FLG2_TSO_CAPABLE)) {
-		if (value)
-			return -EINVAL;
+	if (!(tp->tg3_flags2 & TG3_FLG2_TSO_CAPABLE) && value)
+		return -EINVAL;
+
+	if (!value)
 		return 0;
-	}
+
+	dev->features |= NETIF_F_TSO;
+
 	if ((dev->features & NETIF_F_IPV6_CSUM) &&
 	    ((tp->tg3_flags2 & TG3_FLG2_HW_TSO_2) ||
 	     (tp->tg3_flags2 & TG3_FLG2_HW_TSO_3))) {
-		if (value) {
-			dev->features |= NETIF_F_TSO6;
-			if ((tp->tg3_flags2 & TG3_FLG2_HW_TSO_3) ||
-			    GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5761 ||
-			    (GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5784 &&
-			     GET_CHIP_REV(tp->pci_chip_rev_id) != CHIPREV_5784_AX) ||
-			    GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5785 ||
-			    GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_57780)
-				dev->features |= NETIF_F_TSO_ECN;
-		} else
-			dev->features &= ~(NETIF_F_TSO6 | NETIF_F_TSO_ECN);
+		dev->features |= NETIF_F_TSO6;
+		if ((tp->tg3_flags2 & TG3_FLG2_HW_TSO_3) ||
+		    GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5761 ||
+		    (GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5784 &&
+		     GET_CHIP_REV(tp->pci_chip_rev_id) != CHIPREV_5784_AX) ||
+		    GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5785 ||
+		    GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_57780)
+			dev->features |= NETIF_F_TSO_ECN;
 	}
-	return ethtool_op_set_tso(dev, value);
+
+	return 1;
 }
 
 static int tg3_nway_reset(struct net_device *dev)
@@ -11306,7 +11307,7 @@ static const struct ethtool_ops tg3_ethtool_ops = {
 	.get_rx_csum		= tg3_get_rx_csum,
 	.set_rx_csum		= tg3_set_rx_csum,
 	.set_tx_csum		= tg3_set_tx_csum,
-	.set_tso		= tg3_set_tso,
+	.hw_set_tso		= tg3_set_tso,
 	.self_test		= tg3_self_test,
 	.get_strings		= tg3_get_strings,
 	.phys_id		= tg3_phys_id,
@@ -14681,6 +14682,7 @@ static int __devinit tg3_init_one(struct pci_dev *pdev,
 	tp->rx_jumbo_pending = TG3_DEF_RX_JUMBO_RING_PENDING;
 
 	dev->hw_features |= NETIF_F_SG;
+	dev->hw_features |= NETIF_F_TSO|NETIF_F_TSO6|NETIF_F_TSO_ECN;
 	dev->ethtool_ops = &tg3_ethtool_ops;
 	dev->watchdog_timeo = TG3_TX_TIMEOUT;
 	dev->irq = pdev->irq;
diff --git a/drivers/net/typhoon.c b/drivers/net/typhoon.c
index 4b49dd7..cc2f811 100644
--- a/drivers/net/typhoon.c
+++ b/drivers/net/typhoon.c
@@ -1191,7 +1191,6 @@ static const struct ethtool_ops typhoon_ethtool_ops = {
 	.get_link		= ethtool_op_get_link,
 	.get_rx_csum		= typhoon_get_rx_csum,
 	.set_tx_csum		= ethtool_op_set_tx_csum,
-	.set_tso		= ethtool_op_set_tso,
 	.get_ringparam		= typhoon_get_ringparam,
 	.set_flags		= typhoon_set_flags,
 	.get_flags		= ethtool_op_get_flags,
@@ -2479,7 +2478,7 @@ typhoon_init_one(struct pci_dev *pdev, const struct pci_device_id *ent)
 	netif_napi_add(dev, &tp->napi, typhoon_poll, 16);
 	dev->watchdog_timeo	= TX_TIMEOUT;
 
-	dev->hw_features |= NETIF_F_SG;
+	dev->hw_features |= NETIF_F_SG|NETIF_F_TSO;
 	SET_ETHTOOL_OPS(dev, &typhoon_ethtool_ops);
 
 	/* We can handle scatter gather, up to 16 entries, and
diff --git a/drivers/net/usb/smsc75xx.c b/drivers/net/usb/smsc75xx.c
index 753ee6e..466ed50 100644
--- a/drivers/net/usb/smsc75xx.c
+++ b/drivers/net/usb/smsc75xx.c
@@ -617,16 +617,6 @@ static int smsc75xx_ethtool_set_rx_csum(struct net_device *netdev, u32 val)
 	return smsc75xx_set_rx_csum_offload(dev);
 }
 
-static int smsc75xx_ethtool_set_tso(struct net_device *netdev, u32 data)
-{
-	if (data)
-		netdev->features |= NETIF_F_TSO | NETIF_F_TSO6;
-	else
-		netdev->features &= ~(NETIF_F_TSO | NETIF_F_TSO6);
-
-	return 0;
-}
-
 static const struct ethtool_ops smsc75xx_ethtool_ops = {
 	.get_link	= usbnet_get_link,
 	.nway_reset	= usbnet_nway_reset,
@@ -642,8 +632,6 @@ static const struct ethtool_ops smsc75xx_ethtool_ops = {
 	.set_tx_csum	= ethtool_op_set_tx_hw_csum,
 	.get_rx_csum	= smsc75xx_ethtool_get_rx_csum,
 	.set_rx_csum	= smsc75xx_ethtool_set_rx_csum,
-	.get_tso	= ethtool_op_get_tso,
-	.set_tso	= smsc75xx_ethtool_set_tso,
 };
 
 static int smsc75xx_ioctl(struct net_device *netdev, struct ifreq *rq, int cmd)
@@ -964,8 +952,6 @@ static int smsc75xx_reset(struct usbnet *dev)
 	ret = smsc75xx_set_rx_csum_offload(dev);
 	check_warn_return(ret, "Failed to set rx csum offload: %d", ret);
 
-	smsc75xx_ethtool_set_tso(dev->net, DEFAULT_TSO_ENABLE);
-
 	smsc75xx_set_multicast(dev->net);
 
 	ret = smsc75xx_phy_initialize(dev);
@@ -1069,11 +1055,14 @@ static int smsc75xx_bind(struct usbnet *dev, struct usb_interface *intf)
 
 	/* We have to advertise SG otherwise TSO cannot be enabled */
 	dev->net->features |= NETIF_F_SG;
+	if (DEFAULT_TSO_ENABLE)
+		dev->net->features |= NETIF_F_TSO | NETIF_F_TSO6;
 
 	/* Init all registers */
 	ret = smsc75xx_reset(dev);
 
 	dev->net->netdev_ops = &smsc75xx_netdev_ops;
+	dev->net->hw_features |= NETIF_F_TSO | NETIF_F_TSO6;
 	dev->net->ethtool_ops = &smsc75xx_ethtool_ops;
 	dev->net->flags |= IFF_MULTICAST;
 	dev->net->hard_header_len += SMSC75XX_TX_OVERHEAD;
diff --git a/drivers/net/virtio_net.c b/drivers/net/virtio_net.c
index b332e92..037913f 100644
--- a/drivers/net/virtio_net.c
+++ b/drivers/net/virtio_net.c
@@ -818,7 +818,6 @@ static void virtnet_vlan_rx_kill_vid(struct net_device *dev, u16 vid)
 
 static const struct ethtool_ops virtnet_ethtool_ops = {
 	.set_tx_csum = virtnet_set_tx_csum,
-	.set_tso = ethtool_op_set_tso,
 	.set_ufo = ethtool_op_set_ufo,
 	.get_link = ethtool_op_get_link,
 };
@@ -902,7 +901,7 @@ static int virtnet_probe(struct virtio_device *vdev)
 	/* Set up network device as normal. */
 	dev->netdev_ops = &virtnet_netdev;
 	dev->features = NETIF_F_HIGHDMA;
-	dev->hw_features |= NETIF_F_SG;
+	dev->hw_features |= NETIF_F_SG|NETIF_F_TSO;
 	SET_ETHTOOL_OPS(dev, &virtnet_ethtool_ops);
 	SET_NETDEV_DEV(dev, &vdev->dev);
 
diff --git a/drivers/net/vmxnet3/vmxnet3_ethtool.c b/drivers/net/vmxnet3/vmxnet3_ethtool.c
index 9925d2b..a43c5fb 100644
--- a/drivers/net/vmxnet3/vmxnet3_ethtool.c
+++ b/drivers/net/vmxnet3/vmxnet3_ethtool.c
@@ -547,8 +547,6 @@ static struct ethtool_ops vmxnet3_ethtool_ops = {
 	.set_rx_csum       = vmxnet3_set_rx_csum,
 	.get_tx_csum       = ethtool_op_get_tx_csum,
 	.set_tx_csum       = ethtool_op_set_tx_hw_csum,
-	.get_tso           = ethtool_op_get_tso,
-	.set_tso           = ethtool_op_set_tso,
 	.get_strings       = vmxnet3_get_strings,
 	.get_flags	   = ethtool_op_get_flags,
 	.set_flags	   = vmxnet3_set_flags,
@@ -560,6 +558,6 @@ static struct ethtool_ops vmxnet3_ethtool_ops = {
 
 void vmxnet3_set_ethtool_ops(struct net_device *netdev)
 {
-	netdev->hw_features |= NETIF_F_SG;
+	netdev->hw_features |= NETIF_F_SG|NETIF_F_TSO;
 	SET_ETHTOOL_OPS(netdev, &vmxnet3_ethtool_ops);
 }
diff --git a/drivers/net/vxge/vxge-ethtool.c b/drivers/net/vxge/vxge-ethtool.c
index 3c7ccd0..df9e500 100644
--- a/drivers/net/vxge/vxge-ethtool.c
+++ b/drivers/net/vxge/vxge-ethtool.c
@@ -1090,16 +1090,6 @@ static int vxge_set_rx_csum(struct net_device *dev, u32 data)
 	return 0;
 }
 
-static int vxge_ethtool_op_set_tso(struct net_device *dev, u32 data)
-{
-	if (data)
-		dev->features |= (NETIF_F_TSO | NETIF_F_TSO6);
-	else
-		dev->features &= ~(NETIF_F_TSO | NETIF_F_TSO6);
-
-	return 0;
-}
-
 static int vxge_ethtool_get_sset_count(struct net_device *dev, int sset)
 {
 	struct vxgedev *vdev = (struct vxgedev *)netdev_priv(dev);
@@ -1132,8 +1122,6 @@ static const struct ethtool_ops vxge_ethtool_ops = {
 	.set_rx_csum		= vxge_set_rx_csum,
 	.get_tx_csum		= ethtool_op_get_tx_csum,
 	.set_tx_csum		= ethtool_op_set_tx_hw_csum,
-	.get_tso		= ethtool_op_get_tso,
-	.set_tso		= vxge_ethtool_op_set_tso,
 	.get_strings		= vxge_ethtool_get_strings,
 	.phys_id		= vxge_ethtool_idnic,
 	.get_sset_count		= vxge_ethtool_get_sset_count,
@@ -1143,5 +1131,6 @@ static const struct ethtool_ops vxge_ethtool_ops = {
 void vxge_initialize_ethtool_ops(struct net_device *ndev)
 {
 	ndev->hw_features |= NETIF_F_SG;
+	ndev->hw_features |= NETIF_F_TSO|NETIF_F_TSO6;
 	SET_ETHTOOL_OPS(ndev, &vxge_ethtool_ops);
 }
diff --git a/drivers/net/xen-netfront.c b/drivers/net/xen-netfront.c
index e494cc2..5715ba6 100644
--- a/drivers/net/xen-netfront.c
+++ b/drivers/net/xen-netfront.c
@@ -1178,7 +1178,7 @@ static struct net_device * __devinit xennet_create_dev(struct xenbus_device *dev
 	netif_napi_add(netdev, &np->napi, xennet_poll, 64);
 	netdev->features        = NETIF_F_IP_CSUM;
 
-	netdev->hw_features |= NETIF_F_SG;
+	netdev->hw_features |= NETIF_F_SG|NETIF_F_TSO;
 	SET_ETHTOOL_OPS(netdev, &xennet_ethtool_ops);
 	SET_NETDEV_DEV(netdev, &dev->dev);
 
@@ -1508,7 +1508,7 @@ static int xennet_set_tso(struct net_device *dev, u32 data)
 			return -ENOSYS;
 	}
 
-	return ethtool_op_set_tso(dev, data);
+	return 0;
 }
 
 static void xennet_set_features(struct net_device *dev)
@@ -1525,7 +1525,8 @@ static void xennet_set_features(struct net_device *dev)
 
 	if (!xennet_set_sg(dev, 1)) {
 		dev->features |= NETIF_F_SG;
-		xennet_set_tso(dev, 1);
+		if (!xennet_set_tso(dev, 1))
+			dev->features |= NETIF_F_TSO;
 	}
 }
 
@@ -1640,7 +1641,7 @@ static const struct ethtool_ops xennet_ethtool_ops =
 {
 	.set_tx_csum = ethtool_op_set_tx_csum,
 	.hw_set_sg = xennet_set_sg,
-	.set_tso = xennet_set_tso,
+	.hw_set_tso = xennet_set_tso,
 	.get_link = ethtool_op_get_link,
 };
 
diff --git a/drivers/s390/net/qeth_l3_main.c b/drivers/s390/net/qeth_l3_main.c
index 5fd646f..efd49c9 100644
--- a/drivers/s390/net/qeth_l3_main.c
+++ b/drivers/s390/net/qeth_l3_main.c
@@ -3230,7 +3230,7 @@ static int qeth_l3_ethtool_set_tso(struct net_device *dev, u32 data)
 		dev->features &= ~NETIF_F_TSO;
 		card->options.large_send = QETH_LARGE_SEND_NO;
 	}
-	return rc;
+	return rc ? rc : 1;
 }
 
 static int qeth_l3_ethtool_set_tx_csum(struct net_device *dev, u32 data)
@@ -3254,8 +3254,7 @@ static const struct ethtool_ops qeth_l3_ethtool_ops = {
 	.set_tx_csum = qeth_l3_ethtool_set_tx_csum,
 	.get_rx_csum = qeth_l3_ethtool_get_rx_csum,
 	.set_rx_csum = qeth_l3_ethtool_set_rx_csum,
-	.get_tso     = ethtool_op_get_tso,
-	.set_tso     = qeth_l3_ethtool_set_tso,
+	.hw_set_tso  = qeth_l3_ethtool_set_tso,
 	.get_strings = qeth_core_get_strings,
 	.get_ethtool_stats = qeth_core_get_ethtool_stats,
 	.get_sset_count = qeth_core_get_sset_count,
@@ -3355,7 +3354,7 @@ static int qeth_l3_setup_netdev(struct qeth_card *card)
 	card->dev->ml_priv = card;
 	card->dev->watchdog_timeo = QETH_TX_TIMEOUT;
 	card->dev->mtu = card->info.initial_mtu;
-	card->dev->hw_features |= NETIF_F_SG;
+	card->dev->hw_features |= NETIF_F_SG|NETIF_F_TSO;
 	SET_ETHTOOL_OPS(card->dev, &qeth_l3_ethtool_ops);
 	card->dev->features |=	NETIF_F_HW_VLAN_TX |
 				NETIF_F_HW_VLAN_RX |
diff --git a/include/linux/ethtool.h b/include/linux/ethtool.h
index 6b26e3e..0efb1c9 100644
--- a/include/linux/ethtool.h
+++ b/include/linux/ethtool.h
@@ -548,8 +548,6 @@ 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_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);
@@ -581,8 +579,7 @@ void ethtool_ntuple_flush(struct net_device *dev);
  * get_tx_csum: Report whether transmit checksums are turned on or off
  * set_tx_csum: Turn transmit checksums on or off
  * hw_set_sg: Turn scatter-gather on or off
- * get_tso: Report whether TCP segmentation offload is enabled
- * set_tso: Turn TCP segmentation offload on or off
+ * hw_set_tso: Turn TCP segmentation offload on or off
  * get_ufo: Report whether UDP fragmentation offload is enabled
  * set_ufo: Turn UDP fragmentation offload on or off
  * self_test: Run specified self-tests
@@ -646,8 +643,7 @@ struct ethtool_ops {
 	u32	(*get_tx_csum)(struct net_device *);
 	int	(*set_tx_csum)(struct net_device *, u32);
 	int	(*hw_set_sg)(struct net_device *, u32);
-	u32	(*get_tso)(struct net_device *);
-	int	(*set_tso)(struct net_device *, u32);
+	int	(*hw_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	(*phys_id)(struct net_device *, u32);
diff --git a/include/linux/netdevice.h b/include/linux/netdevice.h
index f11a5a1..1c35967 100644
--- a/include/linux/netdevice.h
+++ b/include/linux/netdevice.h
@@ -877,6 +877,8 @@ struct net_device {
 #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_TSO_ECN | NETIF_F_TSO6)
+
 	/*
 	 * If one device supports one of these features, then enable them
 	 * for all in netdev_increment_features.
diff --git a/net/8021q/vlan_dev.c b/net/8021q/vlan_dev.c
index 14e3d1f..fae31b1 100644
--- a/net/8021q/vlan_dev.c
+++ b/net/8021q/vlan_dev.c
@@ -872,7 +872,7 @@ static int vlan_ethtool_set_tso(struct net_device *dev, u32 data)
 	} else {
 		dev->features &= ~NETIF_F_TSO;
 	}
-	return 0;
+	return 1;
 }
 
 static const struct ethtool_ops vlan_ethtool_ops = {
@@ -881,7 +881,7 @@ static const struct ethtool_ops vlan_ethtool_ops = {
 	.get_link		= ethtool_op_get_link,
 	.get_rx_csum		= vlan_ethtool_get_rx_csum,
 	.get_flags		= vlan_ethtool_get_flags,
-	.set_tso                = vlan_ethtool_set_tso,
+	.hw_set_tso             = vlan_ethtool_set_tso,
 };
 
 static const struct net_device_ops vlan_netdev_ops = {
@@ -992,6 +992,7 @@ void vlan_setup(struct net_device *dev)
 
 	dev->netdev_ops		= &vlan_netdev_ops;
 	dev->destructor		= free_netdev;
+	dev->hw_features	= NETIF_F_ALL_TSO;
 	dev->ethtool_ops	= &vlan_ethtool_ops;
 
 	memset(dev->broadcast, 0, ETH_ALEN);
diff --git a/net/bridge/br_device.c b/net/bridge/br_device.c
index 3d12ebc..dbda588 100644
--- a/net/bridge/br_device.c
+++ b/net/bridge/br_device.c
@@ -196,7 +196,7 @@ static int br_set_tso(struct net_device *dev, u32 data)
 		br->feature_mask &= ~NETIF_F_TSO;
 
 	br_features_recompute(br);
-	return 0;
+	return 1;
 }
 
 static int br_set_tx_csum(struct net_device *dev, u32 data)
@@ -303,8 +303,7 @@ static const struct ethtool_ops br_ethtool_ops = {
 	.get_tx_csum	= ethtool_op_get_tx_csum,
 	.set_tx_csum 	= br_set_tx_csum,
 	.hw_set_sg	= br_set_sg,
-	.get_tso	= ethtool_op_get_tso,
-	.set_tso	= br_set_tso,
+	.hw_set_tso	= br_set_tso,
 	.get_ufo	= ethtool_op_get_ufo,
 	.set_ufo	= ethtool_op_set_ufo,
 	.get_flags	= ethtool_op_get_flags,
@@ -342,7 +341,7 @@ void br_dev_setup(struct net_device *dev)
 
 	dev->netdev_ops = &br_netdev_ops;
 	dev->destructor = br_dev_free;
-	dev->hw_features = NETIF_F_SG;
+	dev->hw_features |= NETIF_F_SG|NETIF_F_ALL_TSO;
 	SET_ETHTOOL_OPS(dev, &br_ethtool_ops);
 	dev->tx_queue_len = 0;
 	dev->priv_flags = IFF_EBRIDGE;
diff --git a/net/core/ethtool.c b/net/core/ethtool.c
index 017667c..9b0e598 100644
--- a/net/core/ethtool.c
+++ b/net/core/ethtool.c
@@ -78,23 +78,6 @@ int ethtool_op_set_tx_ipv6_csum(struct net_device *dev, u32 data)
 }
 EXPORT_SYMBOL(ethtool_op_set_tx_ipv6_csum);
 
-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;
@@ -1065,10 +1048,13 @@ static int __ethtool_set_sg(struct net_device *dev, u32 data)
 {
 	int err;
 
-	if (!data && dev->ethtool_ops->set_tso) {
-		err = dev->ethtool_ops->set_tso(dev, 0);
-		if (err)
-			return err;
+	if (!data && (dev->hw_features & NETIF_F_ALL_TSO)) {
+		if (dev->ethtool_ops->hw_set_tso) {
+			err = dev->ethtool_ops->hw_set_tso(dev, 0);
+			if (err < 0)
+				return err;
+		}
+		dev->features &= dev->hw_features & NETIF_F_ALL_TSO;
 	}
 
 	if (!data && dev->ethtool_ops->set_ufo) {
@@ -1145,11 +1131,16 @@ static int ethtool_set_sg(struct net_device *dev, char __user *useraddr)
 	return __ethtool_set_sg(dev, edata.data);
 }
 
+static u32 ethtool_get_tso(struct net_device *dev)
+{
+	return (dev->features & NETIF_F_ALL_TSO) != 0;
+}
+
 static int ethtool_set_tso(struct net_device *dev, char __user *useraddr)
 {
 	struct ethtool_value edata;
 
-	if (!dev->ethtool_ops->set_tso)
+	if (!(dev->hw_features & NETIF_F_ALL_TSO))
 		return -EOPNOTSUPP;
 
 	if (copy_from_user(&edata, useraddr, sizeof(edata)))
@@ -1158,7 +1149,18 @@ static int ethtool_set_tso(struct net_device *dev, char __user *useraddr)
 	if (edata.data && !(dev->features & NETIF_F_SG))
 		return -EINVAL;
 
-	return dev->ethtool_ops->set_tso(dev, edata.data);
+	if (dev->ethtool_ops->hw_set_tso) {
+		int err = dev->ethtool_ops->hw_set_tso(dev, edata.data);
+		if (err)
+			return min(err, 0);
+	}
+
+	if (edata.data)
+		dev->features |= dev->hw_features & NETIF_F_ALL_TSO;
+	else
+		dev->features &= ~NETIF_F_ALL_TSO;
+
+	return 0;
 }
 
 static int ethtool_set_ufo(struct net_device *dev, char __user *useraddr)
@@ -1582,9 +1584,7 @@ int dev_ethtool(struct net *net, struct ifreq *ifr)
 		break;
 	case ETHTOOL_GTSO:
 		rc = ethtool_get_value(dev, useraddr, ethcmd,
-				       (dev->ethtool_ops->get_tso ?
-					dev->ethtool_ops->get_tso :
-					ethtool_op_get_tso));
+					ethtool_get_tso);
 		break;
 	case ETHTOOL_STSO:
 		rc = ethtool_set_tso(dev, useraddr);
-- 
1.7.1


^ permalink raw reply related

* [PATCH 1/4] Ethtool: Introduce hw_features field in struct netdevice
From: Michał Mirosław @ 2010-10-30  4:27 UTC (permalink / raw)
  To: netdev
  Cc: e1000-devel, Steve Glendinning, Greg Kroah-Hartman, Rasesh Mody,
	Debashis Dutt, Kristoffer Glembo, linux-driver, linux-net-drivers
In-Reply-To: <cover.1288496404.git.mirq-linux@rere.qmqm.pl>


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

diff --git a/include/linux/netdevice.h b/include/linux/netdevice.h
index 072652d..f11a5a1 100644
--- a/include/linux/netdevice.h
+++ b/include/linux/netdevice.h
@@ -884,6 +884,8 @@ struct net_device {
 #define NETIF_F_ONE_FOR_ALL	(NETIF_F_GSO_SOFTWARE | NETIF_F_GSO_ROBUST | \
 				 NETIF_F_SG | NETIF_F_HIGHDMA |		\
 				 NETIF_F_FRAGLIST)
+	/* ethtool-toggable features */
+	unsigned long		hw_features;
 
 	/* Interface index. Unique device identifier	*/
 	int			ifindex;
-- 
1.7.1


^ permalink raw reply related


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