diff -Nuarp linux-2.5.31-e1000-6/drivers/net/Config.in linux-2.5.31-e1000-7/drivers/net/Config.in
--- linux-2.5.31-e1000-6/drivers/net/Config.in	Fri Aug 23 07:11:13 2002
+++ linux-2.5.31-e1000-7/drivers/net/Config.in	Fri Aug 23 07:57:26 2002
@@ -226,6 +226,9 @@ if [ "$CONFIG_ACENIC" != "n" ]; then
 fi
 dep_tristate 'D-Link DL2000-based Gigabit Ethernet support' CONFIG_DL2K $CONFIG_PCI
 dep_tristate 'Intel(R) PRO/1000 Gigabit Ethernet support' CONFIG_E1000 $CONFIG_PCI
+if [ "$CONFIG_E1000" != "n" ]; then
+   bool '  Use TCP Segmentation Offloading (TSO) (EXPERIMENTAL)' CONFIG_E1000_TSO
+fi
 dep_tristate 'MyriCOM Gigabit Ethernet support' CONFIG_MYRI_SBUS $CONFIG_SBUS
 dep_tristate 'National Semiconduct DP83820 support' CONFIG_NS83820 $CONFIG_PCI
 dep_tristate 'Packet Engines Hamachi GNIC-II support' CONFIG_HAMACHI $CONFIG_PCI
diff -Nuarp linux-2.5.31-e1000-6/drivers/net/e1000/e1000.h linux-2.5.31-e1000-7/drivers/net/e1000/e1000.h
--- linux-2.5.31-e1000-6/drivers/net/e1000/e1000.h	Fri Aug 23 07:12:32 2002
+++ linux-2.5.31-e1000-7/drivers/net/e1000/e1000.h	Fri Aug 23 07:36:00 2002
@@ -64,6 +64,9 @@
 #include <linux/list.h>
 #include <linux/reboot.h>
 #include <linux/tqueue.h>
+#ifdef CONFIG_E1000_TSO
+#include <net/checksum.h>
+#endif
 #include <linux/ethtool.h>
 #include <linux/if_vlan.h>
 
diff -Nuarp linux-2.5.31-e1000-6/drivers/net/e1000/e1000_main.c linux-2.5.31-e1000-7/drivers/net/e1000/e1000_main.c
--- linux-2.5.31-e1000-6/drivers/net/e1000/e1000_main.c	Fri Aug 23 07:12:32 2002
+++ linux-2.5.31-e1000-7/drivers/net/e1000/e1000_main.c	Fri Aug 23 07:52:15 2002
@@ -425,6 +425,13 @@ e1000_probe(struct pci_dev *pdev,
 		netdev->features = NETIF_F_SG;
 	}
 
+#ifdef CONFIG_E1000_TSO
+#ifdef NETIF_F_TSO
+	if(adapter->hw.mac_type >= e1000_82544)
+		netdev->features |= NETIF_F_TSO;
+#endif
+#endif
+
 	if(pci_using_dac)
 		netdev->features |= NETIF_F_HIGHDMA;
 
@@ -1276,9 +1283,65 @@ e1000_watchdog(unsigned long data)
 
 #define E1000_TX_FLAGS_CSUM		0x00000001
 #define E1000_TX_FLAGS_VLAN		0x00000002
+#ifdef CONFIG_E1000_TSO
+#define E1000_TX_FLAGS_TSO		0x00000004
+#endif
 #define E1000_TX_FLAGS_VLAN_MASK	0xffff0000
 #define E1000_TX_FLAGS_VLAN_SHIFT	16
 
