From: Francois Romieu <romieu@fr.zoreil.com>

TSO support. Suggestion of Jeff Garzik.

Signed-off-by: Francois Romieu <romieu@fr.zoreil.com>
Signed-off-by: Andrew Morton <akpm@osdl.org>
---

 25-akpm/drivers/net/r8169.c |   17 ++++++++++++++---
 1 files changed, 14 insertions(+), 3 deletions(-)

diff -puN drivers/net/r8169.c~r8169-tso-support drivers/net/r8169.c
--- 25/drivers/net/r8169.c~r8169-tso-support	Thu Sep  9 16:08:47 2004
+++ 25-akpm/drivers/net/r8169.c	Thu Sep  9 16:08:47 2004
@@ -323,6 +323,9 @@ enum _DescStatusBit {
 	LastFrag	= (1 << 28), /* Final segment of a packet */
 
 	/* Tx private */
+	LargeSend	= (1 << 27), /* TCP Large Send Offload (TSO) */
+	MSSShift	= 16,        /* MSS value position */
+	MSSMask		= 0xfff,     /* MSS value + LargeSend bit: 12 bits */
 	IPCS		= (1 << 18), /* Calculate IP checksum */
 	UDPCS		= (1 << 17), /* Calculate UDP/IP checksum */
 	TCPCS		= (1 << 16), /* Calculate TCP/IP checksum */
@@ -844,6 +847,8 @@ static struct ethtool_ops rtl8169_ethtoo
 	.set_tx_csum		= ethtool_op_set_tx_csum,
 	.get_sg			= ethtool_op_get_sg,
 	.set_sg			= ethtool_op_set_sg,
+	.get_tso		= ethtool_op_get_tso,
+	.set_tso		= ethtool_op_set_tso,
 	.get_regs		= rtl8169_get_regs,
 };
 
@@ -1745,8 +1750,14 @@ static int rtl8169_xmit_frags(struct rtl
 	return cur_frag;
 }
 
-static inline u32 rtl8169_tx_csum(struct sk_buff *skb)
+static inline u32 rtl8169_tso_csum(struct sk_buff *skb, struct net_device *dev)
 {
+	if (dev->features & NETIF_F_TSO) {
+		u32 mss = skb_shinfo(skb)->tso_size;
+
+		if (mss)
+			return LargeSend | ((mss & MSSMask) << MSSShift);
+	}
 	if (skb->ip_summed == CHECKSUM_HW) {
 		const struct iphdr *ip = skb->nh.iph;
 
@@ -1754,7 +1765,7 @@ static inline u32 rtl8169_tx_csum(struct
 			return IPCS | TCPCS;
 		else if (ip->protocol == IPPROTO_UDP)
 			return IPCS | UDPCS;
-		BUG();
+		WARN_ON(1);	/* we need a WARN() */
 	}
 	return 0;
 }
@@ -1779,7 +1790,7 @@ static int rtl8169_start_xmit(struct sk_
 	if (unlikely(le32_to_cpu(txd->opts1) & DescOwn))
 		goto err_stop;
 
-	opts1 = DescOwn | rtl8169_tx_csum(skb);
+	opts1 = DescOwn | rtl8169_tso_csum(skb, dev);
 
 	frags = rtl8169_xmit_frags(tp, skb, opts1);
 	if (frags) {
_