+#ifdef CONFIG_E1000_TSO
+static inline boolean_t
+e1000_tso(struct e1000_adapter *adapter, struct sk_buff *skb, int tx_flags) { 
+#ifdef NETIF_F_TSO
+	struct e1000_context_desc *context_desc;
+	int i;
+	uint8_t ipcss, ipcso, tucss, tucso, hdr_len;
+	uint16_t ipcse, tucse, mss;
+	
+	if(skb_shinfo(skb)->tso_size) {
+		hdr_len = ((skb->h.raw - skb->data) + (skb->h.th->doff << 2));
+		mss = skb_shinfo(skb)->tso_size;
+		skb->nh.iph->tot_len = 0;
+		skb->nh.iph->check = 0;
+		skb->h.th->check = ~csum_tcpudp_magic(skb->nh.iph->saddr,
+		                                      skb->nh.iph->daddr,
+		                                      0,
+		                                      IPPROTO_TCP,
+		                                      0);
+		ipcss = skb->nh.raw - skb->data;
+		ipcso = (void *)&(skb->nh.iph->check) - (void *)skb->data;
+		ipcse = skb->h.raw - skb->data - 1;
+		tucss = skb->h.raw - skb->data;
+		tucso = (void *)&(skb->h.th->check) - (void *)skb->data;
+		tucse = 0;
+
+		i = adapter->tx_ring.next_to_use;
+		context_desc = E1000_CONTEXT_DESC(adapter->tx_ring, i);
+		
+		context_desc->lower_setup.ip_fields.ipcss  = ipcss;
+		context_desc->lower_setup.ip_fields.ipcso  = ipcso;
+		context_desc->lower_setup.ip_fields.ipcse  = cpu_to_le16(ipcse);
+		context_desc->upper_setup.tcp_fields.tucss = tucss;
+		context_desc->upper_setup.tcp_fields.tucso = tucso;
+		context_desc->upper_setup.tcp_fields.tucse = cpu_to_le16(tucse);
+		context_desc->tcp_seg_setup.fields.mss     = cpu_to_le16(mss);
+		context_desc->tcp_seg_setup.fields.hdr_len = hdr_len;
+		context_desc->cmd_and_length = cpu_to_le32(adapter->txd_cmd |
+			E1000_TXD_CMD_DEXT | E1000_TXD_CMD_TSE |
+			E1000_TXD_CMD_IP | E1000_TXD_CMD_TCP |
+			(skb->len - (hdr_len)));
+
+		i = (i + 1) % adapter->tx_ring.count;
+		adapter->tx_ring.next_to_use = i;
+
+		return TRUE;
+	}
+#endif
+	
+	return FALSE;
+}
+#endif
+
 static inline boolean_t
 e1000_tx_csum(struct e1000_adapter *adapter, struct sk_buff *skb)
 {
@@ -1378,6 +1441,14 @@ e1000_tx_queue(struct e1000_adapter *ada
 	txd_upper = 0;
 	txd_lower = adapter->txd_cmd;
 
+#ifdef CONFIG_E1000_TSO
+	if(tx_flags & E1000_TX_FLAGS_TSO) {
+		txd_lower |= E1000_TXD_CMD_DEXT | E1000_TXD_DTYP_D |
+		             E1000_TXD_CMD_TSE;
+		txd_upper |= (E1000_TXD_POPTS_IXSM | E1000_TXD_POPTS_TXSM) << 8;
+	}
+#endif
+
 	if(tx_flags & E1000_TX_FLAGS_CSUM) {
 		txd_lower |= E1000_TXD_CMD_DEXT | E1000_TXD_DTYP_D;
 		txd_upper |= E1000_TXD_POPTS_TXSM << 8;
@@ -1427,22 +1498,41 @@ e1000_xmit_frame(struct sk_buff *skb, st
 	for(f = 0; f < skb_shinfo(skb)->nr_frags; f++)
 		count += TXD_USE_COUNT(skb_shinfo(skb)->frags[f].size,
 		                       adapter->max_data_per_txd);
+#ifdef CONFIG_E1000_TSO
+#ifdef NETIF_F_TSO
+	if((skb_shinfo(skb)->tso_size) || (skb->ip_summed == CHECKSUM_HW))
+		count++;
+#else
+	if(skb->ip_summed == CHECKSUM_HW)
+		count++;
+#endif
+#else
 	if(skb->ip_summed == CHECKSUM_HW)
 		count++;
+#endif
 
 	if(E1000_DESC_UNUSED(&adapter->tx_ring) < count) {
 		netif_stop_queue(netdev);
 		return 1;
 	}
 
+#ifndef CONFIG_E1000_TSO
 	if(e1000_tx_csum(adapter, skb))
 		tx_flags |= E1000_TX_FLAGS_CSUM;
+#endif
 
 	if(adapter->vlgrp && vlan_tx_tag_present(skb)) {
 		tx_flags |= E1000_TX_FLAGS_VLAN;
 		tx_flags |= (vlan_tx_tag_get(skb) << E1000_TX_FLAGS_VLAN_SHIFT);
 	}
 
+#ifdef CONFIG_E1000_TSO
+	if(e1000_tso(adapter, skb, tx_flags))
+		tx_flags |= E1000_TX_FLAGS_TSO;
+	else if(e1000_tx_csum(adapter, skb))
+		tx_flags |= E1000_TX_FLAGS_CSUM;
+#endif
+
 	count = e1000_tx_map(adapter, skb);
 
 	e1000_tx_queue(adapter, count, tx_flags);
diff -Nuarp linux-2.5.31-e1000-6/drivers/net/e1000/e1000_proc.c linux-2.5.31-e1000-7/drivers/net/e1000/e1000_proc.c
--- linux-2.5.31-e1000-6/drivers/net/e1000/e1000_proc.c	Fri Aug 23 07:11:13 2002
+++ linux-2.5.31-e1000-7/drivers/net/e1000/e1000_proc.c	Fri Aug 23 07:53:59 2002
@@ -622,9 +622,18 @@ e1000_proc_list_setup(struct e1000_adapt
 	LIST_ADD_U("Rx_Long_Length_Errors", &adapter->stats.roc);
 	LIST_ADD_U("Rx_Short_Length_Errors", &adapter->stats.ruc);
 	
+#ifdef CONFIG_E1000_TSO
+	/* The 82542 does not have some of these stats */
+	if(adapter->hw.mac_type >= e1000_82543) {
+ 		LIST_ADD_U("Rx_Align_Errors", &adapter->stats.algnerrc);
+		LIST_ADD_U("Tx_TCP_Seg_Good", &adapter->stats.tsctc);
+		LIST_ADD_U("Tx_TCP_Seg_Failed", &adapter->stats.tsctfc);
+	}
+#else
 	/* The 82542 does not have an alignment error count register */
 	if(adapter->hw.mac_type >= e1000_82543)
 		LIST_ADD_U("Rx_Align_Errors", &adapter->stats.algnerrc);
+#endif
 	
 	LIST_ADD_U("Rx_Flow_Control_XON", &adapter->stats.xonrxc);
 	LIST_ADD_U("Rx_Flow_Control_XOFF", &adapter->stats.xoffrxc);
